Commit 9588b95a0849cb4c9e344b3791a76af7df0aaf80
1 parent
2edcdce3
CR0.MP/EM/TS support - native fpu support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@640 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
73 additions
and
0 deletions
target-i386/helper2.c
@@ -267,6 +267,9 @@ void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0) | @@ -267,6 +267,9 @@ void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0) | ||
267 | env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT); | 267 | env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT); |
268 | /* ensure that ADDSEG is always set in real mode */ | 268 | /* ensure that ADDSEG is always set in real mode */ |
269 | env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT); | 269 | env->hflags |= ((pe_state ^ 1) << HF_ADDSEG_SHIFT); |
270 | + /* update FPU flags */ | ||
271 | + env->hflags = (env->hflags & ~(HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)) | | ||
272 | + ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)); | ||
270 | } | 273 | } |
271 | 274 | ||
272 | void cpu_x86_update_cr3(CPUX86State *env, uint32_t new_cr3) | 275 | void cpu_x86_update_cr3(CPUX86State *env, uint32_t new_cr3) |
@@ -476,3 +479,73 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) | @@ -476,3 +479,73 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) | ||
476 | return paddr; | 479 | return paddr; |
477 | } | 480 | } |
478 | #endif | 481 | #endif |
482 | + | ||
483 | +#if defined(USE_CODE_COPY) | ||
484 | +struct fpstate { | ||
485 | + uint16_t fpuc; | ||
486 | + uint16_t dummy1; | ||
487 | + uint16_t fpus; | ||
488 | + uint16_t dummy2; | ||
489 | + uint16_t fptag; | ||
490 | + uint16_t dummy3; | ||
491 | + | ||
492 | + uint32_t fpip; | ||
493 | + uint32_t fpcs; | ||
494 | + uint32_t fpoo; | ||
495 | + uint32_t fpos; | ||
496 | + uint8_t fpregs1[8 * 10]; | ||
497 | +}; | ||
498 | + | ||
499 | +void restore_native_fp_state(CPUState *env) | ||
500 | +{ | ||
501 | + int fptag, i, j; | ||
502 | + struct fpstate fp1, *fp = &fp1; | ||
503 | + | ||
504 | + fp->fpuc = env->fpuc; | ||
505 | + fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; | ||
506 | + fptag = 0; | ||
507 | + for (i=7; i>=0; i--) { | ||
508 | + fptag <<= 2; | ||
509 | + if (env->fptags[i]) { | ||
510 | + fptag |= 3; | ||
511 | + } else { | ||
512 | + /* the FPU automatically computes it */ | ||
513 | + } | ||
514 | + } | ||
515 | + fp->fptag = fptag; | ||
516 | + j = env->fpstt; | ||
517 | + for(i = 0;i < 8; i++) { | ||
518 | + memcpy(&fp->fpregs1[i * 10], &env->fpregs[j], 10); | ||
519 | + j = (j + 1) & 7; | ||
520 | + } | ||
521 | + asm volatile ("frstor %0" : "=m" (*fp)); | ||
522 | + env->native_fp_regs = 1; | ||
523 | +} | ||
524 | + | ||
525 | +void save_native_fp_state(CPUState *env) | ||
526 | +{ | ||
527 | + int fptag, i, j; | ||
528 | + uint16_t fpuc; | ||
529 | + struct fpstate fp1, *fp = &fp1; | ||
530 | + | ||
531 | + asm volatile ("fsave %0" : : "m" (*fp)); | ||
532 | + env->fpuc = fp->fpuc; | ||
533 | + env->fpstt = (fp->fpus >> 11) & 7; | ||
534 | + env->fpus = fp->fpus & ~0x3800; | ||
535 | + fptag = fp->fptag; | ||
536 | + for(i = 0;i < 8; i++) { | ||
537 | + env->fptags[i] = ((fptag & 3) == 3); | ||
538 | + fptag >>= 2; | ||
539 | + } | ||
540 | + j = env->fpstt; | ||
541 | + for(i = 0;i < 8; i++) { | ||
542 | + memcpy(&env->fpregs[j], &fp->fpregs1[i * 10], 10); | ||
543 | + j = (j + 1) & 7; | ||
544 | + } | ||
545 | + /* we must restore the default rounding state */ | ||
546 | + /* XXX: we do not restore the exception state */ | ||
547 | + fpuc = 0x037f | (env->fpuc & (3 << 10)); | ||
548 | + asm volatile("fldcw %0" : : "m" (fpuc)); | ||
549 | + env->native_fp_regs = 0; | ||
550 | +} | ||
551 | +#endif |