- Timestamp:
- Feb 17, 2012 12:36:19 AM (13 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r40162 r40164 3561 3561 3562 3562 /** 3563 * Pops one item off the FPU stack if no pending exception prevents it. 3564 * 3565 * @param pCtx The CPU context. 3566 */ 3567 static void iemFpuMaybePopOne(PCPUMCTX pCtx) 3568 { 3569 /* Check pending exceptions. */ 3570 uint16_t uFSW = pCtx->fpu.FSW; 3571 if ( (pCtx->fpu.FSW & (X86_FSW_IE | X86_FSW_ZE | X86_FSW_DE)) 3572 & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_ZM | X86_FCW_DM))) 3573 return; 3574 3575 /* TOP--. */ 3576 uint16_t iOldTop = uFSW & X86_FSW_TOP_MASK; 3577 uFSW &= ~X86_FSW_TOP_MASK; 3578 uFSW |= (iOldTop + (UINT16_C(9) << X86_FSW_TOP_SHIFT)) & X86_FSW_TOP_MASK; 3579 pCtx->fpu.FSW = uFSW; 3580 3581 /* Mark the previous ST0 as empty. */ 3582 iOldTop >>= X86_FSW_TOP_SHIFT; 3583 pCtx->fpu.FTW &= ~RT_BIT(iOldTop); 3584 3585 /* Rotate the registers. */ 3586 iemFpuRotateStackPop(pCtx); 3587 } 3588 3589 3590 /** 3563 3591 * Stores a result in a FPU register, updates the FSW, FTW, FPUIP, FPUCS, and 3564 3592 * FOP. … … 3578 3606 3579 3607 /** 3580 * Stores a result in a FPU register, updates the FSW, FTW, FPUIP, FPUCS, FOP,3581 * F PUDP, and FPUDS.3608 * Stores a result in a FPU register, updates the FSW, FTW, FPUIP, FPUCS, and 3609 * FOP, and then pops the stack. 3582 3610 * 3583 3611 * @param pIemCpu The IEM per CPU data. … … 3586 3614 * @param pCtx The CPU context. 3587 3615 */ 3616 static void iemFpuStoreResultThenPop(PIEMCPU pIemCpu, PIEMFPURESULT pResult, uint8_t iStReg) 3617 { 3618 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 3619 iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx); 3620 iemFpuStoreResultOnly(pIemCpu, pResult, iStReg, pCtx); 3621 iemFpuMaybePopOne(pCtx); 3622 } 3623 3624 3625 /** 3626 * Stores a result in a FPU register, updates the FSW, FTW, FPUIP, FPUCS, FOP, 3627 * FPUDP, and FPUDS. 3628 * 3629 * @param pIemCpu The IEM per CPU data. 3630 * @param pResult The result to store. 3631 * @param iStReg Which FPU register to store it in. 3632 * @param pCtx The CPU context. 3633 */ 3588 3634 static void iemFpuStoreResultWithMemOp(PIEMCPU pIemCpu, PIEMFPURESULT pResult, uint8_t iStReg, uint8_t iEffSeg, RTGCPTR GCPtrEff) 3589 3635 { … … 3592 3638 iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx); 3593 3639 iemFpuStoreResultOnly(pIemCpu, pResult, iStReg, pCtx); 3640 } 3641 3642 3643 /** 3644 * Stores a result in a FPU register, updates the FSW, FTW, FPUIP, FPUCS, FOP, 3645 * FPUDP, and FPUDS, and then pops the stack. 3646 * 3647 * @param pIemCpu The IEM per CPU data. 3648 * @param pResult The result to store. 3649 * @param iStReg Which FPU register to store it in. 3650 * @param pCtx The CPU context. 3651 */ 3652 static void iemFpuStoreResultWithMemOpThenPop(PIEMCPU pIemCpu, PIEMFPURESULT pResult, 3653 uint8_t iStReg, uint8_t iEffSeg, RTGCPTR GCPtrEff) 3654 { 3655 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 3656 iemFpuUpdateDP(pIemCpu, pIemCpu->CTX_SUFF(pCtx), iEffSeg, GCPtrEff); 3657 iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx); 3658 iemFpuStoreResultOnly(pIemCpu, pResult, iStReg, pCtx); 3659 iemFpuMaybePopOne(pCtx); 3594 3660 } 3595 3661 … … 3631 3697 } 3632 3698 3699 3700 DECL_NO_INLINE(static, void) iemFpuStackUnderflowThenPop(PIEMCPU pIemCpu, uint8_t iStReg) 3701 { 3702 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 3703 iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx); 3704 iemFpuStackUnderflowOnly(pIemCpu, iStReg, pCtx); 3705 iemFpuMaybePopOne(pCtx); 3706 } 3707 3708 3709 DECL_NO_INLINE(static, void) 3710 iemFpuStackUnderflowWithMemOpThenPop(PIEMCPU pIemCpu, uint8_t iStReg, uint8_t iEffSeg, RTGCPTR GCPtrEff) 3711 { 3712 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 3713 iemFpuUpdateDP(pIemCpu, pIemCpu->CTX_SUFF(pCtx), iEffSeg, GCPtrEff); 3714 iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx); 3715 iemFpuStackUnderflowOnly(pIemCpu, iStReg, pCtx); 3716 iemFpuMaybePopOne(pCtx); 3717 } 3718 3719 3633 3720 static int iemFpuStRegNonEmptyRef(PIEMCPU pIemCpu, uint8_t iStReg, PCRTFLOAT80U *ppRef) 3634 3721 { … … 3638 3725 { 3639 3726 *ppRef = &pCtx->fpu.aRegs[iStReg].r80; 3727 return VINF_SUCCESS; 3728 } 3729 return VERR_NOT_FOUND; 3730 } 3731 3732 3733 static int iemFpu2StRegsNonEmptyRef(PIEMCPU pIemCpu, uint8_t iStReg0, PCRTFLOAT80U *ppRef0, 3734 uint8_t iStReg1, PCRTFLOAT80U *ppRef1) 3735 { 3736 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 3737 uint16_t iTop = X86_FSW_TOP_GET(pCtx->fpu.FSW); 3738 uint16_t iReg0 = (iTop + iStReg0) & X86_FSW_TOP_SMASK; 3739 uint16_t iReg1 = (iTop + iStReg1) & X86_FSW_TOP_SMASK; 3740 if ((pCtx->fpu.FTW & (RT_BIT(iReg0) | RT_BIT(iReg1))) == (RT_BIT(iReg0) | RT_BIT(iReg1))) 3741 { 3742 *ppRef0 = &pCtx->fpu.aRegs[iStReg0].r80; 3743 *ppRef1 = &pCtx->fpu.aRegs[iStReg1].r80; 3640 3744 return VINF_SUCCESS; 3641 3745 } … … 5812 5916 #define IEM_MC_STORE_FPU_RESULT(a_FpuData, a_iStReg) \ 5813 5917 iemFpuStoreResult(pIemCpu, &a_FpuData, a_iStReg) 5918 /** Stores FPU result in a stack register and pops the stack. */ 5919 #define IEM_MC_STORE_FPU_RESULT_THEN_POP(a_FpuData, a_iStReg) \ 5920 iemFpuStoreResultThenPop(pIemCpu, &a_FpuData, a_iStReg) 5814 5921 /** Stores FPU result in a stack register and sets the FPUDP. */ 5815 5922 #define IEM_MC_STORE_FPU_RESULT_MEM_OP(a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff) \ 5816 5923 iemFpuStoreResultWithMemOp(pIemCpu, &a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff) 5924 /** Stores FPU result in a stack register, sets the FPUDP, and pops the 5925 * stack. */ 5926 #define IEM_MC_STORE_FPU_RESULT_WITH_MEM_OP_THEN_POP(a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff) \ 5927 iemFpuStoreResultWithMemOpThenPop(pIemCpu, &a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff) 5817 5928 5818 5929 /** Raises a FPU stack underflow. Sets FPUIP, FPUCS and FOP. */ 5819 #define IEM_MC_FPU_STACK_UNDERFLOW(a_iSt) \ 5820 iemFpuStackUnderflow(pIemCpu, a_iSt) 5930 #define IEM_MC_FPU_STACK_UNDERFLOW(a_iStDst) \ 5931 iemFpuStackUnderflow(pIemCpu, a_iStDst) 5932 /** Raises a FPU stack underflow. Sets FPUIP, FPUCS and FOP. Pops stack. */ 5933 #define IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP(a_iStDst) \ 5934 iemFpuStackUnderflowThenPop(pIemCpu, a_iStDst) 5821 5935 /** Raises a FPU stack underflow. Sets FPUIP, FPUCS, FOP, FPUDP and FPUDS. */ 5822 #define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(a_iSt, a_iEffSeg, a_GCPtrEff) \ 5823 iemFpuStackUnderflowWithMemOp(pIemCpu, a_iSt, a_iEffSeg, a_GCPtrEff) 5936 #define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(a_iStDst, a_iEffSeg, a_GCPtrEff) \ 5937 iemFpuStackUnderflowWithMemOp(pIemCpu, a_iStDst, a_iEffSeg, a_GCPtrEff) 5938 /** Raises a FPU stack underflow. Sets FPUIP, FPUCS, FOP, FPUDP and FPUDS. 5939 * Pops stack. */ 5940 #define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(a_iStDst, a_iEffSeg, a_GCPtrEff) \ 5941 iemFpuStackUnderflowWithMemOpThenPop(pIemCpu, a_iStDst, a_iEffSeg, a_GCPtrEff) 5824 5942 5825 5943 … … 5867 5985 #define IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(a_pr80Dst, a_iSt) \ 5868 5986 if (iemFpuStRegNonEmptyRef(pIemCpu, (a_iSt), &(a_pr80Dst)) == VINF_SUCCESS) { 5987 #define IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(a_pr80Dst0, a_iSt0, a_pr80Dst1, a_iSt1) \ 5988 if (iemFpu2StRegsNonEmptyRef(pIemCpu, (a_iSt0), &(a_pr80Dst0), (a_iSt1), &(a_pr80Dst1)) == VINF_SUCCESS) { 5869 5989 5870 5990 #define IEM_MC_ELSE() } else { -
trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm
r40163 r40164 1375 1375 ; @param A0 FPU context (fxsave). 1376 1376 ; @param A1 Pointer to a IEMFPURESULT for the output. 1377 ; @param A2 Pointer to the 80-bit dividend.1378 ; @param A3 Pointer to the 64-bit divisor.1377 ; @param A2 Pointer to the 80-bit value. 1378 ; @param A3 Pointer to the 64-bit value. 1379 1379 ; 1380 1380 %macro IEMIMPL_FPU_R80_BY_R64 1 … … 1405 1405 IEMIMPL_FPU_R80_BY_R64 fdivr 1406 1406 1407 1408 ;; 1409 ; FPU instruction working on two 80-bit floating point values. 1410 ; 1411 ; @param 1 The instruction 1412 ; 1413 ; @param A0 FPU context (fxsave). 1414 ; @param A1 Pointer to a IEMFPURESULT for the output. 1415 ; @param A2 Pointer to the first 80-bit value. 1416 ; @param A3 Pointer to the second 80-bit value. 1417 ; 1418 %macro IEMIMPL_FPU_R80_BY_R80 1 1419 BEGINPROC_FASTCALL iemAImpl_ %+ %1 %+ _r80_by_r80, 16 1420 PROLOGUE_4_ARGS 1421 sub xSP, 20h 1422 1423 fninit 1424 fld tword [A3] 1425 fld tword [A2] 1426 FPU_LD_FXSTATE_FCW_AND_SAFE_FSW A0 1427 %1 st0, st1 1428 1429 fnstsw word [A1 + IEMFPURESULT.FSW] 1430 fnclex 1431 fstp tword [A1 + IEMFPURESULT.r80Result] 1432 1433 add xSP, 20h 1434 EPILOGUE_4_ARGS 8 1435 ENDPROC iemAImpl_ %+ %1 %+ _r80_by_r80 1436 %endmacro 1437 1438 IEMIMPL_FPU_R80_BY_R80 fadd 1439 IEMIMPL_FPU_R80_BY_R80 fmul 1440 IEMIMPL_FPU_R80_BY_R80 fsub 1441 IEMIMPL_FPU_R80_BY_R80 fsubr 1442 IEMIMPL_FPU_R80_BY_R80 fdiv 1443 IEMIMPL_FPU_R80_BY_R80 fdivr 1444 IEMIMPL_FPU_R80_BY_R80 fcom 1445 IEMIMPL_FPU_R80_BY_R80 fucom 1446 -
trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
r40163 r40164 10255 10255 10256 10256 10257 /** 10258 * Common worker for FPU instructions working on ST0 and STn, and storing the 10259 * result in ST0. 10260 * 10261 * @param pfnAImpl Pointer to the instruction implementation (assembly). 10262 */ 10263 FNIEMOP_DEF_2(iemOpHlpFpu_st0_stN, uint8_t, bRm, PFNIEMAIMPLFPUR80, pfnAImpl) 10264 { 10265 IEMOP_HLP_NO_LOCK_PREFIX(); 10266 10267 IEM_MC_BEGIN(3, 1); 10268 IEM_MC_LOCAL(IEMFPURESULT, FpuRes); 10269 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0); 10270 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1); 10271 IEM_MC_ARG(PCRTFLOAT80U, pr80Value2, 2); 10272 10273 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE(); 10274 IEM_MC_MAYBE_RAISE_FPU_XCPT(); 10275 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, 0, pr80Value2, bRm & X86_MODRM_RM_MASK) 10276 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pFpuRes, pr80Value1, pr80Value2); 10277 IEM_MC_STORE_FPU_RESULT(FpuRes, 0); 10278 IEM_MC_ELSE() 10279 IEM_MC_FPU_STACK_UNDERFLOW(0); 10280 IEM_MC_ENDIF(); 10281 IEM_MC_ADVANCE_RIP(); 10282 10283 IEM_MC_END(); 10284 return VINF_SUCCESS; 10285 } 10286 10287 10257 10288 /** Opcode 0xd8 11/0. */ 10258 FNIEMOP_STUB_1(iemOp_fadd_stN, uint8_t, bRm); 10289 FNIEMOP_DEF_1(iemOp_fadd_stN, uint8_t, bRm) 10290 { 10291 IEMOP_MNEMONIC("fadd st0,stN"); 10292 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fadd_r80_by_r80); 10293 } 10294 10259 10295 10260 10296 /** Opcode 0xd8 11/1. */ 10261 FNIEMOP_STUB_1(iemOp_fmul_stN, uint8_t, bRm); 10297 FNIEMOP_DEF_1(iemOp_fmul_stN, uint8_t, bRm) 10298 { 10299 IEMOP_MNEMONIC("fmul st0,stN"); 10300 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fmul_r80_by_r80); 10301 } 10302 10262 10303 10263 10304 /** Opcode 0xd8 11/2. */ 10264 FNIEMOP_STUB_1(iemOp_fcom_stN, uint8_t, bRm); 10305 FNIEMOP_DEF_1(iemOp_fcom_stN, uint8_t, bRm) 10306 { 10307 IEMOP_MNEMONIC(" st0,stN"); 10308 /** @todo No need to store ST0! */ 10309 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fcom_r80_by_r80); 10310 } 10311 10265 10312 10266 10313 /** Opcode 0xd8 11/3. */ … … 10268 10315 10269 10316 /** Opcode 0xd8 11/4. */ 10270 FNIEMOP_STUB_1(iemOp_fsub_stN, uint8_t, bRm); 10317 FNIEMOP_DEF_1(iemOp_fsub_stN, uint8_t, bRm) 10318 { 10319 IEMOP_MNEMONIC("fsub st0,stN"); 10320 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fsub_r80_by_r80); 10321 } 10322 10271 10323 10272 10324 /** Opcode 0xd8 11/5. */ 10273 FNIEMOP_STUB_1(iemOp_fsubr_stN, uint8_t, bRm); 10325 FNIEMOP_DEF_1(iemOp_fsubr_stN, uint8_t, bRm) 10326 { 10327 IEMOP_MNEMONIC("fsubr st0,stN"); 10328 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fsubr_r80_by_r80); 10329 } 10330 10274 10331 10275 10332 /** Opcode 0xd8 11/6. */ 10276 FNIEMOP_STUB_1(iemOp_fdiv_stN, uint8_t, bRm); 10333 FNIEMOP_DEF_1(iemOp_fdiv_stN, uint8_t, bRm) 10334 { 10335 IEMOP_MNEMONIC("fdiv st0,stN"); 10336 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fdiv_r80_by_r80); 10337 } 10338 10277 10339 10278 10340 /** Opcode 0xd8 11/7. */ 10279 FNIEMOP_STUB_1(iemOp_fdivr_stN, uint8_t, bRm); 10341 FNIEMOP_DEF_1(iemOp_fdivr_stN, uint8_t, bRm) 10342 { 10343 IEMOP_MNEMONIC("fdivr st0,stN"); 10344 return FNIEMOP_CALL_2(iemOpHlpFpu_st0_stN, bRm, iemAImpl_fdivr_r80_by_r80); 10345 } 10346 10280 10347 10281 10348 /** Opcode 0xd8 !11/0. */ … … 10811 10878 * memory operand, and storing the result in ST0. 10812 10879 * 10813 * @param p ImplPointer to the instruction implementation (assembly).10880 * @param pfnAImpl Pointer to the instruction implementation (assembly). 10814 10881 */ 10815 10882 FNIEMOP_DEF_2(iemOpHlpFpu_ST0_m64r, uint8_t, bRm, PFNIEMAIMPLFPUR64, pfnImpl) … … 11034 11101 11035 11102 11103 /** 11104 * Common worker for FPU instructions working on STn and ST0, storing the result 11105 * in STn, and poping the stack unless IE, DE or ZE was raised. 11106 * 11107 * @param pfnAImpl Pointer to the instruction implementation (assembly). 11108 */ 11109 FNIEMOP_DEF_2(iemOpHlpFpu_stN_st0_pop, uint8_t, bRm, PFNIEMAIMPLFPUR80, pfnAImpl) 11110 { 11111 IEMOP_HLP_NO_LOCK_PREFIX(); 11112 11113 IEM_MC_BEGIN(3, 1); 11114 IEM_MC_LOCAL(IEMFPURESULT, FpuRes); 11115 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0); 11116 IEM_MC_ARG(PCRTFLOAT80U, pr80Value1, 1); 11117 IEM_MC_ARG(PCRTFLOAT80U, pr80Value2, 2); 11118 11119 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE(); 11120 IEM_MC_MAYBE_RAISE_FPU_XCPT(); 11121 IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(pr80Value1, bRm & X86_MODRM_RM_MASK, pr80Value2, 0) 11122 IEM_MC_CALL_FPU_AIMPL_3(pfnAImpl, pFpuRes, pr80Value1, pr80Value2); 11123 IEM_MC_STORE_FPU_RESULT_THEN_POP(FpuRes, bRm & X86_MODRM_RM_MASK); 11124 IEM_MC_ELSE() 11125 IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP(bRm & X86_MODRM_RM_MASK); 11126 IEM_MC_ENDIF(); 11127 IEM_MC_ADVANCE_RIP(); 11128 11129 IEM_MC_END(); 11130 return VINF_SUCCESS; 11131 } 11132 11133 11036 11134 /** Opcode 0xde 11/0. */ 11037 FNIEMOP_STUB_1(iemOp_faddp_stN_st0, uint8_t, bRm); 11135 FNIEMOP_DEF_1(iemOp_faddp_stN_st0, uint8_t, bRm) 11136 { 11137 IEMOP_MNEMONIC("faddp stN,st0"); 11138 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fadd_r80_by_r80); 11139 } 11140 11038 11141 11039 11142 /** Opcode 0xde 11/0. */ 11040 FNIEMOP_STUB_1(iemOp_fmulp_stN_st0, uint8_t, bRm); 11143 FNIEMOP_DEF_1(iemOp_fmulp_stN_st0, uint8_t, bRm) 11144 { 11145 IEMOP_MNEMONIC("fmulp stN,st0"); 11146 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fmul_r80_by_r80); 11147 } 11148 11041 11149 11042 11150 /** Opcode 0xde 0xd9. */ 11043 11151 FNIEMOP_STUB(iemOp_fcompp); 11044 11152 11153 11045 11154 /** Opcode 0xde 11/4. */ 11046 FNIEMOP_STUB_1(iemOp_fsubrp_stN_st0, uint8_t, bRm); 11155 FNIEMOP_DEF_1(iemOp_fsubrp_stN_st0, uint8_t, bRm) 11156 { 11157 IEMOP_MNEMONIC("fsubrp stN,st0"); 11158 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fsubr_r80_by_r80); 11159 } 11160 11047 11161 11048 11162 /** Opcode 0xde 11/5. */ 11049 FNIEMOP_STUB_1(iemOp_fsubp_stN_st0, uint8_t, bRm); 11163 FNIEMOP_DEF_1(iemOp_fsubp_stN_st0, uint8_t, bRm) 11164 { 11165 IEMOP_MNEMONIC("fsubp stN,st0"); 11166 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fsub_r80_by_r80); 11167 } 11168 11050 11169 11051 11170 /** Opcode 0xde 11/6. */ 11052 FNIEMOP_STUB_1(iemOp_fdivrp_stN_st0, uint8_t, bRm); 11171 FNIEMOP_DEF_1(iemOp_fdivrp_stN_st0, uint8_t, bRm) 11172 { 11173 IEMOP_MNEMONIC("fdivrp stN,st0"); 11174 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fdivr_r80_by_r80); 11175 } 11176 11053 11177 11054 11178 /** Opcode 0xde 11/7. */ 11055 FNIEMOP_STUB_1(iemOp_fdivp_stN_st0, uint8_t, bRm); 11179 FNIEMOP_DEF_1(iemOp_fdivp_stN_st0, uint8_t, bRm) 11180 { 11181 IEMOP_MNEMONIC("fdivp stN,st0"); 11182 return FNIEMOP_CALL_2(iemOpHlpFpu_stN_st0_pop, bRm, iemAImpl_fdiv_r80_by_r80); 11183 } 11184 11056 11185 11057 11186 /** Opcode 0xde !11/0. */ -
trunk/src/VBox/VMM/include/IEMInternal.h
r40163 r40164 734 734 /** @} */ 735 735 736 /** @name FPU operations taking a 80-bit float argument 737 * @{ */ 738 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPUR80,(PCX86FXSTATE pFpuState, PIEMFPURESULT pFpuRes, 739 PCRTFLOAT80U pr80Val1, PCRTFLOAT80U pr80Val2)); 740 typedef FNIEMAIMPLFPUR80 *PFNIEMAIMPLFPUR80; 741 FNIEMAIMPLFPUR80 iemAImpl_fadd_r80_by_r80; 742 FNIEMAIMPLFPUR80 iemAImpl_fmul_r80_by_r80; 743 FNIEMAIMPLFPUR80 iemAImpl_fcom_r80_by_r80; 744 FNIEMAIMPLFPUR80 iemAImpl_fsub_r80_by_r80; 745 FNIEMAIMPLFPUR80 iemAImpl_fsubr_r80_by_r80; 746 FNIEMAIMPLFPUR80 iemAImpl_fdiv_r80_by_r80; 747 FNIEMAIMPLFPUR80 iemAImpl_fdivr_r80_by_r80; 748 749 /** @} */ 750 736 751 737 752 /** @name Function tables. -
trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp
r40163 r40164 405 405 #define IEM_MC_PUSH_FPU_RESULT_MEM_OP(a_FpuData, a_iEffSeg, a_GCPtrEff) do { } while (0) 406 406 #define IEM_MC_STORE_FPU_RESULT(a_FpuData, a_iStReg) do { } while (0) 407 #define IEM_MC_STORE_FPU_RESULT_MEM_OP(a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff) do { } while (0) 408 #define IEM_MC_FPU_STACK_UNDERFLOW(a_iStReg) do { } while (0) 409 #define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(a_iStReg, a_iEffSeg, a_GCPtrEff) do { } while (0) 407 #define IEM_MC_STORE_FPU_RESULT_THEN_POP(a_FpuData, a_iStReg) do { } while (0) 408 #define IEM_MC_STORE_FPU_RESULT_MEM_OP(a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff) do { } while (0) 409 #define IEM_MC_STORE_FPU_RESULT_MEM_OP_THEN_POP(a_FpuData, a_iStReg, a_iEffSeg, a_GCPtrEff) do { } while (0) 410 #define IEM_MC_FPU_STACK_UNDERFLOW(a_iStReg) do { } while (0) 411 #define IEM_MC_FPU_STACK_UNDERFLOW_THEN_POP(a_iStReg) do { } while (0) 412 #define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP(a_iStReg, a_iEffSeg, a_GCPtrEff) do { } while (0) 413 #define IEM_MC_FPU_STACK_UNDERFLOW_MEM_OP_THEN_POP(a_iStReg, a_iEffSeg, a_GCPtrEff) do { } while (0) 410 414 411 415 #define IEM_MC_IF_EFL_BIT_SET(a_fBit) if (g_fRandom) { … … 429 433 #define IEM_MC_IF_GREG_BIT_SET(a_iGReg, a_iBitNo) if (g_fRandom) { 430 434 #define IEM_MC_IF_FPUREG_NOT_EMPTY_REF_R80(a_pr80Dst, a_iSt) if (g_fRandom) { 435 #define IEM_MC_IF_TWO_FPUREGS_NOT_EMPTY_REF_R80(p0, i0, p1, i1) if (g_fRandom) { 431 436 #define IEM_MC_ELSE() } else { 432 437 #define IEM_MC_ENDIF() } do {} while (0) … … 441 446 #define iemAImpl_fdiv_r80_by_r64 NULL 442 447 #define iemAImpl_fdivr_r80_by_r64 NULL 448 449 #define iemAImpl_fadd_r80_by_r80 NULL 450 #define iemAImpl_fmul_r80_by_r80 NULL 451 #define iemAImpl_fcom_r80_by_r80 NULL 452 #define iemAImpl_fsub_r80_by_r80 NULL 453 #define iemAImpl_fsubr_r80_by_r80 NULL 454 #define iemAImpl_fdiv_r80_by_r80 NULL 455 #define iemAImpl_fdivr_r80_by_r80 NULL 443 456 444 457 -
trunk/src/VBox/VMM/testcase/tstX86-1A.asm
r40160 r40164 105 105 g_r80_Max: dt 07ffeffffffffffffffffh 106 106 g_r80_Inf: dt 07fff8000000000000000h 107 g_r80_DnMin: dt 000000000000000000001h 108 g_r80_DnMax: dt 000007fffffffffffffffh 107 109 108 110 g_r32V1: dd 3.2 … … 324 326 325 327 ;; 326 ; Checks that ST 0in a FXSAVE image has a certain value (empty or not328 ; Checks that STn in a FXSAVE image has a certain value (empty or not 327 329 ; is ignored). 330 ; 331 ; @uses eax 332 ; @param 1 Address expression for the FXSAVE image. 333 ; @param 2 The register number. 334 ; @param 3 First dword of value. 335 ; @param 4 Second dword of value. 336 ; @param 5 Final word of value. 337 ; 338 %macro FxSaveCheckStNValueEx 5 339 cmp dword [%1 + X86FXSTATE.st0 + %2 * 16], %3 340 je %%ok1 341 %%bad: 342 mov eax, 40000000 + __LINE__ 343 jmp .return 344 %%ok1: 345 cmp dword [%1 + X86FXSTATE.st0 + %2 * 16 + 4], %4 346 jne %%bad 347 cmp word [%1 + X86FXSTATE.st0 + %2 * 16 + 8], %5 348 jne %%bad 349 %endmacro 350 351 352 ;; 353 ; Checks if STn in a FXSAVE image has the same value as the specified 354 ; floating point (80-bit) constant. 355 ; 356 ; @uses eax, xDX 357 ; @param 1 Address expression for the FXSAVE image. 358 ; @param 2 The register number. 359 ; @param 3 The address expression of the constant. 360 ; 361 %macro FxSaveCheckStNValueConstEx 3 362 mov eax, [%3] 363 cmp dword [%1 + X86FXSTATE.st0 + %2 * 16], eax 364 je %%ok1 365 %%bad: 366 mov eax, 40000000 + __LINE__ 367 jmp .return 368 %%ok1: 369 mov eax, [4 + %3] 370 cmp dword [%1 + X86FXSTATE.st0 + %2 * 16 + 4], eax 371 jne %%bad 372 mov ax, [8 + %3] 373 cmp word [%1 + X86FXSTATE.st0 + %2 * 16 + 8], ax 374 jne %%bad 375 %endmacro 376 377 378 ;; 379 ; Checks that ST0 in a FXSAVE image has a certain value. 328 380 ; 329 381 ; @uses eax … … 333 385 ; @param 4 Final word of value. 334 386 ; 335 %macro FxSaveCheckSt0ValueEx 4 336 cmp dword [%1 + X86FXSTATE.st0], %2 337 je %%ok1 338 %%bad: 339 mov eax, 40000000 + __LINE__ 340 jmp .return 341 %%ok1: 342 cmp dword [%1 + X86FXSTATE.st0 + 4], %3 343 jne %%bad 344 cmp word [%1 + X86FXSTATE.st0 + 8], %4 345 jne %%bad 387 %macro FxSaveCheckSt0Value 4 388 FxSaveCheckSt0NonEmpty %1 389 FxSaveCheckStNValueEx %1, 0, %2, %3, %4 346 390 %endmacro 347 391 348 392 349 393 ;; 350 ; Checks if ST0 in a FXSAVE image has the same value as the specified 351 ; floating point (80-bit) constant. 352 ; 353 ; @uses eax, xDX 354 ; @param 1 Address expression for the FXSAVE image. 355 ; @param 2 The address expression of the constant. 356 ; 357 %macro FxSaveCheckSt0ValueConstEx 2 358 mov eax, [%2] 359 cmp dword [%1 + X86FXSTATE.st0], eax 360 je %%ok1 361 %%bad: 362 mov eax, 40000000 + __LINE__ 363 jmp .return 364 %%ok1: 365 mov eax, [4 + %2] 366 cmp dword [%1 + X86FXSTATE.st0 + 4], eax 367 jne %%bad 368 mov ax, [8 + %2] 369 cmp word [%1 + X86FXSTATE.st0 + 8], ax 370 jne %%bad 371 %endmacro 372 373 374 ;; 375 ; Checks that ST0 in a FXSAVE image has a certain value. 394 ; Checks that ST0 in a FXSAVE image is empty and that the value stored is the 395 ; init value set by FpuInitWithCW. 376 396 ; 377 397 ; @uses eax 378 398 ; @param 1 Address expression for the FXSAVE image. 379 ; @param 2 First dword of value.380 ; @param 3 Second dword of value.381 ; @param 4 Final word of value.382 ;383 %macro FxSaveCheckSt0Value 4384 FxSaveCheckSt0NonEmpty %1385 FxSaveCheckSt0ValueEx %1, %2, %3, %4386 %endmacro387 388 389 ;;390 ; Checks that ST0 in a FXSAVE image is empty and that the value stored is the391 ; init value set by FpuInitWithCW.392 ;393 ; @uses eax394 ; @param 1 Address expression for the FXSAVE image.395 399 ; 396 400 %macro FxSaveCheckSt0EmptyInitValue 1 397 401 FxSaveCheckSt0Empty %1 398 FxSaveCheckSt 0ValueEx %1, 0x40404040, 0x40404040, 0xffff402 FxSaveCheckStNValueEx %1, 0, 0x40404040, 0x40404040, 0xffff 399 403 %endmacro 400 404 … … 408 412 %macro FxSaveCheckSt0ValueConst 2 409 413 FxSaveCheckSt0NonEmpty %1 410 FxSaveCheckSt 0ValueConstEx %1, %2414 FxSaveCheckStNValueConstEx %1, 0, %2 411 415 %endmacro 412 416 … … 419 423 ;; Checks that ST0 contains 3 & 1/3. 420 424 %define FxSaveCheckSt0Value_3_and_two_3rds(p) FxSaveCheckSt0Value p, 0xaaaaaaab, 0xeaaaaaaa, 0x4000 425 426 427 428 ;; 429 ; Checks that STn is empty in an FXSAVE image. 430 ; 431 ; @uses eax 432 ; @param 1 Address expression for the FXSAVE image. 433 ; @param 2 The register number. 434 ; 435 %macro FxSaveCheckStNEmpty 2 436 movzx eax, word [%1 + X86FXSTATE.FSW] 437 and eax, X86_FSW_TOP_MASK 438 shr eax, X86_FSW_TOP_SHIFT 439 add eax, %2 440 and eax, X86_FSW_TOP_SMASK 441 bt [%1 + X86FXSTATE.FTW], eax 442 jnc %%ok 443 mov eax, 20000000 + __LINE__ 444 jmp .return 445 %%ok: 446 %endmacro 447 448 449 ;; 450 ; Checks that STn is not-empty in an FXSAVE image. 451 ; 452 ; @uses eax 453 ; @param 1 Address expression for the FXSAVE image. 454 ; @param 2 The register number. 455 ; 456 %macro FxSaveCheckStNNonEmpty 2 457 movzx eax, word [%1 + X86FXSTATE.FSW] 458 and eax, X86_FSW_TOP_MASK 459 shr eax, X86_FSW_TOP_SHIFT 460 add eax, %2 461 and eax, X86_FSW_TOP_SMASK 462 bt [%1 + X86FXSTATE.FTW], eax 463 jc %%ok 464 mov eax, 30000000 + __LINE__ 465 jmp .return 466 %%ok: 467 %endmacro 468 469 470 ;; 471 ; Checks that STn in a FXSAVE image has a certain value. 472 ; 473 ; @uses eax 474 ; @param 1 Address expression for the FXSAVE image. 475 ; @param 2 The register number. 476 ; @param 3 First dword of value. 477 ; @param 4 Second dword of value. 478 ; @param 5 Final word of value. 479 ; 480 %macro FxSaveCheckStNValue 5 481 FxSaveCheckStNNonEmpty %1, %2 482 FxSaveCheckStNValueEx %1, %2, %3, %4, %5 483 %endmacro 484 485 ;; 486 ; Checks that ST0 in a FXSAVE image is non-empty and has the same value as the 487 ; specified constant (80-bit). 488 ; 489 ; @uses eax, xDX 490 ; @param 1 Address expression for the FXSAVE image. 491 ; @param 2 The register number. 492 ; @param 3 The address expression of the constant. 493 %macro FxSaveCheckStNValueConst 3 494 FxSaveCheckStNNonEmpty %1, %2 495 FxSaveCheckStNValueConstEx %1, %2, %3 496 %endmacro 497 498 ;; Checks that ST0 contains QNaN. 499 %define FxSaveCheckStNValue_QNaN(p, iSt) FxSaveCheckStNValue p, iSt, 0x00000000, 0xc0000000, 0xffff 500 ;; Checks that ST0 contains +Inf. 501 %define FxSaveCheckStNValue_PlusInf(p, iSt) FxSaveCheckStNValue p, iSt, 0x00000000, 0x80000000, 0x7fff 502 ;; Checks that ST0 contains 3 & 1/3. 503 %define FxSaveCheckStNValue_3_and_a_3rd(p, iSt) FxSaveCheckStNValue p, iSt, 0x55555555, 0xd5555555, 0x4000 504 ;; Checks that ST0 contains 3 & 1/3. 505 %define FxSaveCheckStNValue_3_and_two_3rds(p, iSt) FxSaveCheckStNValue p, iSt, 0xaaaaaaab, 0xeaaaaaaa, 0x4000 421 506 422 507 … … 2304 2389 ret 2305 2390 2391 ;; 2392 ; Checks a FPU instruction, no memory operand. 2393 ; 2394 ; @uses xCX, xAX, Stack. 2395 ; 2396 %macro FpuCheckOpcodeCsIp 1 2397 %%instruction: 2398 %1 2399 arch_fxsave [xSP] 2400 fnstenv [xSP + 512] ; for the selectors (64-bit) 2401 arch_fxrstor [xSP] ; fnstenv screws up the ES bit. 2402 lea xCX, [REF(%%instruction)] 2403 call CheckOpcodeCsIp 2404 jz %%ok 2405 or eax, __LINE__ 2406 jmp .return 2407 %%ok: 2408 %endmacro 2409 2410 2411 ;; 2412 ; Checks a trapping FPU instruction, no memory operand. 2413 ; 2414 ; Upon return, there is are two FXSAVE image on the stack at xSP. 2415 ; 2416 ; @uses xCX, xAX, Stack. 2417 ; 2418 ; @param %1 The instruction. 2419 ; 2420 %macro FpuTrapOpcodeCsIp 1 2421 %%instruction: 2422 %1 2423 fxsave [xSP + 1024 +512] ; FPUDS and FPUCS for 64-bit hosts. 2424 ; WEIRD: When saved after FWAIT they are ZEROed! (64-bit Intel) 2425 arch_fxsave [xSP] 2426 fnstenv [xSP + 512] 2427 arch_fxrstor [xSP] 2428 %%trap: 2429 fwait 2430 %%trap_end: 2431 mov eax, __LINE__ 2432 jmp .return 2433 BEGINDATA 2434 %%trapinfo: istruc TRAPINFO 2435 at TRAPINFO.uTrapPC, RTCCPTR_DEF %%trap 2436 at TRAPINFO.uResumePC, RTCCPTR_DEF %%resume 2437 at TRAPINFO.u8TrapNo, db X86_XCPT_MF 2438 at TRAPINFO.cbInstr, db (%%trap_end - %%trap) 2439 iend 2440 BEGINCODE 2441 %%resume: 2442 lea xCX, [REF(%%instruction)] 2443 call CheckOpcodeCsIp 2444 jz %%ok 2445 or eax, __LINE__ 2446 jmp .return 2447 %%ok: 2448 %endmacro 2306 2449 2307 2450 … … 2405 2548 arch_fxsave [xSP] 2406 2549 fnstenv [xSP + 512] 2407 arch_fxrstor [xSP] 2550 arch_fxrstor [xSP] 2408 2551 %%trap: 2409 2552 fwait … … 2468 2611 SAVE_ALL_PROLOGUE 2469 2612 sub xSP, 2048 2470 2613 %if 1 2471 2614 ; 2472 2615 ; FDIV with 64-bit floating point memory operand. … … 2475 2618 2476 2619 ; ## Normal operation. ## 2620 2477 2621 fninit 2478 2622 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)] … … 2484 2628 2485 2629 ; ## Masked exceptions. ## 2630 2486 2631 ; Masked stack underflow. 2487 2632 fninit … … 2547 2692 2548 2693 ; ## Unmasked exceptions. ## 2694 2549 2695 ; Stack underflow - TOP and ST0 unmodified. 2550 2696 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST … … 2627 2773 mov xBX, [REF_EXTERN(g_pbEfExecPage)] 2628 2774 ShouldTrap X86_XCPT_MF, fdiv qword [xBX + PAGE_SIZE] 2775 %endif 2776 2777 ; 2778 ; FSUBRP STn, ST0 2779 ; 2780 SetSubTest "FSUBRP STn, ST0" 2781 2782 ; ## Normal operation. ## 2783 fninit 2784 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)] 2785 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)] 2786 FpuCheckOpcodeCsIp { fsubrp st1, st0 } 2787 FxSaveCheckFSW xSP, 0, 0 2788 FxSaveCheckSt0ValueConst xSP, REF(g_r80_Zero) 2789 2790 ; ## Masked exceptions. ## 2791 2792 ; Masked stack underflow, both operands. 2793 fninit 2794 FpuCheckOpcodeCsIp { fsubrp st1, st0 } 2795 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3 2796 FxSaveCheckSt0Value_QNaN(xSP) 2797 2798 ; Masked stack underflow, one operand. 2799 fninit 2800 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)] 2801 FpuCheckOpcodeCsIp { fsubrp st1, st0 } 2802 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3 2803 FxSaveCheckSt0Value_QNaN(xSP) 2804 2805 ; Denormal operand. 2806 fninit 2807 fld tword [REF(g_r80_DnMax)] 2808 fld tword [REF(g_r80_DnMin)] 2809 FpuCheckOpcodeCsIp { fsubrp st1, st0 } 2810 FxSaveCheckFSW xSP, X86_FSW_DE, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3 2811 FxSaveCheckSt0Value xSP, 0xfffffffe, 0x7fffffff, 0x8000 2812 2813 ; ## Unmasked exceptions. ## 2814 2815 ; Stack underflow, both operands - no pop or change. 2816 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST 2817 FpuTrapOpcodeCsIp { fsubrp st1, st0 } 2818 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3 2819 FxSaveCheckSt0EmptyInitValue xSP 2820 2821 ; Stack underflow, one operand - no pop or change. 2822 FpuInitWithCW X86_FCW_PC_64 | X86_FCW_RC_NEAREST 2823 FpuCheckOpcodeCsIpDsDp { fld dword [REF(g_r32_3dot2)] }, [REF(g_r32_3dot2)] 2824 FpuTrapOpcodeCsIp { fsubrp st1, st0 } 2825 FxSaveCheckFSW xSP, X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3 2826 FxSaveCheckSt0ValueConst xSP, REF(g_r80_r32_3dot2) 2827 2828 ; Denormal operand - no pop. 2829 fninit 2830 fld tword [REF(g_r80_DnMax)] 2831 fld tword [REF(g_r80_DnMin)] 2832 fnclex 2833 mov dword [xSP], X86_FCW_PC_64 | X86_FCW_RC_NEAREST 2834 fldcw [xSP] 2835 FpuTrapOpcodeCsIp { fsubrp st1, st0 } 2836 FxSaveCheckFSW xSP, X86_FSW_DE | X86_FSW_ES | X86_FSW_B, X86_FSW_C0 | X86_FSW_C2 | X86_FSW_C3 2837 FxSaveCheckStNValueConst xSP, 1, REF(g_r80_DnMax) 2838 FxSaveCheckStNValueConst xSP, 0, REF(g_r80_DnMin) 2839 2629 2840 2630 2841 .success:
Note:
See TracChangeset
for help on using the changeset viewer.