Changeset 40093 in vbox
- Timestamp:
- Feb 13, 2012 1:05:21 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 76233
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r40077 r40093 3285 3285 3286 3286 /** 3287 * Pushes a FPU result onto the FPU stack after inspecting the resulting 3288 * statuses. 3287 * Updates the FOP, FPU.CS and FPUIP registers. 3288 * 3289 * @param pIemCpu The IEM per CPU data. 3290 * @param pCtx The CPU context. 3291 */ 3292 DECLINLINE(void) iemFpuUpdateOpcodeAndIP(PIEMCPU pIemCpu, PCPUMCTX pCtx) 3293 { 3294 pCtx->fpu.FOP = pIemCpu->abOpcode[pIemCpu->offFpuOpcode] 3295 | ((uint16_t)(pIemCpu->abOpcode[pIemCpu->offFpuOpcode - 1] & 0x7) << 8); 3296 /** @todo FPU.CS and FPUIP needs to be kept seperately. */ 3297 pCtx->fpu.CS = pCtx->cs; 3298 pCtx->fpu.FPUIP = pCtx->rip; 3299 } 3300 3301 3302 /** 3303 * Updates the FPU.DS and FPUDP registers. 3304 * 3305 * @param pIemCpu The IEM per CPU data. 3306 * @param pCtx The CPU context. 3307 * @param iEffSeg The effective segment register. 3308 * @param GCPtrEff The effective address relative to @a iEffSeg. 3309 */ 3310 DECLINLINE(void) iemFpuUpdateDP(PIEMCPU pIemCpu, PCPUMCTX pCtx, uint8_t iEffSeg, RTGCPTR GCPtrEff) 3311 { 3312 RTSEL sel; 3313 switch (iEffSeg) 3314 { 3315 case X86_SREG_DS: sel = pCtx->ds; break; 3316 case X86_SREG_SS: sel = pCtx->ss; break; 3317 case X86_SREG_CS: sel = pCtx->cs; break; 3318 case X86_SREG_ES: sel = pCtx->es; break; 3319 case X86_SREG_FS: sel = pCtx->fs; break; 3320 case X86_SREG_GS: sel = pCtx->gs; break; 3321 default: 3322 AssertMsgFailed(("%d\n", iEffSeg)); 3323 sel = pCtx->ds; 3324 } 3325 /** @todo FPU.DS and FPUDP needs to be kept seperately. */ 3326 pCtx->fpu.DS = sel; 3327 pCtx->fpu.FPUDP = GCPtrEff; 3328 } 3329 3330 3331 /** 3332 * Rotates the stack registers in the push direction. 3333 * 3334 * @param pCtx The CPU context. 3335 * @remarks This is a complete waste of time, but fxsave stores the registers in 3336 * stack order. 3337 */ 3338 DECLINLINE(void) iemFpuRotateStackPush(PCPUMCTX pCtx) 3339 { 3340 RTFLOAT80U r80Tmp = pCtx->fpu.aRegs[7].r80; 3341 pCtx->fpu.aRegs[7].r80 = pCtx->fpu.aRegs[6].r80; 3342 pCtx->fpu.aRegs[6].r80 = pCtx->fpu.aRegs[5].r80; 3343 pCtx->fpu.aRegs[5].r80 = pCtx->fpu.aRegs[4].r80; 3344 pCtx->fpu.aRegs[4].r80 = pCtx->fpu.aRegs[3].r80; 3345 pCtx->fpu.aRegs[3].r80 = pCtx->fpu.aRegs[2].r80; 3346 pCtx->fpu.aRegs[2].r80 = pCtx->fpu.aRegs[1].r80; 3347 pCtx->fpu.aRegs[1].r80 = pCtx->fpu.aRegs[0].r80; 3348 pCtx->fpu.aRegs[0].r80 = r80Tmp; 3349 } 3350 3351 3352 /** 3353 * Rotates the stack registers in the pop direction. 3354 * 3355 * @param pCtx The CPU context. 3356 * @remarks This is a complete waste of time, but fxsave stores the registers in 3357 * stack order. 3358 */ 3359 DECLINLINE(void) iemFpuRotateStackPop(PCPUMCTX pCtx) 3360 { 3361 RTFLOAT80U r80Tmp = pCtx->fpu.aRegs[0].r80; 3362 pCtx->fpu.aRegs[0].r80 = pCtx->fpu.aRegs[1].r80; 3363 pCtx->fpu.aRegs[1].r80 = pCtx->fpu.aRegs[2].r80; 3364 pCtx->fpu.aRegs[2].r80 = pCtx->fpu.aRegs[3].r80; 3365 pCtx->fpu.aRegs[3].r80 = pCtx->fpu.aRegs[4].r80; 3366 pCtx->fpu.aRegs[4].r80 = pCtx->fpu.aRegs[5].r80; 3367 pCtx->fpu.aRegs[5].r80 = pCtx->fpu.aRegs[6].r80; 3368 pCtx->fpu.aRegs[6].r80 = pCtx->fpu.aRegs[7].r80; 3369 pCtx->fpu.aRegs[7].r80 = r80Tmp; 3370 } 3371 3372 3373 #if 0 3374 /** 3289 3375 * 3290 3376 * @param pIemCpu The IEM per CPU data. 3291 3377 * @param pResult The FPU operation result to push. 3292 */ 3293 static void iemFpuPushResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult) 3378 * @param pCtx The CPU context. 3379 * @param iDstReg The destination register, 3380 * @param cStackAdj The stack adjustment on successful operation. 3381 * Note that this is an unsigned value. 3382 * @param fFlags Flags. 3383 */ 3384 static void iemFpuPushResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult, PCPUMCTX pCtx, uint16_t iDstReg, 3385 uint8_t cStackAdj, ) 3294 3386 { 3295 3387 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 3388 iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx); 3296 3389 3297 3390 uint16_t iNewTop = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + 7) & X86_FSW_TOP_SMASK; … … 3331 3424 } 3332 3425 3333 /* This is stupid, but we must now rotate the registers since they stored 3334 in stack order. A complete waste of time! */ 3335 RTFLOAT80U r80Tmp = pCtx->fpu.aRegs[7].r80; 3336 memmove(&pCtx->fpu.aRegs[1], &pCtx->fpu.aRegs[0], sizeof(pCtx->fpu.aRegs[0]) * 7); 3337 pCtx->fpu.aRegs[0].r80 = r80Tmp; 3338 } 3339 3426 iemFpuRotateStackPush(pCtx); 3427 } 3428 3429 3430 /** 3431 * Writes a FPU result to the FPU stack after inspecting the resulting 3432 * statuses. 3433 * 3434 * @param pIemCpu The IEM per CPU data. 3435 * @param pResult The FPU operation result to push. 3436 * @param iReg The stack relative FPU register number. 3437 */ 3438 static void iemFpuStoreResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult, uint8_t iReg) 3439 { 3440 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 3441 iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx); 3442 3443 uint16_t iReg = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + iReg) & X86_FSW_TOP_SMASK; 3444 3445 uint16_t fXcpts = (pResult->FSW & (X86_FSW_IE | X86_FSW_DE | X86_FSW_ZE | X86_FSW_OE | X86_FSW_UE | X86_FSW_PE)) 3446 & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_DM | X86_FCW_ZM | X86_FCW_OM | X86_FCW_UM | X86_FCW_PM)); 3447 if (!fXcpts) 3448 { 3449 /* No unmasked exceptions, just store the result. */ 3450 pCtx->fpu.FSW &= X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3; 3451 pCtx->fpu.FSW |= (pResult->FSW & ~(X86_FSW_TOP_MASK | X86_FSW_B | X86_FSW_ES)); 3452 pCtx->fpu.FTW |= RT_BIT(iNewTop); 3453 pCtx->fpu.aRegs[7].r80 = pResult->r80Result; 3454 } 3455 else 3456 { 3457 AssertFailed(); 3458 } 3459 } 3460 #endif 3461 3462 3463 /** 3464 * Pushes a FPU result onto the FPU stack after inspecting the resulting 3465 * statuses. 3466 * 3467 * @param pIemCpu The IEM per CPU data. 3468 * @param pResult The FPU operation result to push. 3469 */ 3470 static void iemFpuPushResult(PIEMCPU pIemCpu, PIEMFPURESULT pResult) 3471 { 3472 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 3473 iemFpuUpdateOpcodeAndIP(pIemCpu, pCtx); 3474 3475 uint16_t iNewTop = (X86_FSW_TOP_GET(pCtx->fpu.FSW) + 7) & X86_FSW_TOP_SMASK; 3476 if (!(RT_BIT(iNewTop) & pCtx->fpu.FTW)) 3477 { 3478 /* No stack error. */ 3479 uint16_t fXcpts = (pResult->FSW & (X86_FSW_IE | X86_FSW_DE | X86_FSW_ZE | X86_FSW_OE | X86_FSW_UE | X86_FSW_PE)) 3480 & ~(pCtx->fpu.FCW & (X86_FCW_IM | X86_FCW_DM | X86_FCW_ZM | X86_FCW_OM | X86_FCW_UM | X86_FCW_PM)); 3481 if (!fXcpts) 3482 { 3483 /* No unmasked exceptions, just store the result. */ 3484 pCtx->fpu.FSW &= X86_FSW_TOP_MASK | X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3; 3485 pCtx->fpu.FSW |= (iNewTop << X86_FSW_TOP_SHIFT) | (pResult->FSW & ~(X86_FSW_TOP_MASK | X86_FSW_B | X86_FSW_ES)); 3486 pCtx->fpu.FTW |= RT_BIT(iNewTop); 3487 pCtx->fpu.aRegs[7].r80 = pResult->r80Result; 3488 } 3489 else 3490 { 3491 AssertFailed(); 3492 } 3493 3494 } 3495 else if (pCtx->fpu.FCW & X86_FCW_IM) 3496 { 3497 /* Masked stack overflow. */ 3498 pCtx->fpu.FSW &= X86_FSW_TOP_MASK | X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3; 3499 pCtx->fpu.FSW |= (iNewTop << X86_FSW_TOP_SHIFT) | X86_FSW_C1 | X86_FSW_IE | X86_FSW_SF; 3500 pCtx->fpu.FTW |= RT_BIT(iNewTop); 3501 iemFpuStoreQNan(&pCtx->fpu.aRegs[7].r80); 3502 } 3503 else 3504 { 3505 /* Stack overflow exception. */ 3506 pCtx->fpu.FSW &= X86_FSW_C0 | X86_FSW_C1 | X86_FSW_C2 | X86_FSW_C3; 3507 pCtx->fpu.FSW |= X86_FSW_C1 | X86_FSW_IE | X86_FSW_SF | X86_FSW_ES | X86_FSW_B; 3508 return; 3509 } 3510 3511 iemFpuRotateStackPush(pCtx); 3512 } 3513 3514 3515 /** 3516 * Pushes a FPU result onto the FPU stack after inspecting the resulting 3517 * statuses, and sets FPU.DS and FPUDP. 3518 * 3519 * @param pIemCpu The IEM per CPU data. 3520 * @param pResult The FPU operation result to push. 3521 * @param iEffSeg The effective segment register. 3522 * @param GCPtrEff The effective address relative to @a iEffSeg. 3523 */ 3524 static void iemFpuPushResultWithMemOp(PIEMCPU pIemCpu, PIEMFPURESULT pResult, uint8_t iEffSeg, RTGCPTR GCPtrEff) 3525 { 3526 iemFpuUpdateDP(pIemCpu, pIemCpu->CTX_SUFF(pCtx), iEffSeg, GCPtrEff); 3527 iemFpuPushResult(pIemCpu, pResult); 3528 } 3340 3529 3341 3530 /** @} */ … … 5233 5422 IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU32(pIemCpu, &(a_r32Dst).u32, (a_iSeg), (a_GCPtrMem))) 5234 5423 #define IEM_MC_FETCH_MEM_R64(a_r64Dst, a_iSeg, a_GCPtrMem) \ 5235 IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU64(pIemCpu, &(a_r64Dst). u64, (a_iSeg), (a_GCPtrMem)))5424 IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataU64(pIemCpu, &(a_r64Dst).au64[0], (a_iSeg), (a_GCPtrMem))) 5236 5425 #define IEM_MC_FETCH_MEM_R80(a_r80Dst, a_iSeg, a_GCPtrMem) \ 5237 5426 IEM_MC_RETURN_ON_FAILURE(iemMemFetchDataR80(pIemCpu, &(a_r64Dst), (a_iSeg), (a_GCPtrMem))) … … 5482 5671 } while (0) 5483 5672 /** Pushes FPU result onto the stack. */ 5484 #define IEM_MC_PUSH_FPU_RESULT(a_FpuData) iemFpuPushResult(pIemCpu, &a_FpuData) 5673 #define IEM_MC_PUSH_FPU_RESULT(a_FpuData) \ 5674 iemFpuPushResult(pIemCpu, &a_FpuData) 5675 /** Pushes FPU result onto the stack and sets the FPUDP. */ 5676 #define IEM_MC_PUSH_FPU_RESULT_MEM_OP(a_FpuData, a_iEffSeg, a_GCPtrEff) \ 5677 iemFpuPushResultWithMemOp(pIemCpu, &a_FpuData, a_iEffSeg, a_GCPtrEff) 5485 5678 5486 5679 -
trunk/src/VBox/VMM/VMMAll/IEMAllAImpl.asm
r40077 r40093 1361 1361 ENDPROC iemAImpl_fpu_r32_to_r80 1362 1362 1363 1364 ;; 1365 ; Converts a 64-bit floating point value to a 80-bit one (fpu register). 1366 ; 1367 ; @param A0 FPU context (fxsave). 1368 ; @param A1 Pointer to a IEMFPURESULT for the output. 1369 ; @param A2 Pointer to the 32-bit floating point value to convert. 1370 ; 1371 BEGINPROC_FASTCALL iemAImpl_fpu_r64_to_r80, 12 1372 PROLOGUE_3_ARGS 1373 sub xSP, 20h 1374 1375 FPU_SAFE_INIT A0 1376 fld qword [A2] 1377 1378 fnstsw word [A1 + IEMFPURESULT.FSW] 1379 fstp tword [A1 + IEMFPURESULT.r80Result] 1380 1381 add xSP, 20h 1382 EPILOGUE_3_ARGS 0 1383 ENDPROC iemAImpl_fpu_r64_to_r80 1384 -
trunk/src/VBox/VMM/VMMAll/IEMAllInstructions.cpp.h
r40092 r40093 10342 10342 10343 10343 10344 /** Opcode 0xd9 /0 mem32real */ 10344 /** Opcode 0xd9 /0 mem32real 10345 * @sa iemOp_fld_m64r */ 10345 10346 FNIEMOP_DEF_1(iemOp_fld_m32r, uint8_t, bRm) 10346 10347 { … … 10360 10361 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fpu_r32_to_r80, pFpuRes, r32Val); 10361 10362 10362 IEM_MC_PUSH_FPU_RESULT (FpuRes);10363 IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pIemCpu->iEffSeg, GCPtrEffSrc); 10363 10364 IEM_MC_ADVANCE_RIP(); 10364 10365 … … 10824 10825 10825 10826 /** Opcode 0xdc !11/6. */ 10827 #if 0 10828 FNIEMOP_DEF_1(iemOp_fdiv_m64r, uint8_t, bRm) 10829 { 10830 IEMOP_MNEMONIC("fdiv m64r"); 10831 IEMOP_HLP_NO_LOCK_PREFIX(); 10832 10833 IEM_MC_BEGIN(2, 3); 10834 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc); 10835 IEM_MC_LOCAL(IEMFPURESULT, FpuRes); 10836 IEM_MC_LOCAL(RTFLOAT64U, r64Val); 10837 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0); 10838 IEM_MC_ARG_LOCAL_REF(PRTFLOAT64U, pr64Val, r64Val, 1); 10839 10840 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm); 10841 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE(); 10842 IEM_MC_MAYBE_RAISE_FPU_XCPT(); 10843 IEM_MC_FETCH_MEM_R64(r64Val, pIemCpu->iEffSeg, GCPtrEffSrc); 10844 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fpu_r64_to_r80, pFpuRes, pr64Val); 10845 10846 IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pIemCpu->iEffSeg, GCPtrEffSrc); 10847 IEM_MC_ADVANCE_RIP(); 10848 10849 IEM_MC_END(); 10850 return VINF_SUCCESS; 10851 } 10852 #else 10826 10853 FNIEMOP_STUB_1(iemOp_fdiv_m64r, uint8_t, bRm); 10854 #endif 10827 10855 10828 10856 /** Opcode 0xdc !11/7. */ … … 10868 10896 10869 10897 10870 /** Opcode 0xdd !11/0. */ 10871 FNIEMOP_STUB_1(iemOp_fld_m64r, uint8_t, bRm); 10898 /** Opcode 0xdd !11/0. 10899 * @sa iemOp_fld_m32r */ 10900 FNIEMOP_DEF_1(iemOp_fld_m64r, uint8_t, bRm) 10901 { 10902 IEMOP_MNEMONIC("fld m64r"); 10903 IEMOP_HLP_NO_LOCK_PREFIX(); 10904 10905 IEM_MC_BEGIN(2, 3); 10906 IEM_MC_LOCAL(RTGCPTR, GCPtrEffSrc); 10907 IEM_MC_LOCAL(IEMFPURESULT, FpuRes); 10908 IEM_MC_LOCAL(RTFLOAT64U, r64Val); 10909 IEM_MC_ARG_LOCAL_REF(PIEMFPURESULT, pFpuRes, FpuRes, 0); 10910 IEM_MC_ARG_LOCAL_REF(PRTFLOAT64U, pr64Val, r64Val, 1); 10911 10912 IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm); 10913 IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE(); 10914 IEM_MC_MAYBE_RAISE_FPU_XCPT(); 10915 IEM_MC_FETCH_MEM_R64(r64Val, pIemCpu->iEffSeg, GCPtrEffSrc); 10916 IEM_MC_CALL_FPU_AIMPL_2(iemAImpl_fpu_r64_to_r80, pFpuRes, pr64Val); 10917 10918 IEM_MC_PUSH_FPU_RESULT_MEM_OP(FpuRes, pIemCpu->iEffSeg, GCPtrEffSrc); 10919 IEM_MC_ADVANCE_RIP(); 10920 10921 IEM_MC_END(); 10922 return VINF_SUCCESS; 10923 } 10872 10924 10873 10925 /** Opcode 0xdd !11/0. */ -
trunk/src/VBox/VMM/include/IEMInternal.h
r40082 r40093 716 716 /** @} */ 717 717 718 /** @name FPU operations taking a 64-bit float argument 719 * @{ */ 720 typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLFPUR64,(PCX86FXSTATE pFpuState, PIEMFPURESULT pFpuRes, PCRTFLOAT64U pr64Val)); 721 typedef FNIEMAIMPLFPUR64 *PFNIEMAIMPLFPUR64; 722 FNIEMAIMPLFPUR64 iemAImpl_fpu_r64_to_r80; 723 /** @} */ 724 718 725 719 726 /** @name Function tables. -
trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp
r40072 r40093 402 402 #define IEM_MC_CALL_FPU_AIMPL_2(a_pfnAImpl, a0, a1) do { } while (0) 403 403 #define IEM_MC_PUSH_FPU_RESULT(a_FpuData) do { } while (0) 404 #define IEM_MC_PUSH_FPU_RESULT_MEM_OP(a_FpuData, a_iEffSeg, a_GCPtrEff) do { } while (0) 404 405 405 406 #define IEM_MC_IF_EFL_BIT_SET(a_fBit) if (g_fRandom) {
Note:
See TracChangeset
for help on using the changeset viewer.