Commit 9588b95a0849cb4c9e344b3791a76af7df0aaf80

Authored by bellard
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 267 env->hflags = (env->hflags & ~HF_PE_MASK) | (pe_state << HF_PE_SHIFT);
268 268 /* ensure that ADDSEG is always set in real mode */
269 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 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 479 return paddr;
477 480 }
478 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
... ...