Changeset 106180 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Sep 30, 2024 1:51:48 PM (7 months ago)
- svn:sync-xref-src-repo-rev:
- 164964
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py
r106179 r106180 2944 2944 if sRet: 2945 2945 asRet.append(sRet); 2946 2947 ## @todo Check that IEM_MC_REF_EFLAGS isn't used before memory fetches and does 2948 # not have any stores or conditional raises afterwards. 2946 2949 2947 2950 return asRet; -
trunk/src/VBox/VMM/VMMAll/IEMAllInstVexMap2.cpp.h
r106061 r106180 313 313 IEM_MC_REF_XREG_U128_CONST(puSrc2, IEM_GET_MODRM_RM(pVCpu, bRm)); \ 314 314 IEM_MC_REF_EFLAGS(pEFlags); \ 315 316 317 315 IEM_MC_CALL_VOID_AIMPL_3(IEM_SELECT_HOST_OR_FALLBACK(fAvx, iemAImpl_ ## a_Instr ## _u128, \ 316 iemAImpl_ ## a_Instr ## _u128_fallback), \ 317 puSrc1, puSrc2, pEFlags); \ 318 318 IEM_MC_ADVANCE_RIP_AND_FINISH(); \ 319 319 IEM_MC_END(); \ … … 362 362 IEM_MC_REF_XREG_U128_CONST(puSrc1, IEM_GET_MODRM_REG(pVCpu, bRm)); \ 363 363 IEM_MC_REF_EFLAGS(pEFlags); \ 364 365 366 364 IEM_MC_CALL_VOID_AIMPL_3(IEM_SELECT_HOST_OR_FALLBACK(fAvx, iemAImpl_ ## a_Instr ## _u128, \ 365 iemAImpl_ ## a_Instr ## _u128_fallback), \ 366 puSrc1, puSrc2, pEFlags); \ 367 367 IEM_MC_ADVANCE_RIP_AND_FINISH(); \ 368 368 IEM_MC_END(); \ -
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompBltIn.cpp
r106144 r106180 56 56 #include "IEMN8veRecompilerEmit.h" 57 57 #include "IEMN8veRecompilerTlbLookup.h" 58 #include "target-x86/IEMAllN8veEmit-x86.h" 58 59 59 60 … … 213 214 uint8_t const idxTmpReg1 = iemNativeRegAllocTmp(pReNative, &off); 214 215 uint8_t const idxTmpReg2 = a_fCheckIrqs ? iemNativeRegAllocTmp(pReNative, &off) : UINT8_MAX; 215 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, RT_ARCH_VAL == RT_ARCH_VAL_AMD64 ? 72 : 32); 216 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 217 (RT_ARCH_VAL == RT_ARCH_VAL_AMD64 ? 72 : 32) 218 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS * 3); 216 219 217 220 /* … … 226 229 227 230 /* jz ReturnBreakFF */ 228 off = iemNativeEmit JccTbExitEx(pReNative, pCodeBuf, off, kIemNativeLabelType_ReturnBreakFF, kIemNativeInstrCond_e);231 off = iemNativeEmitTbExitJccEx<kIemNativeLabelType_ReturnBreakFF>(pReNative, pCodeBuf, off, kIemNativeInstrCond_e); 229 232 230 233 # elif defined(RT_ARCH_ARM64) … … 235 238 236 239 /* cbz reg1, ReturnBreakFF */ 237 off = iemNativeEmitT estIfGprIsZeroAndTbExitEx(pReNative, pCodeBuf, off, idxTmpReg1, false /*f64Bit*/,238 kIemNativeLabelType_ReturnBreakFF);240 off = iemNativeEmitTbExitIfGprIsZeroEx<kIemNativeLabelType_ReturnBreakFF>(pReNative, pCodeBuf, off, 241 idxTmpReg1, false /*f64Bit*/); 239 242 240 243 # else … … 341 344 off = iemNativeEmitCmpGprWithImmEx(pCodeBuf, off, idxTmpReg1, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC); 342 345 /* ja ReturnBreakFF */ 343 off = iemNativeEmit JccTbExitEx(pReNative, pCodeBuf, off, kIemNativeLabelType_ReturnBreakFF, kIemNativeInstrCond_nbe);346 off = iemNativeEmitTbExitJccEx<kIemNativeLabelType_ReturnBreakFF>(pReNative, pCodeBuf, off, kIemNativeInstrCond_nbe); 344 347 345 348 /* … … 357 360 # ifdef RT_ARCH_AMD64 358 361 /* jz ReturnBreakFF */ 359 off = iemNativeEmit JccTbExitEx(pReNative, pCodeBuf, off, kIemNativeLabelType_ReturnBreakFF, kIemNativeInstrCond_e);362 off = iemNativeEmitTbExitJccEx<kIemNativeLabelType_ReturnBreakFF>(pReNative, pCodeBuf, off, kIemNativeInstrCond_e); 360 363 361 364 # elif defined(RT_ARCH_ARM64) 362 365 /* cbz reg1, ReturnBreakFF */ 363 off = iemNativeEmitT estIfGprIsZeroAndTbExitEx(pReNative, pCodeBuf, off, idxTmpReg1, false /*f64Bit*/,364 kIemNativeLabelType_ReturnBreakFF);366 off = iemNativeEmitTbExitIfGprIsZeroEx<kIemNativeLabelType_ReturnBreakFF>(pReNative, pCodeBuf, off, 367 idxTmpReg1, false /*f64Bit*/); 365 368 # else 366 369 # error "port me" … … 475 478 off = iemNativeEmitLoadGprFromVCpuU32(pReNative, off, idxTmpReg, RT_UOFFSETOF(VMCPUCC, iem.s.fExec)); 476 479 off = iemNativeEmitAndGpr32ByImm(pReNative, off, idxTmpReg, IEMTB_F_KEY_MASK); 477 off = iemNativeEmitT estIfGpr32NotEqualImmAndTbExit(pReNative, off, idxTmpReg, fExpectedExec & IEMTB_F_KEY_MASK,478 kIemNativeLabelType_ReturnBreak);480 off = iemNativeEmitTbExitIfGpr32NotEqualImm<kIemNativeLabelType_ReturnBreak>(pReNative, off, idxTmpReg, 481 fExpectedExec & IEMTB_F_KEY_MASK); 479 482 iemNativeRegFreeTmp(pReNative, idxTmpReg); 480 483 … … 606 609 607 610 /* 3. Jump if greater. */ 608 off = iemNativeEmit JaTbExit(pReNative, off, kIemNativeLabelType_RaiseGp0);611 off = iemNativeEmitTbExitJa<kIemNativeLabelType_RaiseGp0>(pReNative, off); 609 612 610 613 iemNativeRegFreeTmp(pReNative, idxRegCsLim); … … 694 697 /* Compare the two and jump out if we're too close to the limit. */ 695 698 off = iemNativeEmitCmpGprWithGpr(pReNative, off, idxRegLeft, idxRegRight); 696 off = iemNativeEmit JlTbExit(pReNative, off, kIemNativeLabelType_NeedCsLimChecking);699 off = iemNativeEmitTbExitJl<kIemNativeLabelType_NeedCsLimChecking>(pReNative, off); 697 700 698 701 iemNativeRegFreeTmp(pReNative, idxRegRight); … … 754 757 } while (0) 755 758 756 # define NEAR_JMP_SIZE 5757 758 759 # define CHECK_OPCODES_CMP_JMP() /* cost: 7 bytes first time, then 2 bytes */ do { \ 759 760 if (offConsolidatedJump != UINT32_MAX) \ … … 766 767 else \ 767 768 { \ 768 pbCodeBuf[off++] = 0x74; /* jz near +NEAR_JMP_SIZE */ \ 769 pbCodeBuf[off++] = NEAR_JMP_SIZE + BP_ON_OBSOLETION; \ 770 offConsolidatedJump = off; \ 769 pbCodeBuf[off++] = 0x74; /* jz near +5 */ \ 770 offConsolidatedJump = ++off; \ 771 771 if (BP_ON_OBSOLETION) pbCodeBuf[off++] = 0xcc; \ 772 off = iemNativeEmitTbExitEx(pReNative, pbCodeBuf, off, kIemNativeLabelType_ObsoleteTb); \ 772 off = iemNativeEmitTbExitEx<kIemNativeLabelType_ObsoleteTb, false /*a_fActuallyExitingTb*/>(pReNative, \ 773 pbCodeBuf, off); \ 774 pbCodeBuf[offConsolidatedJump - 1] = off - offConsolidatedJump; \ 773 775 } \ 774 776 } while (0) … … 836 838 } 837 839 838 uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 6 + 14 + 54 + 8 + 6 + BP_ON_OBSOLETION /* = 88 */); 840 uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 6 + 14 + 54 + 8 + 6 + BP_ON_OBSOLETION /* = 88 */ 841 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 839 842 840 843 if (cbLeft > 8) … … 880 883 uint8_t const idxRegCx = iemNativeRegAllocTmpEx(pReNative, &off, RT_BIT_32(X86_GREG_xCX)); 881 884 882 uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 6 + 10 + 5 + 5 + 3 + 4 + 3 + BP_ON_OBSOLETION /*= 36*/); 885 uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 6 + 10 + 5 + 5 + 3 + 4 + 3 + BP_ON_OBSOLETION /*= 36*/ 886 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 883 887 884 888 /** @todo profile and optimize this further. Maybe an idea to align by … … 943 947 uint8_t const idxRegSrc1Val = iemNativeRegAllocTmp(pReNative, &off); 944 948 945 uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 64 );949 uint32_t * const pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 64 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS * 2); 946 950 947 951 /* One byte compare can be done with the opcode byte as an immediate. We'll … … 1014 1018 if (fPendingJmp) 1015 1019 { 1016 off = iemNativeEmit JccTbExitEx(pReNative, pu32CodeBuf, off, kIemNativeLabelType_ObsoleteTb,1017 kArmv8InstrCond_Ne);1020 off = iemNativeEmitTbExitJccEx<kIemNativeLabelType_ObsoleteTb>(pReNative, pu32CodeBuf, off, 1021 kArmv8InstrCond_Ne); 1018 1022 fPendingJmp = false; 1019 1023 } … … 1051 1055 ARMA64_NZCV_F_N0_Z0_C0_V0, kArmv8InstrCond_Eq); 1052 1056 1053 off = iemNativeEmitJccTbExitEx(pReNative, pu32CodeBuf, off, kIemNativeLabelType_ObsoleteTb, 1054 kArmv8InstrCond_Ne); 1057 off = iemNativeEmitTbExitJccEx<kIemNativeLabelType_ObsoleteTb>(pReNative, pu32CodeBuf, off, kArmv8InstrCond_Ne); 1055 1058 1056 1059 /* Advance and loop. */ … … 1185 1188 */ 1186 1189 if (fPendingJmp) 1187 off = iemNativeEmit JnzTbExit(pReNative, off, kIemNativeLabelType_ObsoleteTb);1190 off = iemNativeEmitTbExitJnz<kIemNativeLabelType_ObsoleteTb>(pReNative, off); 1188 1191 1189 1192 RT_NOREF(pu32CodeBuf, cbLeft, offPage, pbOpcodes, offConsolidatedJump); … … 1346 1349 /* 3. Check that off is less than X86_PAGE_SIZE/cbInstrBufTotal. */ 1347 1350 off = iemNativeEmitCmpGprWithImm(pReNative, off, idxRegTmp, X86_PAGE_SIZE - 1); 1348 off = iemNativeEmit JaTbExit(pReNative, off, kIemNativeLabelType_CheckBranchMiss);1351 off = iemNativeEmitTbExitJa<kIemNativeLabelType_CheckBranchMiss>(pReNative, off); 1349 1352 1350 1353 /* 4. Add iem.s.GCPhysInstrBuf and compare with GCPhysRangePageWithOffset. */ … … 1377 1380 | pTb->aRanges[idxRange].offPhysPage) 1378 1381 + offRange; 1379 off = iemNativeEmitT estIfGprNotEqualImmAndTbExit(pReNative, off, idxRegTmp, GCPhysRangePageWithOffset,1380 kIemNativeLabelType_CheckBranchMiss);1382 off = iemNativeEmitTbExitIfGprNotEqualImm<kIemNativeLabelType_CheckBranchMiss>(pReNative, off, idxRegTmp, 1383 GCPhysRangePageWithOffset); 1381 1384 1382 1385 iemNativeRegFreeTmp(pReNative, idxRegTmp); … … 1487 1490 */ 1488 1491 RTGCPHYS const GCPhysNewPage = iemTbGetRangePhysPageAddr(pTb, idxRange); 1489 off = iemNativeEmitTestIfGprNotEqualImmAndTbExit(pReNative, off, idxRegGCPhys, GCPhysNewPage, 1490 kIemNativeLabelType_ObsoleteTb); 1492 off = iemNativeEmitTbExitIfGprNotEqualImm<kIemNativeLabelType_ObsoleteTb>(pReNative, off, idxRegGCPhys, GCPhysNewPage); 1491 1493 1492 1494 iemNativeRegFreeTmp(pReNative, idxRegGCPhys); … … 1699 1701 off = iemNativeEmitLoadGprImm64(pReNative, off, idxRegTmp2, GCPhysRangePageWithOffset); 1700 1702 off = iemNativeEmitCmpGprWithGpr(pReNative, off, idxRegTmp, idxRegTmp2); 1701 off = iemNativeEmit JnzTbExit(pReNative, off, kIemNativeLabelType_CheckBranchMiss);1703 off = iemNativeEmitTbExitJnz<kIemNativeLabelType_CheckBranchMiss>(pReNative, off); 1702 1704 uint32_t const offFixedJumpToEnd = off; 1703 1705 off = iemNativeEmitJmpToFixed(pReNative, off, off + 512 /* force rel32 */); … … 1711 1713 1712 1714 /* Check that we haven't been here before. */ 1713 off = iemNativeEmitTestIfGprIsNotZeroAndTbExit(pReNative, off, idxRegTmp2, false /*f64Bit*/, 1714 kIemNativeLabelType_CheckBranchMiss); 1715 off = iemNativeEmitTbExitIfGprIsNotZero<kIemNativeLabelType_CheckBranchMiss>(pReNative, off, idxRegTmp2, false /*f64Bit*/); 1715 1716 1716 1717 /* Jump to the TLB lookup code. */ -
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h
r106179 r106180 60 60 #include "IEMN8veRecompilerTlbLookup.h" 61 61 #include "IEMNativeFunctions.h" 62 #include "target-x86/IEMAllN8veEmit-x86.h" 62 63 63 64 … … 442 443 RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_OTHER), 443 444 RT_BIT_64(IEMLIVENESSBIT_IDX_EFL_OTHER)); 444 off = iemNativeEmitTestAnyBitsInGprAndTbExitIfAnySet(pReNative, off, idxEflReg, 445 X86_EFL_TF | CPUMCTX_DBG_HIT_DRX_MASK | CPUMCTX_DBG_DBGF_MASK, 446 kIemNativeLabelType_ReturnWithFlags); 445 off = iemNativeEmitTbExitIfAnyBitsSetInGpr<kIemNativeLabelType_ReturnWithFlags>(pReNative, off, idxEflReg, 446 X86_EFL_TF 447 | CPUMCTX_DBG_HIT_DRX_MASK 448 | CPUMCTX_DBG_DBGF_MASK); 447 449 off = iemNativeEmitAndGpr32ByImm(pReNative, off, idxEflReg, ~(uint32_t)(X86_EFL_RF | CPUMCTX_INHIBIT_SHADOW)); 448 450 off = iemNativeEmitStoreGprToVCpuU32(pReNative, off, idxEflReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.eflags)); … … 556 558 557 559 if (pReNative->idxLastCheckIrqCallNo != UINT32_MAX) 558 return iemNativeEmitTbExit (pReNative, off, kIemNativeLabelType_ReturnBreakViaLookup);559 return iemNativeEmitTbExit (pReNative, off, kIemNativeLabelType_ReturnBreakViaLookupWithIrq);560 return iemNativeEmitTbExit<kIemNativeLabelType_ReturnBreakViaLookup>(pReNative, off); 561 return iemNativeEmitTbExit<kIemNativeLabelType_ReturnBreakViaLookupWithIrq>(pReNative, off); 560 562 } 561 563 } 562 564 if (pReNative->idxLastCheckIrqCallNo != UINT32_MAX) 563 return iemNativeEmitTbExit (pReNative, off, kIemNativeLabelType_ReturnBreakViaLookupWithTlb);564 return iemNativeEmitTbExit (pReNative, off, kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq);565 return iemNativeEmitTbExit<kIemNativeLabelType_ReturnBreakViaLookupWithTlb>(pReNative, off); 566 return iemNativeEmitTbExit<kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq>(pReNative, off); 565 567 #endif 566 568 } … … 749 751 off = iemNativeEmitAddGpr32Imm(pReNative, off, iTmpReg, (int32_t)0x8000); 750 752 off = iemNativeEmitShiftGprRight(pReNative, off, iTmpReg, 16); 751 off = iemNativeEmit JnzTbExit(pReNative, off, kIemNativeLabelType_RaiseGp0);753 off = iemNativeEmitTbExitJnz<kIemNativeLabelType_RaiseGp0>(pReNative, off); 752 754 753 755 iemNativeRegFreeTmp(pReNative, iTmpReg); … … 768 770 off = iemNativeEmitAddTwoGprs(pReNative, off, iTmpReg, idxAddrReg); 769 771 off = iemNativeEmitCmpArm64(pReNative, off, ARMV8_A64_REG_XZR, iTmpReg, true /*f64Bit*/, 48 /*cShift*/, kArmv8A64InstrShift_Lsr); 770 off = iemNativeEmit JnzTbExit(pReNative, off, kIemNativeLabelType_RaiseGp0);772 off = iemNativeEmitTbExitJnz<kIemNativeLabelType_RaiseGp0>(pReNative, off); 771 773 772 774 iemNativeRegFreeTmp(pReNative, iTmpReg); … … 854 856 off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxAddrReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip)); 855 857 856 off = iemNativeEmitTbExit (pReNative, off, kIemNativeLabelType_RaiseGp0, false /*fActuallyExitingTb*/);858 off = iemNativeEmitTbExit<kIemNativeLabelType_RaiseGp0, false /*a_fActuallyExitingTb*/>(pReNative, off); 857 859 858 860 /* .Lnoexcept: */ … … 950 952 off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxOldPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip)); 951 953 952 off = iemNativeEmitTbExit (pReNative, off, kIemNativeLabelType_RaiseGp0, false /*fActuallyExitingTb*/);954 off = iemNativeEmitTbExit<kIemNativeLabelType_RaiseGp0, false /*a_fActuallyExitingTb*/>(pReNative, off); 953 955 iemNativeFixupFixedJump(pReNative, offFixup, off); 954 956 } 955 957 else 956 958 #endif 957 off = iemNativeEmit JnzTbExit(pReNative, off, kIemNativeLabelType_RaiseGp0);959 off = iemNativeEmitTbExitJnz<kIemNativeLabelType_RaiseGp0>(pReNative, off); 958 960 959 961 iemNativeRegFreeTmp(pReNative, iTmpReg); … … 995 997 996 998 off = iemNativeEmitCmpGpr32WithGpr(pReNative, off, idxAddrReg, idxRegCsLim); 997 off = iemNativeEmit JaTbExit(pReNative, off, kIemNativeLabelType_RaiseGp0);999 off = iemNativeEmitTbExitJa<kIemNativeLabelType_RaiseGp0>(pReNative, off); 998 1000 999 1001 iemNativeRegFreeTmp(pReNative, idxRegCsLim); … … 1058 1060 off = iemNativeEmitStoreImmToVCpuU8(pReNative, off, idxInstr, RT_UOFFSETOF(VMCPUCC, iem.s.idxTbCurInstr)); 1059 1061 # endif 1060 off = iemNativeEmitTbExit (pReNative, off, kIemNativeLabelType_RaiseGp0, false /*fActuallyExitingTb*/);1062 off = iemNativeEmitTbExit<kIemNativeLabelType_RaiseGp0, false /*a_fActuallyExitingTb*/>(pReNative, off); 1061 1063 iemNativeFixupFixedJump(pReNative, offFixup, off); 1062 1064 } 1063 1065 else 1064 1066 #endif 1065 off = iemNativeEmit JaTbExit(pReNative, off, kIemNativeLabelType_RaiseGp0);1067 off = iemNativeEmitTbExitJa<kIemNativeLabelType_RaiseGp0>(pReNative, off); 1066 1068 1067 1069 iemNativeRegFreeTmp(pReNative, idxRegCsLim); … … 2599 2601 */ 2600 2602 /* Test and jump. */ 2601 off = iemNativeEmitT estAnyBitsInGprAndTbExitIfAnySet(pReNative, off, idxCr0Reg, X86_CR0_EM | X86_CR0_TS,2602 kIemNativeLabelType_RaiseNm);2603 off = iemNativeEmitTbExitIfAnyBitsSetInGpr<kIemNativeLabelType_RaiseNm>(pReNative, off, idxCr0Reg, 2604 X86_CR0_EM | X86_CR0_TS); 2603 2605 2604 2606 /* Free but don't flush the CR0 register. */ … … 2659 2661 off = iemNativeEmitAndGpr32ByImm(pReNative, off, idxCr0Reg, X86_CR0_MP | X86_CR0_TS); 2660 2662 /* Test and jump. */ 2661 off = iemNativeEmitTestIfGpr32EqualsImmAndTbExit(pReNative, off, idxCr0Reg, X86_CR0_MP | X86_CR0_TS, 2662 kIemNativeLabelType_RaiseNm); 2663 off = iemNativeEmitTbExitIfGpr32EqualsImm<kIemNativeLabelType_RaiseNm>(pReNative, off, idxCr0Reg, X86_CR0_MP | X86_CR0_TS); 2663 2664 2664 2665 /* Free the CR0 register. */ … … 2712 2713 */ 2713 2714 /* Test and jump. */ 2714 off = iemNativeEmitT estBitInGprAndTbExitIfSet(pReNative, off, idxFpuFswReg, X86_FSW_ES_BIT, kIemNativeLabelType_RaiseMf);2715 off = iemNativeEmitTbExitIfBitSetInGpr<kIemNativeLabelType_RaiseMf>(pReNative, off, idxFpuFswReg, X86_FSW_ES_BIT); 2715 2716 2716 2717 /* Free but don't flush the FSW register. */ … … 2769 2770 * be a safe assumption. 2770 2771 */ 2771 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1+6+3+3+7+7+6); 2772 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2773 1+6+3+3+7+7+6 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 2772 2774 //pCodeBuf[off++] = 0xcc; 2773 2775 off = iemNativeEmitLoadGpr32ImmEx(pCodeBuf, off, idxTmpReg, X86_CR4_OSFXSR); /* Isolate CR4.OSFXSR as CR4.TSD and */ … … 2776 2778 off = iemNativeEmitAndGpr32ByImmEx(pCodeBuf, off, idxTmpReg, X86_CR0_EM | X86_CR0_TS | X86_CR4_OSFXSR); 2777 2779 off = iemNativeEmitXorGpr32ByImmEx(pCodeBuf, off, idxTmpReg, X86_CR4_OSFXSR); 2778 off = iemNativeEmit JccTbExitEx(pReNative, pCodeBuf, off, kIemNativeLabelType_RaiseSseRelated, kIemNativeInstrCond_ne);2780 off = iemNativeEmitTbExitJccEx<kIemNativeLabelType_RaiseSseRelated>(pReNative, pCodeBuf, off, kIemNativeInstrCond_ne); 2779 2781 2780 2782 #elif defined(RT_ARCH_ARM64) … … 2784 2786 * else { goto RaiseSseRelated; } 2785 2787 */ 2786 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1+5); 2788 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2789 1+5 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 2787 2790 //pCodeBuf[off++] = Armv8A64MkInstrBrk(0x1111); 2788 2791 Assert(Armv8A64ConvertImmRImmS2Mask32(1, 32 - X86_CR0_EM_BIT) == (X86_CR0_EM | X86_CR0_TS)); … … 2793 2796 pCodeBuf[off++] = Armv8A64MkInstrEorImm(idxTmpReg, idxTmpReg, 0, 0, false /*f64Bit*/); 2794 2797 /* -> idxTmpReg[0]=~OSFXSR; idxTmpReg[2]=EM; idxTmpReg[3]=TS; (the rest is zero) */ 2795 off = iemNativeEmitT estIfGprIsNotZeroAndTbExitEx(pReNative, pCodeBuf, off, idxTmpReg, false /*f64Bit*/,2796 kIemNativeLabelType_RaiseSseRelated);2798 off = iemNativeEmitTbExitIfGprIsNotZeroEx<kIemNativeLabelType_RaiseSseRelated>(pReNative, pCodeBuf, off, 2799 idxTmpReg, false /*f64Bit*/); 2797 2800 2798 2801 #else … … 2870 2873 ^ 0x1a) ) { likely } 2871 2874 else { goto RaiseAvxRelated; } */ 2872 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1+6+3+5+3+5+3+7+6); 2875 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2876 1+6+3+5+3+5+3+7+6 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 2873 2877 //pCodeBuf[off++] = 0xcc; 2874 2878 off = iemNativeEmitLoadGpr32ImmEx(pCodeBuf, off, idxTmpReg, XSAVE_C_YMM | XSAVE_C_SSE); … … 2882 2886 off = iemNativeEmitXorGpr32ByImmEx(pCodeBuf, off, idxTmpReg, ((XSAVE_C_YMM | XSAVE_C_SSE) << 2) | 2); 2883 2887 /* -> idxTmpReg[0]=CR0.TS idxTmpReg[1]=~CR4.OSXSAVE; idxTmpReg[2]=0; idxTmpReg[3]=~SSE; idxTmpReg[4]=~YMM; */ 2884 off = iemNativeEmit JccTbExitEx(pReNative, pCodeBuf, off, kIemNativeLabelType_RaiseAvxRelated, kIemNativeInstrCond_ne);2888 off = iemNativeEmitTbExitJccEx<kIemNativeLabelType_RaiseAvxRelated>(pReNative, pCodeBuf, off, kIemNativeInstrCond_ne); 2885 2889 2886 2890 #elif defined(RT_ARCH_ARM64) … … 2888 2892 | ((cr0 >> X86_CR0_TS_BIT) & 1) ) { likely } 2889 2893 else { goto RaiseAvxRelated; } */ 2890 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1+6); 2894 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2895 1+6 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 2891 2896 //pCodeBuf[off++] = Armv8A64MkInstrBrk(0x1111); 2892 2897 Assert(Armv8A64ConvertImmRImmS2Mask32(1, 32 - XSAVE_C_SSE_BIT) == (XSAVE_C_YMM | XSAVE_C_SSE)); … … 2900 2905 pCodeBuf[off++] = Armv8A64MkInstrBfxil(idxTmpReg, idxCr0Reg, X86_CR0_TS_BIT, 1, false /*f64Bit*/); 2901 2906 /* -> idxTmpReg[0]=CR0.TS; idxTmpReg[1]=~CR4.OSXSAVE; idxTmpReg[2]=~SSE; idxTmpReg[3]=~YMM; (the rest is zero) */ 2902 off = iemNativeEmitT estIfGprIsNotZeroAndTbExitEx(pReNative, pCodeBuf, off, idxTmpReg, false /*f64Bit*/,2903 kIemNativeLabelType_RaiseAvxRelated);2907 off = iemNativeEmitTbExitIfGprIsNotZeroEx<kIemNativeLabelType_RaiseAvxRelated>(pReNative, pCodeBuf, off, 2908 idxTmpReg, false /*f64Bit*/); 2904 2909 2905 2910 #else … … 2952 2957 /* Do the job we're here for. */ 2953 2958 uint8_t const idxVarReg = iemNativeVarRegisterAcquire(pReNative, idxVar, &off); 2954 off = iemNativeEmitT estIfGprIsZeroAndTbExit(pReNative, off, idxVarReg, false /*f64Bit*/, kIemNativeLabelType_RaiseDe);2959 off = iemNativeEmitTbExitIfGprIsZero<kIemNativeLabelType_RaiseDe>(pReNative, off, idxVarReg, false /*f64Bit*/); 2955 2960 iemNativeVarRegisterRelease(pReNative, idxVar); 2956 2961 … … 2991 2996 2992 2997 uint8_t const idxVarReg = iemNativeVarRegisterAcquire(pReNative, idxVarEffAddr, &off); 2993 off = iemNativeEmitTestAnyBitsInGprAndTbExitIfAnySet(pReNative, off, idxVarReg, cbAlign - 1, 2994 kIemNativeLabelType_RaiseGp0); 2998 off = iemNativeEmitTbExitIfAnyBitsSetInGpr<kIemNativeLabelType_RaiseGp0>(pReNative, off, idxVarReg, cbAlign - 1); 2995 2999 iemNativeVarRegisterRelease(pReNative, idxVarEffAddr); 2996 3000 … … 4335 4339 * Make the call and update the return code variable if we've got one. 4336 4340 */ 4337 off = iemNativeEmitCallImm (pReNative, off, pfnAImpl);4341 off = iemNativeEmitCallImm<true /*a_fSkipEflChecks*/>(pReNative, off, pfnAImpl); 4338 4342 if (idxVarRc != UINT8_MAX) 4339 4343 iemNativeVarRegisterSet(pReNative, idxVarRc, IEMNATIVE_CALL_RET_GREG, off, false /*fAllocated*/); … … 5865 5869 # else 5866 5870 PCIEMLIVENESSENTRY const pLivenessEntry = &pReNative->paLivenessEntries[pReNative->idxCurCall]; 5867 IEMLIVENESSBIT const LivenessClobbered = 5868 { 5869 pLivenessEntry->aBits[IEMLIVENESS_BIT_WRITE].bm64 5870 & ~( pLivenessEntry->aBits[IEMLIVENESS_BIT_POTENTIAL_CALL].bm64 5871 | pLivenessEntry->aBits[IEMLIVENESS_BIT_READ].bm64 5872 | pLivenessEntry->aBits[IEMLIVENESS_BIT_CALL].bm64) 5873 }; 5874 IEMLIVENESSBIT const LivenessDelayable = 5875 { 5876 pLivenessEntry->aBits[IEMLIVENESS_BIT_POTENTIAL_CALL].bm64 5877 & pLivenessEntry->aBits[IEMLIVENESS_BIT_WRITE].bm64 5878 & ~( pLivenessEntry->aBits[IEMLIVENESS_BIT_READ].bm64 5879 | pLivenessEntry->aBits[IEMLIVENESS_BIT_CALL].bm64) 5880 }; 5871 IEMLIVENESSBIT const LivenessClobbered = { IEMLIVENESS_STATE_GET_WILL_BE_CLOBBERED_SET(pLivenessEntry) }; 5872 IEMLIVENESSBIT const LivenessDelayable = { IEMLIVENESS_STATE_GET_CAN_BE_POSTPONED_SET(pLivenessEntry) }; 5881 5873 # define CHECK_FLAG_AND_UPDATE_STATS(a_fEfl, a_fLivenessMember, a_CoreStatName) \ 5882 5874 if (fEflOutput & (a_fEfl)) \ … … 5989 5981 #define IEM_MC_COMMIT_EFLAGS_EX(a_EFlags, a_fEflInput, a_fEflOutput) \ 5990 5982 IEMNATIVE_EFLAGS_OPTIMIZATION_STATS(a_fEflInput, a_fEflOutput); \ 5991 off = iemNativeEmitCommitEFlags<true /* fUpdateSkipping*/, a_fEflOutput, \5983 off = iemNativeEmitCommitEFlags<true /*a_fUpdateSkippingAndPostponing*/, a_fEflOutput, \ 5992 5984 iemNativeEflagsToLivenessMask<a_fEflInput>(), \ 5993 5985 iemNativeEflagsToLivenessMask<a_fEflOutput>()>(pReNative, off, a_EFlags, a_fEflInput) … … 5996 5988 #define IEM_MC_COMMIT_EFLAGS_OPT_EX(a_EFlags, a_fEflInput, a_fEflOutput) \ 5997 5989 IEMNATIVE_EFLAGS_OPTIMIZATION_STATS(a_fEflInput, a_fEflOutput); \ 5998 off = iemNativeEmitCommitEFlags<false /* fUpdateSkipping*/, a_fEflOutput, \5990 off = iemNativeEmitCommitEFlags<false /*a_fUpdateSkippingAndPostponing*/, a_fEflOutput, \ 5999 5991 iemNativeEflagsToLivenessMask<a_fEflInput>(), \ 6000 5992 iemNativeEflagsToLivenessMask<a_fEflOutput>()>(pReNative, off, a_EFlags, a_fEflInput) 6001 5993 6002 5994 /** Handles IEM_MC_COMMIT_EFLAGS_EX. */ 6003 template<bool const a_fUpdateSkipping , uint32_t const a_fEflOutput,5995 template<bool const a_fUpdateSkippingAndPostponing, uint32_t const a_fEflOutput, 6004 5996 uint64_t const a_fLivenessEflInputBits, uint64_t const a_fLivenessEflOutputBits> 6005 5997 DECL_INLINE_THROW(uint32_t) … … 6052 6044 6053 6045 #ifdef IEMNATIVE_WITH_EFLAGS_SKIPPING 6054 if RT_CONSTEXPR_IF(a_fUpdateSkipping )6046 if RT_CONSTEXPR_IF(a_fUpdateSkippingAndPostponing) 6055 6047 { 6056 6048 Assert(!(pReNative->fSkippingEFlags & fElfInput)); RT_NOREF(fElfInput); … … 6066 6058 RT_UOFFSETOF(VMCPU, iem.s.fSkippingEFlags)); 6067 6059 # endif 6060 IEMNATIVE_CLEAR_POSTPONED_EFLAGS(pReNative, a_fEflOutput); 6068 6061 } 6069 6062 #endif … … 6252 6245 #define IEM_MC_REF_EFLAGS_EX(a_pEFlags, a_fEflInput, a_fEflOutput) \ 6253 6246 IEMNATIVE_EFLAGS_OPTIMIZATION_STATS(a_fEflInput, a_fEflOutput); \ 6254 off = iemNativeEmitRefEFlags (pReNative, off, a_pEFlags, a_fEflInput, a_fEflOutput)6247 off = iemNativeEmitRefEFlags<a_fEflOutput>(pReNative, off, a_pEFlags, a_fEflInput) 6255 6248 6256 6249 /** Handles IEM_MC_REF_EFLAGS. */ 6257 DECL_INLINE_THROW(uint32_t) 6258 iemNativeEmitRefEFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarRef, uint32_t fEflInput, uint32_t fEflOutput) 6250 template<uint32_t const a_fEflOutput> 6251 DECL_INLINE_THROW(uint32_t) 6252 iemNativeEmitRefEFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarRef, uint32_t fEflInput) 6259 6253 { 6260 6254 iemNativeVarSetKindToGstRegRef(pReNative, idxVarRef, kIemNativeGstRegRef_EFlags, 0); … … 6264 6258 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_AND_POSTPONING(pReNative, fEflInput); 6265 6259 IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(pReNative, off, fEflInput); 6266 pReNative->fSkippingEFlags &= ~ fEflOutput;6260 pReNative->fSkippingEFlags &= ~a_fEflOutput; 6267 6261 # ifdef IEMNATIVE_STRICT_EFLAGS_SKIPPING 6268 6262 6269 6263 /* Updating the skipping according to the outputs is a little early, but 6270 6264 we don't have any other hooks for references atm. */ 6271 if ((fEflOutput & X86_EFL_STATUS_BITS) == X86_EFL_STATUS_BITS)6265 if RT_CONSTEXPR((a_fEflOutput & X86_EFL_STATUS_BITS) == X86_EFL_STATUS_BITS) 6272 6266 off = iemNativeEmitStoreImmToVCpuU32(pReNative, off, 0, RT_UOFFSETOF(VMCPU, iem.s.fSkippingEFlags)); 6273 else if (fEflOutput & X86_EFL_STATUS_BITS)6274 off = iemNativeEmitAndImmIntoVCpuU32(pReNative, off, ~( fEflOutput & X86_EFL_STATUS_BITS),6267 else if RT_CONSTEXPR((a_fEflOutput & X86_EFL_STATUS_BITS) != 0) 6268 off = iemNativeEmitAndImmIntoVCpuU32(pReNative, off, ~(a_fEflOutput & X86_EFL_STATUS_BITS), 6275 6269 RT_UOFFSETOF(VMCPU, iem.s.fSkippingEFlags)); 6276 6270 # endif 6277 #endif 6278 RT_NOREF(fEflInput, fEflOutput); 6271 6272 /* This ASSUMES that EFLAGS references are not taken before use. */ 6273 IEMNATIVE_CLEAR_POSTPONED_EFLAGS(pReNative, a_fEflOutput); 6274 6275 #endif 6276 RT_NOREF(fEflInput); 6279 6277 6280 6278 /* If we've delayed writing back the register value, flush it now. */ … … 11055 11053 * Make the call. 11056 11054 */ 11057 off = iemNativeEmitCallImm (pReNative, off, pfnAImpl);11055 off = iemNativeEmitCallImm<true /*a_fSkipEflChecks*/>(pReNative, off, pfnAImpl); 11058 11056 11059 11057 /* … … 11097 11095 /* tmp &= mxcsr */ 11098 11096 off = iemNativeEmitAndGpr32ByGpr32(pReNative, off, idxRegTmp, idxRegTmp2); 11099 off = iemNativeEmitT estAnyBitsInGprAndTbExitIfAnySet(pReNative, off, idxRegTmp, X86_MXCSR_XCPT_FLAGS,11100 kIemNativeLabelType_RaiseSseAvxFpRelated);11097 off = iemNativeEmitTbExitIfAnyBitsSetInGpr<kIemNativeLabelType_RaiseSseAvxFpRelated>(pReNative, off, idxRegTmp, 11098 X86_MXCSR_XCPT_FLAGS); 11101 11099 11102 11100 iemNativeRegFreeTmp(pReNative, idxRegTmp2); -
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
r106136 r106180 9 9 * - Level 3 (Log3) : Disassemble native code after recompiling. 10 10 * - Level 4 (Log4) : Delayed PC updating. 11 * - Level 5 (Log5) : ...11 * - Level 5 (Log5) : Postponed and skipped EFLAGS calculations. 12 12 * - Level 6 (Log6) : ... 13 13 * - Level 7 (Log7) : ... … … 78 78 #include "IEMN8veRecompilerTlbLookup.h" 79 79 #include "IEMNativeFunctions.h" 80 #include "target-x86/IEMAllN8veEmit-x86.h" 80 81 81 82 … … 2070 2071 #endif 2071 2072 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 2072 pReNative->fPostponingEFlags = 0; 2073 pReNative->PostponedEfl.fEFlags = 0; 2074 pReNative->PostponedEfl.enmOp = kIemNativePostponedEflOp_Invalid; 2075 pReNative->PostponedEfl.cOpBits = 0; 2076 pReNative->PostponedEfl.idxReg1 = UINT8_MAX; 2077 pReNative->PostponedEfl.idxReg2 = UINT8_MAX; 2073 2078 #endif 2074 2079 … … 6442 6447 6443 6448 /* Jump to non-zero status return path. */ 6444 off = iemNativeEmit JnzTbExit(pReNative, off, kIemNativeLabelType_NonZeroRetOrPassUp);6449 off = iemNativeEmitTbExitJnz<kIemNativeLabelType_NonZeroRetOrPassUp>(pReNative, off); 6445 6450 6446 6451 /* done. */ … … 6450 6455 * ARM64: w0 = call status code. 6451 6456 */ 6457 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1+3+3 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 6458 6452 6459 # ifdef IEMNATIVE_WITH_INSTRUCTION_COUNTING 6453 off = iemNativeEmitLoadGprImm64(pReNative, off, ARMV8_A64_REG_X2, idxInstr); 6460 AssertCompile(ARMV8_A64_REG_X2 == IEMNATIVE_CALL_ARG2_GREG); 6461 off = iemNativeEmitLoadGprImmEx(pCodeBuf, off, ARMV8_A64_REG_X2, idxInstr); 6454 6462 # endif 6455 off = iemNativeEmitLoadGprFromVCpuU32(pReNative, off, ARMV8_A64_REG_X3, RT_UOFFSETOF(VMCPUCC, iem.s.rcPassUp)); 6456 6457 uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3); 6458 6459 pu32CodeBuf[off++] = Armv8A64MkInstrOrr(ARMV8_A64_REG_X4, ARMV8_A64_REG_X3, ARMV8_A64_REG_X0, false /*f64Bit*/); 6460 6461 off = iemNativeEmitTestIfGprIsNotZeroAndTbExitEx(pReNative, pu32CodeBuf, off, ARMV8_A64_REG_X4, true /*f64Bit*/, 6462 kIemNativeLabelType_NonZeroRetOrPassUp); 6463 off = iemNativeEmitLoadGprFromVCpuU32Ex(pCodeBuf, off, ARMV8_A64_REG_X3, RT_UOFFSETOF(VMCPUCC, iem.s.rcPassUp)); 6464 6465 pCodeBuf[off++] = Armv8A64MkInstrOrr(ARMV8_A64_REG_X4, ARMV8_A64_REG_X3, ARMV8_A64_REG_X0, false /*f64Bit*/); 6466 6467 off = iemNativeEmitTbExitIfGprIsNotZeroEx<kIemNativeLabelType_NonZeroRetOrPassUp>(pReNative, pCodeBuf, off, 6468 ARMV8_A64_REG_X4, true /*f64Bit*/); 6463 6469 6464 6470 #else … … 9990 9996 = szSegSel[X86_SREG_COUNT] = '\0'; 9991 9997 9992 char szEFlags[ 8];9993 for (unsigned i = 0; i < 7; i++)9998 char szEFlags[IEMLIVENESSBIT_IDX_EFL_COUNT + 1]; 9999 for (unsigned i = 0; i < IEMLIVENESSBIT_IDX_EFL_COUNT; i++) 9994 10000 szEFlags[i] = s_achState[iemNativeLivenessGetStateByGstRegEx(pLivenessEntry, i + kIemNativeGstReg_EFlags)]; 9995 10001 szEFlags[7] = '\0'; 9996 10002 9997 Log2(("liveness: g rp=%s segbase=%s segattr=%s seglim=%s segsel=%s efl=%s\n",10003 Log2(("liveness: gpr=%s segbase=%s segattr=%s seglim=%s segsel=%s efl=%s\n", 9998 10004 szGpr, szSegBase, szSegAttrib, szSegLimit, szSegSel, szEFlags)); 9999 10005 } … … 10027 10033 */ 10028 10034 //off = iemNativeEmitBrk(pReNative, off, 0x1227); 10029 off = iemNativeEmitTbExit (pReNative, off, kIemNativeLabelType_ReturnSuccess);10035 off = iemNativeEmitTbExit<kIemNativeLabelType_ReturnSuccess, true, false>(pReNative, off); 10030 10036 10031 10037 /* … … 10039 10045 if (fTailLabels) 10040 10046 { 10047 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, kIemNativeLabelType_LastTbExit + 1); 10041 10048 do 10042 10049 { … … 10047 10054 AssertContinue(idxLabel != UINT32_MAX); 10048 10055 iemNativeLabelDefine(pReNative, idxLabel, off); 10049 off = iemNativeEmitTbExit(pReNative, off, enmLabel); 10056 10057 iemNativeAddTbExitFixup(pReNative, off, enmLabel); 10058 # ifdef RT_ARCH_ARM64 10059 pCodeBuf[off++] = Armv8A64MkInstrB(-1); 10060 # else 10061 # error "port me" 10062 # endif 10050 10063 } while (fTailLabels); 10064 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 10051 10065 } 10052 10066 #else -
trunk/src/VBox/VMM/VMMAll/target-x86/IEMAllN8veEmit-x86.h
r106123 r106180 195 195 #endif /* RT_ARCH_AMD64 */ 196 196 197 198 199 /********************************************************************************************************************************* 200 * EFLAGS * 201 *********************************************************************************************************************************/ 202 203 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 204 205 /** @def IEMNATIVE_POSTPONING_REG_MASK 206 * Register suitable for keeping the inputs or result for a postponed EFLAGS 207 * calculation. 208 * 209 * We use non-volatile register here so we don't have to save & restore them 210 * accross callouts (i.e. TLB loads). 211 * 212 * @note On x86 we cannot use RDI and RSI because these are used by the 213 * opcode checking code. The usual joy of the x86 instruction set. 214 */ 215 # ifdef RT_ARCH_AMD64 216 # define IEMNATIVE_POSTPONING_REG_MASK \ 217 (IEMNATIVE_CALL_NONVOLATILE_GREG_MASK & ~(RT_BIT_32(X86_GREG_xDI) | RT_BIT_32(X86_GREG_xSI))) 218 # else 219 # define IEMNATIVE_POSTPONING_REG_MASK IEMNATIVE_CALL_NONVOLATILE_GREG_MASK 220 # endif 221 222 /** 223 * This is normally invoked via IEMNATIVE_CLEAR_POSTPONED_EFLAGS(). 224 */ 225 template<uint32_t const a_fEflClobbered> 226 DECL_FORCE_INLINE(void) iemNativeClearPostponedEFlags(PIEMRECOMPILERSTATE pReNative) 227 { 228 AssertCompile(!(a_fEflClobbered & ~X86_EFL_STATUS_BITS)); 229 uint32_t fEFlags = pReNative->PostponedEfl.fEFlags; 230 if (fEFlags) 231 { 232 if RT_CONSTEXPR(a_fEflClobbered != X86_EFL_STATUS_BITS) 233 { 234 fEFlags &= ~a_fEflClobbered; 235 if (!fEFlags) 236 { /* likely */ } 237 else 238 { 239 Log5(("iemNativeClearPostponedEFlags: Clobbering %#x: %#x -> %#x (op=%d bits=%u)\n", a_fEflClobbered, 240 pReNative->PostponedEfl.fEFlags, fEFlags, pReNative->PostponedEfl.enmOp, pReNative->PostponedEfl.cOpBits)); 241 pReNative->PostponedEfl.fEFlags = fEFlags; 242 return; 243 } 244 } 245 246 /* Do cleanup. */ 247 Log5(("iemNativeClearPostponedEFlags: Cleanup of op=%u bits=%u efl=%#x upon clobbering %#x\n", 248 pReNative->PostponedEfl.enmOp, pReNative->PostponedEfl.cOpBits, pReNative->PostponedEfl.fEFlags, a_fEflClobbered)); 249 pReNative->PostponedEfl.fEFlags = 0; 250 pReNative->PostponedEfl.enmOp = kIemNativePostponedEflOp_Invalid; 251 pReNative->PostponedEfl.cOpBits = 0; 252 iemNativeRegFreeTmp(pReNative, pReNative->PostponedEfl.idxReg1); 253 if (pReNative->PostponedEfl.idxReg2 != UINT8_MAX) 254 iemNativeRegFreeTmp(pReNative, pReNative->PostponedEfl.idxReg2); 255 pReNative->PostponedEfl.idxReg1 = UINT8_MAX; 256 pReNative->PostponedEfl.idxReg2 = UINT8_MAX; 257 } 258 } 259 260 DECL_INLINE_THROW(uint32_t) iemNativeEmitPostponedEFlagsCalcLogical(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t cOpBits, 261 uint8_t idxRegResult, uint8_t idxRegEfl, uint8_t idxRegTmp) 262 { 263 #ifdef RT_ARCH_AMD64 264 /* 265 * Do an AND and collect flags and merge them with eflags. 266 */ 267 /* Do TEST idxRegResult, idxRegResult to set flags. */ 268 off = iemNativeEmitAmd64OneByteModRmInstrRREx(pCodeBuf, off, 0x84, 0x85, cOpBits, idxRegResult, idxRegResult); 269 270 if (idxRegTmp == X86_GREG_xAX) 271 { 272 /* sahf ; AH = EFLAGS */ 273 pCodeBuf[off++] = 0x9e; 274 if (idxRegEfl <= X86_GREG_xBX) 275 { 276 /* mov [CDB]L, AH */ 277 pCodeBuf[off++] = 0x88; 278 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4 /*AH*/, idxRegEfl); 279 } 280 else 281 { 282 /* mov AL, AH */ 283 pCodeBuf[off++] = 0x88; 284 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4 /*AH*/, 0 /*AL*/); 285 /* mov xxL, AL */ 286 pCodeBuf[off++] = idxRegEfl >= 8 ? X86_OP_REX_B : X86_OP_REX; 287 pCodeBuf[off++] = 0x88; 288 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 0 /*AL*/, idxRegEfl & 7); 289 } 290 } 291 else if (idxRegEfl != X86_GREG_xAX) 292 { 293 /* pushf */ 294 pCodeBuf[off++] = 0x9c; 295 /* pop tmp */ 296 if (idxRegTmp >= 8) 297 pCodeBuf[off++] = X86_OP_REX_B; 298 pCodeBuf[off++] = 0x58 + (idxRegTmp & 7); 299 /* mov byte(efl), byte(tmp) */ 300 pCodeBuf[off++] = (idxRegEfl >= 8 ? X86_OP_REX_B : X86_OP_REX) 301 | (idxRegTmp >= 8 ? X86_OP_REX_R : 0); 302 pCodeBuf[off++] = 0x88; 303 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, idxRegTmp & 7, idxRegEfl & 7); 304 } 305 else 306 { 307 /* xchg al, ah */ 308 pCodeBuf[off++] = 0x86; 309 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4 /*AH*/, 0 /*AL*/); 310 /* sahf ; AH = EFLAGS */ 311 pCodeBuf[off++] = 0x9e; 312 /* xchg al, ah */ 313 pCodeBuf[off++] = 0x86; 314 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4 /*AH*/, 0 /*AL*/); 315 } 316 /* BTC idxEfl, 11; Clear OF */ 317 if (idxRegEfl >= 8) 318 pCodeBuf[off++] = X86_OP_REX_B; 319 pCodeBuf[off++] = 0xf; 320 pCodeBuf[off++] = 0xba; 321 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, idxRegEfl & 7); 322 pCodeBuf[off++] = X86_EFL_OF_BIT; 323 324 #elif defined(RT_ARCH_ARM64) 325 /* 326 * Calculate flags. 327 */ 328 /* Clear the status bits. ~0x8D5 (or ~0x8FD) can't be AND immediate, so use idxRegTmp for constant. */ 329 off = iemNativeEmitLoadGpr32ImmExT<~X86_EFL_STATUS_BITS>(pCodeBuf, off, idxRegTmp); 330 off = iemNativeEmitAndGpr32ByGpr32Ex(pCodeBuf, off, idxRegEfl, idxRegTmp); 331 332 /* N,Z -> SF,ZF */ 333 if (cOpBits < 32) 334 pCodeBuf[off++] = Armv8A64MkInstrSetF8SetF16(idxRegResult, cOpBits > 8); /* sets NZ */ 335 else 336 pCodeBuf[off++] = Armv8A64MkInstrAnds(ARMV8_A64_REG_XZR, idxRegResult, idxRegResult, cOpBits > 32 /*f64Bit*/); 337 pCodeBuf[off++] = Armv8A64MkInstrMrs(idxRegTmp, ARMV8_AARCH64_SYSREG_NZCV); /* Bits: 31=N; 30=Z; 29=C; 28=V; */ 338 pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxRegTmp, idxRegTmp, 30); 339 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxRegTmp, X86_EFL_ZF_BIT, 2, false /*f64Bit*/); 340 AssertCompile(X86_EFL_ZF_BIT + 1 == X86_EFL_SF_BIT); 341 342 /* Calculate 8-bit parity of the result. */ 343 pCodeBuf[off++] = Armv8A64MkInstrEor(idxRegTmp, idxRegResult, idxRegResult, false /*f64Bit*/, 344 4 /*offShift6*/, kArmv8A64InstrShift_Lsr); 345 pCodeBuf[off++] = Armv8A64MkInstrEor(idxRegTmp, idxRegTmp, idxRegTmp, false /*f64Bit*/, 346 2 /*offShift6*/, kArmv8A64InstrShift_Lsr); 347 pCodeBuf[off++] = Armv8A64MkInstrEor(idxRegTmp, idxRegTmp, idxRegTmp, false /*f64Bit*/, 348 1 /*offShift6*/, kArmv8A64InstrShift_Lsr); 349 Assert(Armv8A64ConvertImmRImmS2Mask32(0, 0) == 1); 350 pCodeBuf[off++] = Armv8A64MkInstrEorImm(idxRegTmp, idxRegTmp, 0, 0, false /*f64Bit*/); 351 pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxRegTmp, X86_EFL_PF_BIT, 1, false /*f64Bit*/); 352 353 #else 354 # error "port me" 355 #endif 356 return off; 357 } 358 359 360 template<uint32_t const a_bmInputRegs> 361 static uint32_t iemNativeDoPostponedEFlagsAtTbExitInternal(PIEMRECOMPILERSTATE pReNative, uint32_t off, PIEMNATIVEINSTR pCodeBuf) 362 { 363 /* 364 * We can't do regular register allocations here, but since we're in an exit 365 * path where all pending writes has been flushed and we have a known set of 366 * registers with input for the exit label, we do our own simple stuff here. 367 * 368 * Note! On x86 we prefer using RAX as the first TMP register, so we can 369 * make use of LAHF which is typically faster than PUSHF/POP. This 370 * is why the idxRegTmp allocation is first when there is no EFLAG 371 * shadow, since RAX is represented by bit 0 in the mask. 372 */ 373 uint32_t bmAvailableRegs = ~(a_bmInputRegs | IEMNATIVE_REG_FIXED_MASK) & IEMNATIVE_HST_GREG_MASK; 374 if (pReNative->PostponedEfl.idxReg2 != UINT8_MAX) 375 bmAvailableRegs &= ~(RT_BIT_32(pReNative->PostponedEfl.idxReg1) | RT_BIT_32(pReNative->PostponedEfl.idxReg2)); 376 else 377 bmAvailableRegs &= ~RT_BIT_32(pReNative->PostponedEfl.idxReg1); 378 379 /* Use existing EFLAGS shadow if available. */ 380 uint8_t idxRegEfl, idxRegTmp; 381 if (pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(kIemNativeGstReg_EFlags)) 382 { 383 idxRegEfl = pReNative->Core.aidxGstRegShadows[kIemNativeGstReg_EFlags]; 384 Assert(idxRegEfl < IEMNATIVE_HST_GREG_COUNT && (bmAvailableRegs & RT_BIT_32(idxRegEfl))); 385 bmAvailableRegs &= ~RT_BIT_32(idxRegEfl); 386 #ifdef VBOX_STRICT 387 /** @todo check shadow register content. */ 388 #endif 389 390 idxRegTmp = ASMBitFirstSetU32(bmAvailableRegs) - 1; 391 bmAvailableRegs &= ~RT_BIT_32(idxRegTmp); 392 } 393 else 394 { 395 idxRegTmp = ASMBitFirstSetU32(bmAvailableRegs) - 1; /* allocate the temp register first to prioritize EAX on x86. */ 396 bmAvailableRegs &= ~RT_BIT_32(idxRegTmp); 397 398 idxRegEfl = ASMBitFirstSetU32(bmAvailableRegs) - 1; 399 bmAvailableRegs &= ~RT_BIT_32(idxRegTmp); 400 off = iemNativeEmitLoadGprFromVCpuU32Ex(pCodeBuf, off, idxRegEfl, RT_UOFFSETOF(VMCPU, cpum.GstCtx.eflags)); 401 } 402 Assert(bmAvailableRegs != 0); 403 404 /* 405 * Do the actual EFLAGS calculation. 406 */ 407 switch (pReNative->PostponedEfl.enmOp) 408 { 409 case kIemNativePostponedEflOp_Logical: 410 Assert(pReNative->PostponedEfl.idxReg2 == UINT8_MAX); 411 off = iemNativeEmitPostponedEFlagsCalcLogical(pCodeBuf, off, pReNative->PostponedEfl.cOpBits, 412 pReNative->PostponedEfl.idxReg1, idxRegEfl, idxRegTmp); 413 break; 414 415 default: 416 AssertFailedBreak(); 417 } 418 419 /* 420 * Store EFLAGS. 421 */ 422 off = iemNativeEmitStoreGprToVCpuU32Ex(pCodeBuf, off, idxRegEfl, RT_UOFFSETOF(VMCPU, cpum.GstCtx.eflags)); 423 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 424 425 return off; 426 } 427 428 429 430 template<uint32_t const a_bmInputRegs> 431 DECL_FORCE_INLINE_THROW(uint32_t) 432 iemNativeDoPostponedEFlagsAtTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off) 433 { 434 if (pReNative->PostponedEfl.fEFlags) 435 { 436 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 437 return iemNativeDoPostponedEFlagsAtTbExitInternal<a_bmInputRegs>(pReNative, off, pCodeBuf); 438 } 439 return off; 440 } 441 442 443 template<uint32_t const a_bmInputRegs> 444 DECL_FORCE_INLINE_THROW(uint32_t) 445 iemNativeDoPostponedEFlagsAtTbExitEx(PIEMRECOMPILERSTATE pReNative, uint32_t off, PIEMNATIVEINSTR pCodeBuf) 446 { 447 if (pReNative->PostponedEfl.fEFlags) 448 return iemNativeDoPostponedEFlagsAtTbExitInternal<a_bmInputRegs>(pReNative, off, pCodeBuf); 449 return off; 450 } 451 452 453 #endif /* IEMNATIVE_WITH_EFLAGS_POSTPONING */ 454 455 197 456 /** 198 457 * This is an implementation of IEM_EFL_UPDATE_STATUS_BITS_FOR_LOGICAL. … … 201 460 */ 202 461 DECL_INLINE_THROW(uint32_t) 203 iemNativeEmitEFlagsForLogical(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEfl 462 iemNativeEmitEFlagsForLogical(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEfl, 463 uint8_t cOpBits, uint8_t idxRegResult 204 464 #ifndef RT_ARCH_AMD64 205 , uint8_t cOpBits, uint8_t idxRegResult,bool fNativeFlags = false465 , bool fNativeFlags = false 206 466 #endif 207 467 ) 208 468 { 209 469 STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativeEflTotalLogical); 470 IEMNATIVE_CLEAR_POSTPONED_EFLAGS(pReNative, X86_EFL_STATUS_BITS); 471 RT_NOREF(cOpBits, idxRegResult); 210 472 211 473 #ifdef IEMNATIVE_WITH_EFLAGS_SKIPPING … … 214 476 */ 215 477 PCIEMLIVENESSENTRY const pLivenessEntry = &pReNative->paLivenessEntries[pReNative->idxCurCall]; 216 if ( IEMLIVENESS_STATE_ARE_STATUS_EFL_TO_BE_CLOBBERED(pLivenessEntry) 478 uint64_t const fEflClobbered = IEMLIVENESS_STATE_GET_WILL_BE_CLOBBERED_SET(pLivenessEntry) 479 & IEMLIVENESSBIT_STATUS_EFL_MASK; 480 # ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 481 uint64_t fEflPostponing; 482 # endif 483 if ( fEflClobbered == IEMLIVENESSBIT_STATUS_EFL_MASK 217 484 && !(pReNative->fMc & IEM_MC_F_WITH_FLAGS)) 218 485 { … … 222 489 off = iemNativeEmitOrImmIntoVCpuU32(pReNative, off, X86_EFL_STATUS_BITS, RT_UOFFSETOF(VMCPU, iem.s.fSkippingEFlags)); 223 490 # endif 224 } 491 Log5(("iemNativeEmitEFlagsForLogical: Skipping %#x\n", X86_EFL_STATUS_BITS)); 492 } 493 # ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 494 else if ( ( (fEflPostponing = IEMLIVENESS_STATE_GET_CAN_BE_POSTPONED_SET(pLivenessEntry) & IEMLIVENESSBIT_STATUS_EFL_MASK) 495 | fEflClobbered) 496 == IEMLIVENESSBIT_STATUS_EFL_MASK 497 && idxRegResult != UINT8_MAX) 498 { 499 STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativeEflPostponedLogical); 500 pReNative->fSkippingEFlags = 0; 501 pReNative->PostponedEfl.fEFlags = X86_EFL_STATUS_BITS; 502 pReNative->PostponedEfl.enmOp = kIemNativePostponedEflOp_Logical; 503 pReNative->PostponedEfl.cOpBits = cOpBits; 504 pReNative->PostponedEfl.idxReg1 = iemNativeRegAllocTmpEx(pReNative, &off, IEMNATIVE_POSTPONING_REG_MASK, false); 505 /** @todo it would normally be possible to use idxRegResult, iff it is 506 * already a non-volatile register and we can be user the caller 507 * doesn't modify it. That'll save a register move and allocation. */ 508 off = iemNativeEmitLoadGprFromGpr(pReNative, off, pReNative->PostponedEfl.idxReg1, idxRegResult); 509 Log5(("iemNativeEmitEFlagsForLogical: Postponing %#x op=%u bits=%u reg1=%u\n", X86_EFL_STATUS_BITS, 510 kIemNativePostponedEflOp_Logical, cOpBits, pReNative->PostponedEfl.idxReg1)); 511 } 512 # endif 225 513 else 226 514 #endif … … 317 605 { 318 606 STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativeEflTotalArithmetic); 607 IEMNATIVE_CLEAR_POSTPONED_EFLAGS(pReNative, X86_EFL_STATUS_BITS); 319 608 320 609 #ifdef IEMNATIVE_WITH_EFLAGS_SKIPPING … … 504 793 505 794 795 796 /********************************************************************************************************************************* 797 * Bitwise Logical Operations * 798 *********************************************************************************************************************************/ 799 506 800 /** 507 801 * The AND instruction will clear OF, CF and AF (latter is undefined) and … … 521 815 iemNativeVarRegisterRelease(pReNative, idxVarSrc); 522 816 523 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl );817 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, idxRegDst); 524 818 525 819 #elif defined(RT_ARCH_ARM64) … … 553 847 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 554 848 555 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl );849 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, idxRegDst); 556 850 557 851 #elif defined(RT_ARCH_ARM64) … … 628 922 629 923 #ifdef RT_ARCH_AMD64 630 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl );924 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, UINT8_MAX); 631 925 #else 632 926 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, idxRegResult, cOpBits >= 32 /*fNativeFlags*/); … … 652 946 iemNativeVarRegisterRelease(pReNative, idxVarDst); 653 947 654 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl );948 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, UINT8_MAX); 655 949 656 950 #elif defined(RT_ARCH_ARM64) … … 712 1006 iemNativeVarRegisterRelease(pReNative, idxVarSrc); 713 1007 714 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl );1008 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, idxRegDst); 715 1009 716 1010 #elif defined(RT_ARCH_ARM64) … … 745 1039 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 746 1040 747 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl );1041 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, idxRegDst); 748 1042 749 1043 #elif defined(RT_ARCH_ARM64) … … 795 1089 iemNativeVarRegisterRelease(pReNative, idxVarSrc); 796 1090 797 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl );1091 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, idxRegDst); 798 1092 799 1093 #elif defined(RT_ARCH_ARM64) … … 828 1122 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 829 1123 830 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl );1124 off = iemNativeEmitEFlagsForLogical(pReNative, off, idxVarEfl, cOpBits, idxRegDst); 831 1125 832 1126 #elif defined(RT_ARCH_ARM64) … … 2733 3027 /* tmp &= mxcsr */ 2734 3028 off = iemNativeEmitAndGpr32ByGpr32(pReNative, off, idxRegMxCsrXcptFlags, idxRegTmp); 2735 off = iemNativeEmitT estAnyBitsInGprAndTbExitIfAnySet(pReNative, off, idxRegMxCsrXcptFlags, X86_MXCSR_XCPT_FLAGS,2736 kIemNativeLabelType_RaiseSseAvxFpRelated);3029 off = iemNativeEmitTbExitIfAnyBitsSetInGpr<kIemNativeLabelType_RaiseSseAvxFpRelated>(pReNative, off, idxRegMxCsrXcptFlags, 3030 X86_MXCSR_XCPT_FLAGS); 2737 3031 2738 3032 uint8_t const idxSimdRegDst = iemNativeSimdRegAllocTmpForGuestSimdReg(pReNative, &off, IEMNATIVEGSTSIMDREG_SIMD(idxSimdGstRegDst),
Note:
See TracChangeset
for help on using the changeset viewer.