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 | 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 | ... | ... |