Changeset 40242 in vbox
- Timestamp:
- Feb 23, 2012 9:58:44 PM (13 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r40239 r40242 3400 3400 3401 3401 /** 3402 * Pushes a FPU result onto the FPU stack if no pending exception prevents it. 3402 * Updates FSW and pushes a FPU result onto the FPU stack if no pending 3403 * exception prevents it. 3403 3404 * 3404 3405 * @param pIemCpu The IEM per CPU data. … … 3408 3409 static void iemFpuMaybePushResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult, PCPUMCTX pCtx) 3409 3410 { 3410 /* Check pending exceptions. */ 3411 uint16_t uFSW = pCtx->fpu.FSW; 3412 if ( (pCtx->fpu.FSW & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE)) 3411 /* Update FSW and bail if there are pending exceptions afterwards. */ 3412 uint16_t fFsw = pCtx->fpu.FSW & ~X86_FSW_C_MASK; 3413 fFsw |= pResult->FSW & ~X86_FSW_TOP_MASK; 3414 if ( (fFsw & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE)) 3413 3415 & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_ZM | X86_FCW_DM))) 3416 { 3417 pCtx->fpu.FSW = fFsw; 3414 3418 return; 3415 3416 uint16_t iNewTop = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + 7) & X86_FSW_TOP_SMASK; 3419 } 3420 3421 uint16_t iNewTop = (X86_FSW_TOP_GET(fFsw) + 7) & X86_FSW_TOP_SMASK; 3417 3422 if (!(pCtx->fpu.FTW & RT_BIT(iNewTop))) 3418 3423 { 3419 3424 /* All is fine, push the actual value. */ 3420 3425 pCtx->fpu.FTW |= RT_BIT(iNewTop); 3421 pCtx->fpu.FSW &= ~(X86_FSW_TOP_MASK | X86_FSW_C_MASK);3422 pCtx->fpu.FSW |= pResult->FSW & ~X86_FSW_TOP_MASK;3423 pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT;3424 3426 pCtx->fpu.aRegs[7].r80 = pResult->r80Result; 3425 3427 } … … 3427 3429 { 3428 3430 /* Masked stack overflow, push QNaN. */ 3429 pCtx->fpu.FSW &= ~(X86_FSW_TOP_MASK | X86_FSW_C_MASK); 3430 pCtx->fpu.FSW |= pResult->FSW & ~X86_FSW_TOP_MASK; 3431 pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1; 3432 pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT; 3431 fFsw |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1; 3433 3432 iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80); 3434 3433 } … … 3440 3439 return; 3441 3440 } 3441 3442 fFsw &= ~X86_FSW_TOP_MASK; 3443 fFsw |= iNewTop << X86_FSW_TOP_SHIFT; 3444 pCtx->fpu.FSW = fFsw; 3442 3445 3443 3446 iemFpuRotateStackPush(pCtx); … … 3535 3538 iemFpuUpdateOpcodeAndIpWorker(pIemCpu, pCtx); 3536 3539 iemFpuMaybePushResult(pIemCpu, pResult, pCtx); 3540 } 3541 3542 3543 /** 3544 * Replace ST0 with the first value and push the second onto the FPU stack, 3545 * unless a pending exception prevents it. 3546 * 3547 * @param pIemCpu The IEM per CPU data. 3548 * @param pResult The FPU operation result to store and push. 3549 */ 3550 static void iemFpuPushResultTwo(PIEMCPU pIemCpu, PIEMFPURESULTTWO pResult) 3551 { 3552 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 3553 iemFpuUpdateOpcodeAndIpWorker(pIemCpu, pCtx); 3554 3555 /* Update FSW and bail if there are pending exceptions afterwards. */ 3556 uint16_t fFsw = pCtx->fpu.FSW & ~X86_FSW_C_MASK; 3557 fFsw |= pResult->FSW & ~X86_FSW_TOP_MASK; 3558 if ( (fFsw & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE)) 3559 & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_ZM | X86_FCW_DM))) 3560 { 3561 pCtx->fpu.FSW = fFsw; 3562 return; 3563 } 3564 3565 uint16_t iNewTop = (X86_FSW_TOP_GET(fFsw) + 7) & X86_FSW_TOP_SMASK; 3566 if (!(pCtx->fpu.FTW & RT_BIT(iNewTop))) 3567 { 3568 /* All is fine, push the actual value. */ 3569 pCtx->fpu.FTW |= RT_BIT(iNewTop); 3570 pCtx->fpu.aRegs[0].r80 = pResult->r80Result1; 3571 pCtx->fpu.aRegs[7].r80 = pResult->r80Result2; 3572 } 3573 else if (pCtx->fpu.FCW & X86_FCW_IM) 3574 { 3575 /* Masked stack overflow, push QNaN. */ 3576 fFsw |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1; 3577 iemFpuStoreQNan(&pCtx->fpu.aRegs[0].r80); 3578 iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80); 3579 } 3580 else 3581 { 3582 /* Raise stack overflow, don't push anything. */ 3583 pCtx->fpu.FSW |= pResult->FSW & ~X86_FSW_C_MASK; 3584 pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF | X86_FSW_C1 | X86_FSW_B | X86_FSW_ES; 3585 return; 3586 } 3587 3588 fFsw &= ~X86_FSW_TOP_MASK; 3589 fFsw |= iNewTop << X86_FSW_TOP_SHIFT; 3590 pCtx->fpu.FSW = fFsw; 3591 3592 iemFpuRotateStackPush(pCtx); 3537 3593 } 3538 3594 … … 3780 3836 pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT; 3781 3837 pCtx->fpu.FTW |= RT_BIT(iNewTop); 3838 iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80); 3839 iemFpuRotateStackPush(pCtx); 3840 } 3841 else 3842 { 3843 /* Exception pending - don't change TOP or the register stack. */ 3844 pCtx->fpu.FSW &= ~X86_FSW_C_MASK; 3845 pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B; 3846 } 3847 } 3848 3849 3850 DECL_NO_INLINE(static, void) 3851 iemFpuStackPushUnderflowTwo(PIEMCPU pIemCpu) 3852 { 3853 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 3854 iemFpuUpdateOpcodeAndIpWorker(pIemCpu, pCtx); 3855 3856 if (pCtx->fpu.FCW & X86_FCW_IM) 3857 { 3858 /* Masked overflow - Push QNaN. */ 3859 uint16_t iNewTop = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + 7) & X86_FSW_TOP_SMASK; 3860 pCtx->fpu.FSW &= ~(X86_FSW_TOP_MASK | X86_FSW_C_MASK); 3861 pCtx->fpu.FSW |= X86_FSW_IE | X86_FSW_SF; 3862 pCtx->fpu.FSW |= iNewTop << X86_FSW_TOP_SHIFT; 3863 pCtx->fpu.FTW |= RT_BIT(iNewTop); 3864 iemFpuStoreQNan(&pCtx->fpu.aRegs[0].r80); 3782 3865 iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80); 3783 3866 iemFpuRotateStackPush(pCtx); … … 6184 6267 iemFpuPushResultWithMemOp(pIemCpu, &a_FpuData, a_iEffSeg, a_GCPtrEff) 6185 6268 6269 /** Replaces ST0 with value one and pushes value 2 onto the FPU stack. */ 6270 #define IEM_MC_PUSH_FPU_RESULT_TWO(a_FpuDataTwo) \ 6271 iemFpuPushResultTwo(pIemCpu, &a_FpuDataTwo) 6272 6186 6273 /** Stores FPU result in a stack register. */ 6187 6274 #define IEM_MC_STORE_FPU_RESULT(a_FpuData, a_iStReg) \ … … 6235 6322 #define IEM_MC_FPU_STACK_PUSH_UNDERFLOW() \ 6236 6323 iemFpuStackPushUnderflow(pIemCpu) 6324 /** Raises a FPU stack underflow exception for an instruction pushing a result 6325 * value onto the stack and replacing ST0. Sets FPUIP, FPUCS and FOP. */ 6326 #define IEM_MC_FPU_STACK_PUSH_UNDERFLOW_TWO() \ 6327 iemFpuStackPushUnderflowTwo(pIemCpu) 6237 6328 6238 6329 /** Raises a FPU stack overflow exception as part of a push attempt. Sets -
trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm
r40239 r40242 1315 1315 1316 1316 ;; 1317 ; Need to move this as well somewhere better? 1318 ; 1319 struc IEMFPURESULTTWO 1320 .r80Result1 resw 5 1321 .FSW resw 1 1322 .r80Result2 resw 5 1323 endstruc 1324 1325 1326 ;; 1317 1327 ; Converts a 80-bit floating point value to a 32-bit signed integer. 1318 1328 ; … … 1696 1706 IEMIMPL_FPU_R80 fchs 1697 1707 IEMIMPL_FPU_R80 fabs 1708 IEMIMPL_FPU_R80 f2xm1 1709 IEMIMPL_FPU_R80 fyl2x 1698 1710 1699 1711 … … 1766 1778 IEMIMPL_FPU_R80_CONST fldz 1767 1779 1780 1781 ;; 1782 ; FPU instruction working on one 80-bit floating point value, outputing two. 1783 ; 1784 ; @param 1 The instruction 1785 ; 1786 ; @param A0 FPU context (fxsave). 1787 ; @param A1 Pointer to a IEMFPURESULTTWO for the output. 1788 ; @param A2 Pointer to the 80-bit value. 1789 ; 1790 BEGINPROC_FASTCALL iemAImpl_fptan_r80_r80, 12 1791 PROLOGUE_3_ARGS 1792 sub xSP, 20h 1793 1794 fninit 1795 fld tword [A2] 1796 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0 1797 fptan 1798 1799 fnstsw word [A1 + IEMFPURESULTTWO.FSW] 1800 fnclex 1801 fstp tword [A1 + IEMFPURESULTTWO.r80Result2] 1802 fnclex 1803 fstp tword [A1 + IEMFPURESULTTWO.r80Result1] 1804 1805 fninit 1806 add xSP, 20h 1807 EPILOGUE_3_ARGS 4 1808 ENDPROC iemAImpl_fptan_r80_r80 1809 -
trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
r40239 r40242 11052 11052 11053 11053 /** Opcode 0xd9 0xf0. */ 11054 FNIEMOP_STUB(iemOp_f2xm1); 11054 FNIEMOP_DEF(iemOp_f2xm1) 11055 { 11056 IEMOP_MNEMONIC("f2xm1 st0"); 11057 return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_f2xm1_r80); 11058 } 11059 11055 11060 11056 11061 /** Opcode 0xd9 0xf1. */ 11057 FNIEMOP_STUB(iemOp_fylx2); 11062 FNIEMOP_DEF(iemOp_fylx2) 11063 { 11064 IEMOP_MNEMONIC("fylx2 st0"); 11065 return FNIEMOP_CALL_1(iemOpHlpFpu_st0, iemAImpl_fylx2_r80); 11066 } 11067 11058 11068 11059 11069 /** Opcode 0xd9 0xf2. */ 11060 FNIEMOP_STUB(iemOp_fptan); 11070 FNIEMOP_DEF(iemOp_fptan) 11071 { 11072 IEMOP_MNEMONIC("fptan st0"); 11073 IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX(); 11074 11075 IEM_MC_BEGIN(2, 1); 11076 IEM_MC_LOCAL(IEMFPURESULTTWO, FpuResTwo); 11077 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULTTWO, pFpuResTwo, FpuResTwo, 0); 11078 IEM_MC_ARG(PCRTFLOAT80U, pr80Value, 1); 11079 11080 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE(); 11081 IEM_MC_MAYBE_RAISE_FPU_XCPT(); 11082 IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(pr80Value, 0) 11083 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fptan_r80_r80, pFpuResTwo, pr80Value); 11084 IEM_MC_PUSH_FPU_RESULT_TWO(FpuResTwo); 11085 IEM_MC_ELSE() 11086 IEM_MC_FPU_STACK_PUSH_UNDERFLOW_TWO(); 11087 IEM_MC_ENDIF(); 11088 IEM_MC_ADVANCE_RIP(); 11089 11090 IEM_MC_END(); 11091 return VINF_SUCCESS; 11092 11093 } 11061 11094 11062 11095 /** Opcode 0xd9 0xf3. */ -
trunk/src/VBox/VMM/include/IEMInternal.h
r40239 r40242 99 99 /** Pointer to a const FPU result. */ 100 100 typedef IEMFPURESULT const *PCIEMFPURESULT; 101 102 103 /** 104 * A FPU result consisting of two output values and FSW. 105 */ 106 typedef struct IEMFPURESULTTWO 107 { 108 /** The first output value. */ 109 RTFLOAT80U r80Result1; 110 /** The output status. */ 111 uint16_t FSW; 112 /** The second output value. */ 113 RTFLOAT80U r80Result2; 114 } IEMFPURESULTTWO; 115 AssertCompileMemberOffset(IEMFPURESULTTWO, FSW, 10); 116 AssertCompileMemberOffset(IEMFPURESULTTWO, r80Result2, 12); 117 /** Pointer to a FPU result consisting of two output values and FSW. */ 118 typedef IEMFPURESULTTWO *PIEMFPURESULTTWO; 119 /** Pointer to a const FPU result consisting of two output values and FSW. */ 120 typedef IEMFPURESULTTWO const *PCIEMFPURESULTTWO; 101 121 102 122 … … 789 809 FNIEMAIMPLFPUR80UNARY iemAImpl_fabs_r80; 790 810 FNIEMAIMPLFPUR80UNARY iemAImpl_fchs_r80; 811 FNIEMAIMPLFPUR80UNARY iemAImpl_f2xm1_r80; 812 FNIEMAIMPLFPUR80UNARY iemAImpl_fylx2_r80; 791 813 792 814 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPUR80UNARYFSW,(PCX86FXSTATE pFpuState, uint16_t *pu16Fsw, PCRTFLOAT80U pr80Val)); … … 804 826 FNIEMAIMPLFPUR80LDCONST iemAImpl_fldln2; 805 827 FNIEMAIMPLFPUR80LDCONST iemAImpl_fldz; 828 829 IEM_DECL_IMPL_DEF(void, iemAImpl_fptan_r80_r80,(PCX86FXSTATE pFpuState, PIEMFPURESULTTWO pFpuResTwo, PCRTFLOAT80U pr80Val)); 830 806 831 /** @} */ 807 832 -
trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp
r40239 r40242 190 190 #define iemAImpl_ftst_r80 NULL 191 191 #define iemAImpl_fxam_r80 NULL 192 #define iemAImpl_f2xm1_r80 NULL 193 #define iemAImpl_flx2y_r80 NULL 192 194 #define iemAImpl_fld1 NULL 193 195 #define iemAImpl_fldl2t NULL … … 451 453 #define IEM_MC_PUSH_FPU_RESULT(a_FpuData) do { } while (0) 452 454 #define IEM_MC_PUSH_FPU_RESULT_MEM_OP(a_FpuData, a_iEffSeg, a_GCPtrEff) do { } while (0) 455 #define IEM_MC_PUSH_FPU_RESULT_TWO(a_FpuDataTwo) do { } while (0) 453 456 #define IEM_MC_STORE_FPU_RESULT(a_FpuData, a_iStReg) do { } while (0) 454 457 #define IEM_MC_STORE_FPU_RESULT_THEN_POP(a_FpuData, a_iStReg) do { } while (0) … … 460 463 #define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(a_iStReg, a_iEffSeg, a_GCPtrEff) do { } while (0) 461 464 #define IEM_MC_FPU_STACK_PUSH_UNDERFLOW() do { } while (0) 465 #define IEM_MC_FPU_STACK_PUSH_UNDERFLOW_TWO() do { } while (0) 462 466 #define IEM_MC_FPU_STACK_PUSH_OVERFLOW() do { } while (0) 463 467 #define IEM_MC_FPU_STACK_PUSH_OVERFLOW_MEM_OP(a_iEffSeg, a_GCPtrEff) do { } while (0) -
trunk/src/VBox/VMM/testcase/tstX86-1.cpp
r40209 r40242 255 255 RTTestFailed(hTest, "x861_Test5 -> %d", rc); 256 256 257 #endif258 257 RTTestSub(hTest, "Floating point exceptions ++"); 259 258 rc = x861_Test7(); 260 259 if (rc != 0) 261 260 RTTestFailed(hTest, "x861_Test6 -> %d", rc); 261 #endif 262 262 263 263 rc = x861_TestFPUInstr1(); -
trunk/src/VBox/VMM/testcase/tstX86-1A.asm
r40209 r40242 107 107 g_r80_QNaN: dt 07fffc000000000000000h 108 108 g_r80_QNaNMax: dt 07fffffffffffffffffffh 109 g_r80_NegQNaN: dt 0ffffc000000000000000h 109 110 g_r80_SNaN: dt 07fff8000000000000001h 110 111 g_r80_SNaNMax: dt 07fffbfffffffffffffffh … … 3063 3064 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2) 3064 3065 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1) 3065 %endif3066 3066 3067 3067 ; … … 3115 3115 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_3dot2) 3116 3116 FxSaveCheckStNValueConst xSP, 2, REF(g_r80_0dot1) 3117 %endif 3118 3119 ; 3120 ; FPTAN - calc, store ST0, push 1.0. 3121 ; 3122 SetSubTest "FPTAN" 3123 3124 ; ## Normal operation. ## 3125 fninit 3126 fldpi 3127 FpuCheckOpcodeCsIp { fptan } 3128 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_One) 3129 FxSaveCheckStNValue xSP, 1, 0x00000000, 0x80000000, 0x3fbf ; should be zero, so, this might fail due to precision later. 3130 3131 ; Masked stack underflow - two QNaNs. 3132 fninit 3133 FpuCheckOpcodeCsIp { fptan } 3134 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_NegQNaN) 3135 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_NegQNaN) 3136 3137 ; Masked stack overflow - two QNaNs 3138 fninit 3139 fldpi 3140 fldpi 3141 fldpi 3142 fldpi 3143 fldpi 3144 fldpi 3145 fldpi 3146 fldpi 3147 FpuCheckOpcodeCsIp { fptan } 3148 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_NegQNaN) 3149 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_NegQNaN) 3150 3151 ;; @todo Finish FPTAN testcase. 3152 3117 3153 3118 3154 .success:
Note:
See TracChangeset
for help on using the changeset viewer.