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 |