Changeset 106180 in vbox
- Timestamp:
- Sep 30, 2024 1:51:48 PM (5 months ago)
- svn:sync-xref-src-repo-rev:
- 164964
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 9 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), -
trunk/src/VBox/VMM/VMMR3/IEMR3.cpp
r106101 r106180 731 731 "/IEM/CPU%u/re/NativeRegFindFreeLivenessHelped", idCpu); 732 732 733 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflSkippedArithmetic, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 734 "Skipped all status flag updating, arithmetic instructions", 735 "/IEM/CPU%u/re/NativeEFlags/ArithmeticSkipped", idCpu); 736 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflTotalArithmetic, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 737 "Total number of arithmetic intructions with status flag updating", 738 "/IEM/CPU%u/re/NativeEFlags/ArithmeticTotal", idCpu); 739 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeEFlags/ArithmeticTotal", idCpu); 740 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeEFlags/ArithmeticSkipped", idCpu); 741 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat, 742 "Skipped all status flag updating, arithmetic instructions, percentage", 743 "/IEM/CPU%u/re/NativeEFlags/ArithmeticSkippedPct", idCpu); 744 745 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflSkippedLogical, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 746 "Skipped all status flag updating, logical instructions", 747 "/IEM/CPU%u/re/NativeEFlags/LogicalSkipped", idCpu); 748 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflTotalLogical, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 749 "Total number of logical intructions with status flag updating", 750 "/IEM/CPU%u/re/NativeEFlags/LogicalTotal", idCpu); 751 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeEFlags/LogicalTotal", idCpu); 752 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeEFlags/LogicalSkipped", idCpu); 753 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat, 754 "Skipped all status flag updating, logical instructions, percentage", 755 "/IEM/CPU%u/re/NativeEFlags/LogicalSkippedPct", idCpu); 756 757 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflSkippedShift, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 758 "Skipped all status flag updating, shift instructions", 759 "/IEM/CPU%u/re/NativeEFlags/ShiftSkipped", idCpu); 760 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflTotalShift, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, 761 "Total number of shift intructions with status flag updating", 762 "/IEM/CPU%u/re/NativeEFlags/ShiftTotal", idCpu); 763 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeEFlags/ShiftTotal", idCpu); 764 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeEFlags/ShiftSkipped", idCpu); 765 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat, 766 "Skipped all status flag updating, shift instructions, percentage", 767 "/IEM/CPU%u/re/NativeEFlags/ShiftSkippedPct", idCpu); 733 # define REG_NATIVE_EFL_GROUP(a_Lower, a_Camel) do { \ 734 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflPostponed ## a_Camel, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, \ 735 "Postponed all status flag updating, " #a_Lower " instructions", \ 736 "/IEM/CPU%u/re/NativeEFlags/" #a_Camel "Postponed", idCpu); \ 737 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflSkipped ## a_Camel, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, \ 738 "Skipped all status flag updating, " #a_Lower " instructions", \ 739 "/IEM/CPU%u/re/NativeEFlags/" #a_Camel "Skipped", idCpu); \ 740 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflTotal ## a_Camel, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, \ 741 "Total number of " #a_Lower " intructions with status flag updating", \ 742 "/IEM/CPU%u/re/NativeEFlags/" #a_Camel "Total", idCpu); \ 743 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeEFlags/" #a_Camel "Total", idCpu); \ 744 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeEFlags/" #a_Camel "Postponed", idCpu); \ 745 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat, \ 746 "Postponed all status flag updating, " #a_Lower " instructions, percentage", \ 747 "/IEM/CPU%u/re/NativeEFlags/" #a_Camel "PostponedPct", idCpu); \ 748 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeEFlags/" #a_Camel "Skipped", idCpu); \ 749 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat, \ 750 "Skipped all status flag updating, " #a_Lower " instructions, percentage", \ 751 "/IEM/CPU%u/re/NativeEFlags/" #a_Camel "SkippedPct", idCpu); \ 752 } while (0) 753 REG_NATIVE_EFL_GROUP(arithmetic, Arithmetic); 754 REG_NATIVE_EFL_GROUP(logical, Logical); 755 REG_NATIVE_EFL_GROUP(shift, Shift); 756 # undef REG_NATIVE_EFL_GROUP 768 757 769 758 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflCfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.CF updating", "/IEM/CPU%u/re/NativeLivenessEFlags/CfSkippable", idCpu); -
trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
r106127 r106180 80 80 # if 0 || defined(DOXYGEN_RUNNING) 81 81 # define IEMNATIVE_WITH_EFLAGS_POSTPONING 82 # endif 83 #endif 84 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 85 # ifndef IEMNATIVE_WITH_EFLAGS_SKIPPING 86 # error "IEMNATIVE_WITH_EFLAGS_POSTPONING requires IEMNATIVE_WITH_EFLAGS_SKIPPING at present" 82 87 # endif 83 88 #endif … … 314 319 * Mask of registers the callee will not save and may trash. */ 315 320 #ifdef RT_ARCH_AMD64 316 # define IEMNATIVE_CALL_RET_GREG 321 # define IEMNATIVE_CALL_RET_GREG X86_GREG_xAX 317 322 318 323 # ifdef RT_OS_WINDOWS … … 435 440 # define IEMNATIVE_CALL_VOLATILE_NOTMP_GREG_MASK IEMNATIVE_CALL_VOLATILE_GREG_MASK 436 441 #endif 442 443 /** @def IEMNATIVE_CALL_NONVOLATILE_GREG_MASK 444 * The allocatable non-volatile general purpose register set. */ 445 #define IEMNATIVE_CALL_NONVOLATILE_GREG_MASK \ 446 (~IEMNATIVE_CALL_VOLATILE_GREG_MASK & ~IEMNATIVE_REG_FIXED_MASK & IEMNATIVE_HST_GREG_MASK) 437 447 /** @} */ 438 448 … … 480 490 { 481 491 kIemNativeLabelType_Invalid = 0, 482 /* 483 * Labels w/o data, only once instance per TB - aka exit reasons. 492 /** @name Exit reasons - Labels w/o data, only once instance per TB. 484 493 * 485 * Note! Jumps to these requires instructions that are capable of spanning 486 * the max TB length. 494 * The labels requiring register inputs are documented. 495 * 496 * @note Jumps to these requires instructions that are capable of spanning the 497 * max TB length. 498 * @{ 487 499 */ 488 500 /* Simple labels comes first for indexing reasons. RaiseXx is order by the exception's numerical value(s). */ … … 496 508 kIemNativeLabelType_RaiseMf, /**< Raise (throw) X86_XCPT_MF (10h). */ 497 509 kIemNativeLabelType_RaiseXf, /**< Raise (throw) X86_XCPT_XF (13h). */ 498 kIemNativeLabelType_ObsoleteTb, 499 kIemNativeLabelType_NeedCsLimChecking, 500 kIemNativeLabelType_CheckBranchMiss, 510 kIemNativeLabelType_ObsoleteTb, /**< Calls iemNativeHlpObsoleteTb (no inputs). */ 511 kIemNativeLabelType_NeedCsLimChecking, /**< Calls iemNativeHlpNeedCsLimChecking (no inputs). */ 512 kIemNativeLabelType_CheckBranchMiss, /**< Calls iemNativeHlpCheckBranchMiss (no inputs). */ 501 513 kIemNativeLabelType_LastSimple = kIemNativeLabelType_CheckBranchMiss, 502 /* Manually defined labels. */ 514 515 /* Manually defined labels: */ 516 /**< Returns with VINF_SUCCESS, no inputs. */ 517 kIemNativeLabelType_ReturnSuccess, 518 /** Returns with VINF_IEM_REEXEC_FINISH_WITH_FLAGS, no inputs. */ 519 kIemNativeLabelType_ReturnWithFlags, 520 /** Returns with VINF_IEM_REEXEC_BREAK, no inputs. */ 503 521 kIemNativeLabelType_ReturnBreak, 522 /** Returns with VINF_IEM_REEXEC_BREAK_FF, no inputs. */ 504 523 kIemNativeLabelType_ReturnBreakFF, 524 /** The last TB exit label that doesn't have any input registers. */ 525 kIemNativeLabelType_LastTbExitWithoutInputs = kIemNativeLabelType_ReturnBreakFF, 526 527 /** Argument registers 1, 2 & 3 are set up. */ 505 528 kIemNativeLabelType_ReturnBreakViaLookup, 529 /** Argument registers 1, 2 & 3 are set up. */ 506 530 kIemNativeLabelType_ReturnBreakViaLookupWithIrq, 531 /** Argument registers 1 & 2 are set up. */ 507 532 kIemNativeLabelType_ReturnBreakViaLookupWithTlb, 533 /** Argument registers 1 & 2 are set up. */ 508 534 kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq, 509 kIemNativeLabelType_ReturnWithFlags, 535 /** Return register holds the RC and the instruction number is in CL/RCX 536 * on amd64 and the 2rd argument register elsewhere. */ 510 537 kIemNativeLabelType_NonZeroRetOrPassUp, 511 kIemNativeLabelType_ReturnSuccess, /**< Sets eax/w0 to zero and returns. */ 538 512 539 /** The last fixup for branches that can span almost the whole TB length. 513 540 * @note Whether kIemNativeLabelType_Return needs to be one of these is 514 541 * a bit questionable, since nobody jumps to it except other tail code. */ 515 kIemNativeLabelType_LastWholeTbBranch = kIemNativeLabelType_ ReturnSuccess,542 kIemNativeLabelType_LastWholeTbBranch = kIemNativeLabelType_NonZeroRetOrPassUp, 516 543 /** The last fixup for branches that exits the TB. */ 517 kIemNativeLabelType_LastTbExit = kIemNativeLabelType_ReturnSuccess, 544 kIemNativeLabelType_LastTbExit = kIemNativeLabelType_NonZeroRetOrPassUp, 545 /** @} */ 518 546 519 547 /** Loop-jump target. */ … … 538 566 #define IEMNATIVELABELTYPE_IS_EXIT_REASON(a_enmLabel) \ 539 567 ((a_enmLabel) <= kIemNativeLabelType_LastTbExit && (a_enmLabel) > kIemNativeLabelType_Invalid) 568 569 #define IEMNATIVELABELTYPE_IS_EXIT_WITHOUT_INPUTS(a_enmLabel) \ 570 ((a_enmLabel) <= kIemNativeLabelType_LastTbExitWithoutInputs && (a_enmLabel) > kIemNativeLabelType_Invalid) 571 572 /** 573 * Get the mask of input registers for an TB exit label. 574 * This will return zero for any non-exit lable. 575 */ 576 #ifdef RT_ARCH_AMD64 577 # define IEMNATIVELABELTYPE_GET_INPUT_REG_MASK(a_enmLabel) \ 578 ( (a_enmLabel) == kIemNativeLabelType_ReturnBreakViaLookup \ 579 || (a_enmLabel) == kIemNativeLabelType_ReturnBreakViaLookupWithIrq \ 580 ? RT_BIT_32(IEMNATIVE_CALL_ARG1_GREG) | RT_BIT_32(IEMNATIVE_CALL_ARG2_GREG) | RT_BIT_32(IEMNATIVE_CALL_ARG3_GREG) \ 581 : (a_enmLabel) == kIemNativeLabelType_ReturnBreakViaLookupWithTlb \ 582 || (a_enmLabel) == kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq \ 583 ? RT_BIT_32(IEMNATIVE_CALL_ARG1_GREG) | RT_BIT_32(IEMNATIVE_CALL_ARG2_GREG) \ 584 : (a_enmLabel) == kIemNativeLabelType_NonZeroRetOrPassUp \ 585 ? RT_BIT_32(IEMNATIVE_CALL_RET_GREG) | RT_BIT_32(X86_GREG_xCX) /* <-- the difference */ \ 586 : 0) 587 # else 588 # define IEMNATIVELABELTYPE_GET_INPUT_REG_MASK(a_enmLabel) \ 589 ( (a_enmLabel) == kIemNativeLabelType_ReturnBreakViaLookup \ 590 || (a_enmLabel) == kIemNativeLabelType_ReturnBreakViaLookupWithIrq \ 591 ? RT_BIT_32(IEMNATIVE_CALL_ARG1_GREG) | RT_BIT_32(IEMNATIVE_CALL_ARG2_GREG) | RT_BIT_32(IEMNATIVE_CALL_ARG3_GREG) \ 592 : (a_enmLabel) == kIemNativeLabelType_ReturnBreakViaLookupWithTlb \ 593 || (a_enmLabel) == kIemNativeLabelType_ReturnBreakViaLookupWithTlbAndIrq \ 594 ? RT_BIT_32(IEMNATIVE_CALL_ARG1_GREG) | RT_BIT_32(IEMNATIVE_CALL_ARG2_GREG) \ 595 : (a_enmLabel) == kIemNativeLabelType_NonZeroRetOrPassUp \ 596 ? RT_BIT_32(IEMNATIVE_CALL_RET_GREG) | RT_BIT_32(IEMNATIVE_CALL_ARG2_GREG) \ 597 : 0) 598 #endif 540 599 541 600 … … 660 719 #define IEMLIVENESSBIT_IDX_EFL_SF ((unsigned)kIemNativeGstReg_EFlags + 5) 661 720 #define IEMLIVENESSBIT_IDX_EFL_OF ((unsigned)kIemNativeGstReg_EFlags + 6) 721 #define IEMLIVENESSBIT_IDX_EFL_COUNT 7 662 722 663 723 … … 819 879 # define IEMLIVENESS_STATE_ARE_STATUS_EFL_TO_BE_CLOBBERED(a_pCurEntry) \ 820 880 ( (((a_pCurEntry)->Bit0.bm64 | (a_pCurEntry)->Bit1.bm64) & IEMLIVENESSBIT_STATUS_EFL_MASK) == 0 ) 881 882 /*** 883 * Construct a mask of what will be clobbered and never used. 884 * 885 * This is mainly used with IEMLIVENESSBIT_STATUS_EFL_MASK to avoid 886 * unnecessary EFLAGS calculations. 887 * 888 * @param a_pCurEntry The current liveness entry. 889 * @note Used by actual code. 890 */ 891 # define IEMLIVENESS_STATE_GET_WILL_BE_CLOBBERED_SET(a_pCurEntry) \ 892 ( ~((a_pCurEntry)->Bit0.bm64 | (a_pCurEntry)->Bit1.bm64) & IEMLIVENESSBIT_MASK ) 821 893 822 894 /** Construct a mask of the guest registers in the UNUSED and XCPT_OR_CALL … … 864 936 * @note Used by actual code. */ 865 937 # define IEMLIVENESS_STATE_GET_CAN_BE_FREED_SET(a_pCurEntry) \ 866 ( ~(a_pCurEntry)->aBits[IEMLIVENESS_BIT_READ].bm64 \ 867 & ~(a_pCurEntry)->aBits[IEMLIVENESS_BIT_WRITE].bm64 \ 868 & IEMLIVENESSBIT_MASK ) 869 938 ( ~(a_pCurEntry)->aBits[IEMLIVENESS_BIT_READ].bm64 \ 939 & ~(a_pCurEntry)->aBits[IEMLIVENESS_BIT_WRITE].bm64 \ 940 & IEMLIVENESSBIT_MASK ) 941 942 /*** 943 * Construct a mask of what will be clobbered and never used. 944 * 945 * This is mainly used with IEMLIVENESSBIT_STATUS_EFL_MASK to avoid 946 * unnecessary EFLAGS calculations. 947 * 948 * @param a_pCurEntry The current liveness entry. 949 * @note Used by actual code. 950 */ 951 # define IEMLIVENESS_STATE_GET_WILL_BE_CLOBBERED_SET(a_pCurEntry) \ 952 ( (a_pCurEntry)->aBits[IEMLIVENESS_BIT_WRITE].bm64 \ 953 & ~( (a_pCurEntry)->aBits[IEMLIVENESS_BIT_POTENTIAL_CALL].bm64 \ 954 | (a_pCurEntry)->aBits[IEMLIVENESS_BIT_READ].bm64 \ 955 | (a_pCurEntry)->aBits[IEMLIVENESS_BIT_CALL].bm64) ) 956 957 /** 958 * Construct a mask of what (EFLAGS) which can be postponed. 959 * 960 * The postponement is for the avoiding EFLAGS status bits calculations in the 961 * primary code stream whenever possible, and instead only do these in the TLB 962 * load and TB exit code paths which shouldn't be traveled quite as often. 963 * A requirement, though, is that the status bits will be clobbered later in the 964 * TB. 965 * 966 * User need to apply IEMLIVENESSBIT_STATUS_EFL_MASK if appropriate/necessary. 967 * 968 * @param a_pCurEntry The current liveness entry. 969 * @note Used by actual code. 970 */ 971 # define IEMLIVENESS_STATE_GET_CAN_BE_POSTPONED_SET(a_pCurEntry) \ 972 ( (a_pCurEntry)->aBits[IEMLIVENESS_BIT_POTENTIAL_CALL].bm64 \ 973 & (a_pCurEntry)->aBits[IEMLIVENESS_BIT_WRITE].bm64 \ 974 & ~( (a_pCurEntry)->aBits[IEMLIVENESS_BIT_READ].bm64 \ 975 | (a_pCurEntry)->aBits[IEMLIVENESS_BIT_CALL].bm64) ) 870 976 871 977 #endif /* IEMLIVENESS_EXTENDED_LAYOUT */ … … 1039 1145 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 1040 1146 # define IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(a_pReNative, a_fEflNeeded) \ 1041 AssertMsg(!((a_pReNative)-> fPostponingEFlags & (a_fEflNeeded)), \1042 ("%#x & %#x -> %#x\n", (a_pReNative)-> fPostponingEFlags, \1043 a_fEflNeeded, (a_pReNative)-> fPostponingEFlags & (a_fEflNeeded) ))1147 AssertMsg(!((a_pReNative)->PostponedEfl.fEFlags & (a_fEflNeeded)), \ 1148 ("%#x & %#x -> %#x\n", (a_pReNative)->PostponedEfl.fEFlags, \ 1149 a_fEflNeeded, (a_pReNative)->PostponedEfl.fEFlags & (a_fEflNeeded) )) 1044 1150 #else 1045 1151 # define IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(a_pReNative, a_fEflNeeded) ((void)0) … … 1052 1158 #if defined(IEMNATIVE_WITH_EFLAGS_SKIPPING) && defined(IEMNATIVE_WITH_EFLAGS_POSTPONING) 1053 1159 # define IEMNATIVE_ASSERT_EFLAGS_SKIPPING_AND_POSTPONING(a_pReNative, a_fEflNeeded) \ 1054 AssertMsg(!(((a_pReNative)->fSkippingEFlags | (a_pReNative)-> fPostponingEFlags) & (a_fEflNeeded)), \1055 ("(%#x | %#x) & %#x -> %#x\n", (a_pReNative)->fSkippingEFlags, (a_pReNative)-> fPostponingEFlags, \1056 a_fEflNeeded, ((a_pReNative)->fSkippingEFlags | (a_pReNative)-> fPostponingEFlags) & (a_fEflNeeded) ))1160 AssertMsg(!(((a_pReNative)->fSkippingEFlags | (a_pReNative)->PostponedEfl.fEFlags) & (a_fEflNeeded)), \ 1161 ("(%#x | %#x) & %#x -> %#x\n", (a_pReNative)->fSkippingEFlags, (a_pReNative)->PostponedEfl.fEFlags, \ 1162 a_fEflNeeded, ((a_pReNative)->fSkippingEFlags | (a_pReNative)->PostponedEfl.fEFlags) & (a_fEflNeeded) )) 1057 1163 #elif defined(IEMNATIVE_WITH_EFLAGS_SKIPPING) 1058 1164 # define IEMNATIVE_ASSERT_EFLAGS_SKIPPING_AND_POSTPONING(a_pReNative, a_fEflNeeded) \ … … 1077 1183 #else 1078 1184 # define IEMNATIVE_STRICT_EFLAGS_SKIPPING_EMIT_CHECK(a_pReNative, a_off, a_fEflNeeded) do { } while (0) 1185 #endif 1186 1187 1188 /** @def IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS 1189 * Number of extra instructions to allocate for each TB exit to account for 1190 * postponed EFLAGS calculations. 1191 */ 1192 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 1193 # ifdef RT_ARCH_AMD64 1194 # define IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS 32 1195 # elif defined(RT_ARCH_ARM64) || defined(DOXYGEN_RUNNING) 1196 # define IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS 32 1197 # else 1198 # error "port me" 1199 # endif 1200 #else 1201 # define IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS 0 1202 #endif 1203 1204 /** @def IEMNATIVE_CLEAR_POSTPONED_EFLAGS 1205 * Helper macro function for calling iemNativeClearPostponedEFlags() when 1206 * IEMNATIVE_WITH_EFLAGS_POSTPONING is enabled. 1207 */ 1208 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 1209 # define IEMNATIVE_CLEAR_POSTPONED_EFLAGS(a_pReNative, a_fEflClobbered) iemNativeClearPostponedEFlags<a_fEflClobbered>(a_pReNative) 1210 #else 1211 # define IEMNATIVE_CLEAR_POSTPONED_EFLAGS(a_pReNative, a_fEflClobbered) ((void)0) 1079 1212 #endif 1080 1213 … … 1533 1666 1534 1667 1668 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 1669 typedef enum IEMNATIVE_POSTPONED_EFL_OP_T : uint8_t 1670 { 1671 kIemNativePostponedEflOp_Invalid = 0, 1672 /** Logical operation. 1673 * Operands: result register. 1674 * @note This clears OF, CF and (undefined) AF, thus no need for inputs. */ 1675 kIemNativePostponedEflOp_Logical, 1676 kIemNativePostponedEflOp_End 1677 } IEMNATIVE_POSTPONED_EFL_OP_T; 1678 #endif /* IEMNATIVE_WITH_EFLAGS_POSTPONING */ 1679 1535 1680 /** 1536 1681 * Conditional stack entry. … … 1670 1815 #endif 1671 1816 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 1672 uint32_t fPostponingEFlags; 1817 struct 1818 { 1819 /** EFLAGS status bits that we're currently postponing the calculcation of. */ 1820 uint32_t fEFlags; 1821 /** The postponed EFLAGS status bits calculation operation. */ 1822 IEMNATIVE_POSTPONED_EFL_OP_T enmOp; 1823 /** The bit-width of the postponed EFLAGS calculation. */ 1824 uint8_t cOpBits; 1825 /** Host register holding result or first source for the delayed operation, 1826 * UINT8_MAX if not in use. */ 1827 uint8_t idxReg1; 1828 /** Host register holding second source for the delayed operation, 1829 * UINT8_MAX if not in use. */ 1830 uint8_t idxReg2; 1831 } PostponedEfl; 1673 1832 #endif 1674 1833 -
trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h
r106144 r106180 234 234 pCodeBuf[off++] = Armv8A64MkInstrMovZ(iGpr, uImm32 & UINT32_C(0xffff), 0, false /*f64Bit*/); 235 235 pCodeBuf[off++] = Armv8A64MkInstrMovK(iGpr, uImm32 >> 16, 1, false /*f64Bit*/); 236 } 237 238 #else 239 # error "port me" 240 #endif 241 return off; 242 } 243 244 245 /** 246 * Variant of iemNativeEmitLoadGpr32Imm where the caller ensures sufficent 247 * buffer space. 248 * 249 * Max buffer consumption: 250 * - AMD64: 6 instruction bytes. 251 * - ARM64: 2 instruction words (8 bytes). 252 * 253 * @note The top 32 bits will be cleared. 254 */ 255 template<uint32_t const a_uImm32> 256 DECL_FORCE_INLINE(uint32_t) iemNativeEmitLoadGpr32ImmExT(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGpr) 257 { 258 #ifdef RT_ARCH_AMD64 259 if (a_uImm32 == 0) 260 { 261 /* xor gpr, gpr */ 262 if (iGpr >= 8) 263 pCodeBuf[off++] = X86_OP_REX_R | X86_OP_REX_B; 264 pCodeBuf[off++] = 0x33; 265 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGpr & 7, iGpr & 7); 266 } 267 else 268 { 269 /* mov gpr, imm32 */ 270 if (iGpr >= 8) 271 pCodeBuf[off++] = X86_OP_REX_B; 272 pCodeBuf[off++] = 0xb8 + (iGpr & 7); 273 pCodeBuf[off++] = RT_BYTE1(a_uImm32); 274 pCodeBuf[off++] = RT_BYTE2(a_uImm32); 275 pCodeBuf[off++] = RT_BYTE3(a_uImm32); 276 pCodeBuf[off++] = RT_BYTE4(a_uImm32); 277 } 278 279 #elif defined(RT_ARCH_ARM64) 280 if RT_CONSTEXPR((a_uImm32 >> 16) == 0) 281 /* movz gpr, imm16 */ 282 pCodeBuf[off++] = Armv8A64MkInstrMovZ(iGpr, a_uImm32, 0, false /*f64Bit*/); 283 else if RT_CONSTEXPR((a_uImm32 & UINT32_C(0xffff)) == 0) 284 /* movz gpr, imm16, lsl #16 */ 285 pCodeBuf[off++] = Armv8A64MkInstrMovZ(iGpr, a_uImm32 >> 16, 1, false /*f64Bit*/); 286 else if RT_CONSTEXPR((a_uImm32 & UINT32_C(0xffff)) == UINT32_C(0xffff)) 287 /* movn gpr, imm16, lsl #16 */ 288 pCodeBuf[off++] = Armv8A64MkInstrMovN(iGpr, ~a_uImm32 >> 16, 1, false /*f64Bit*/); 289 else if RT_CONSTEXPR((a_uImm32 >> 16) == UINT32_C(0xffff)) 290 /* movn gpr, imm16 */ 291 pCodeBuf[off++] = Armv8A64MkInstrMovN(iGpr, ~a_uImm32, 0, false /*f64Bit*/); 292 else 293 { 294 pCodeBuf[off++] = Armv8A64MkInstrMovZ(iGpr, a_uImm32 & UINT32_C(0xffff), 0, false /*f64Bit*/); 295 pCodeBuf[off++] = Armv8A64MkInstrMovK(iGpr, a_uImm32 >> 16, 1, false /*f64Bit*/); 236 296 } 237 297 … … 8156 8216 * Emits a call to a 64-bit address. 8157 8217 */ 8218 template<bool const a_fSkipEflChecks = false> 8158 8219 DECL_INLINE_THROW(uint32_t) iemNativeEmitCallImm(PIEMRECOMPILERSTATE pReNative, uint32_t off, uintptr_t uPfn) 8159 8220 { 8221 if RT_CONSTEXPR(!a_fSkipEflChecks) 8222 { 8223 IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8224 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY( pReNative, X86_EFL_STATUS_BITS); 8225 } 8226 8160 8227 #ifdef RT_ARCH_AMD64 8161 8228 off = iemNativeEmitLoadGprImm64(pReNative, off, X86_GREG_xAX, uPfn); … … 8281 8348 *********************************************************************************************************************************/ 8282 8349 8350 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 8351 /* IEMAllN8veEmit-x86.h: */ 8352 template<uint32_t const a_bmInputRegs> 8353 DECL_FORCE_INLINE_THROW(uint32_t) 8354 iemNativeDoPostponedEFlagsAtTbExitEx(PIEMRECOMPILERSTATE pReNative, uint32_t off, PIEMNATIVEINSTR pCodeBuf); 8355 8356 template<uint32_t const a_bmInputRegs> 8357 DECL_FORCE_INLINE_THROW(uint32_t) 8358 iemNativeDoPostponedEFlagsAtTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off); 8359 #endif 8360 8361 8283 8362 /** 8284 8363 * Helper for marking the current conditional branch as exiting the TB. … … 8298 8377 8299 8378 /** 8379 * Unconditionally exits the translation block via a branch instructions. 8380 * 8381 * @note In case a delayed EFLAGS calculation is pending, this may emit an 8382 * additional IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS instructions. 8383 */ 8384 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fActuallyExitingTb = true, bool const a_fPostponedEfl = true> 8385 DECL_INLINE_THROW(uint32_t) iemNativeEmitTbExitEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off) 8386 { 8387 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8388 AssertCompile(IEMNATIVELABELTYPE_IS_EXIT_REASON(a_enmExitReason)); 8389 8390 if RT_CONSTEXPR(a_fActuallyExitingTb) 8391 iemNativeMarkCurCondBranchAsExiting(pReNative); 8392 8393 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 8394 if RT_CONSTEXPR(a_fPostponedEfl) 8395 off = iemNativeDoPostponedEFlagsAtTbExitEx<IEMNATIVELABELTYPE_GET_INPUT_REG_MASK(a_enmExitReason)>(pReNative, off, 8396 pCodeBuf); 8397 #endif 8398 8399 #ifdef RT_ARCH_AMD64 8400 /* jmp rel32 */ 8401 pCodeBuf[off++] = 0xe9; 8402 iemNativeAddTbExitFixup(pReNative, off, a_enmExitReason); 8403 pCodeBuf[off++] = 0xfe; 8404 pCodeBuf[off++] = 0xff; 8405 pCodeBuf[off++] = 0xff; 8406 pCodeBuf[off++] = 0xff; 8407 8408 #elif defined(RT_ARCH_ARM64) 8409 iemNativeAddTbExitFixup(pReNative, off, a_enmExitReason); 8410 pCodeBuf[off++] = Armv8A64MkInstrB(-1); 8411 8412 #else 8413 # error "Port me!" 8414 #endif 8415 return off; 8416 } 8417 8418 8419 /** 8420 * Unconditionally exits the translation block via a branch instructions. 8421 * 8422 * @note In case a delayed EFLAGS calculation is pending, this may emit an 8423 * additional IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS instructions. 8424 */ 8425 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fActuallyExitingTb = true, bool const a_fPostponedEfl = true> 8426 DECL_INLINE_THROW(uint32_t) iemNativeEmitTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off) 8427 { 8428 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8429 AssertCompile(IEMNATIVELABELTYPE_IS_EXIT_REASON(a_enmExitReason)); 8430 8431 if RT_CONSTEXPR(a_fActuallyExitingTb) 8432 iemNativeMarkCurCondBranchAsExiting(pReNative); 8433 8434 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 8435 if RT_CONSTEXPR(a_fPostponedEfl) 8436 off = iemNativeDoPostponedEFlagsAtTbExit<IEMNATIVELABELTYPE_GET_INPUT_REG_MASK(a_enmExitReason)>(pReNative, off); 8437 #endif 8438 8439 #ifdef RT_ARCH_AMD64 8440 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 6); 8441 8442 /* jmp rel32 */ 8443 pCodeBuf[off++] = 0xe9; 8444 iemNativeAddTbExitFixup(pReNative, off, a_enmExitReason); 8445 pCodeBuf[off++] = 0xfe; 8446 pCodeBuf[off++] = 0xff; 8447 pCodeBuf[off++] = 0xff; 8448 pCodeBuf[off++] = 0xff; 8449 8450 #elif defined(RT_ARCH_ARM64) 8451 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1); 8452 iemNativeAddTbExitFixup(pReNative, off, a_enmExitReason); 8453 pCodeBuf[off++] = Armv8A64MkInstrB(-1); 8454 8455 #else 8456 # error "Port me!" 8457 #endif 8458 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8459 return off; 8460 } 8461 8462 8463 /** 8300 8464 * Emits a Jcc rel32 / B.cc imm19 to the given label (ASSUMED requiring fixup). 8301 */ 8465 * 8466 * @note In case a delayed EFLAGS calculation is pending, this may emit an 8467 * additional IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS instructions. 8468 */ 8469 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8302 8470 DECL_FORCE_INLINE_THROW(uint32_t) 8303 iemNativeEmitJccTbExitEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off, 8304 IEMNATIVELABELTYPE enmExitReason, IEMNATIVEINSTRCOND enmCond) 8471 iemNativeEmitTbExitJccEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off, IEMNATIVEINSTRCOND enmCond) 8305 8472 { 8306 8473 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8307 IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(pReNative, X86_EFL_STATUS_BITS); /** @todo emit postponed stuff here and invert the condition. */ 8308 Assert(IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason)); 8474 AssertCompile(IEMNATIVELABELTYPE_IS_EXIT_REASON(a_enmExitReason)); 8475 8476 #ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 8477 if RT_CONSTEXPR(a_fPostponedEfl) 8478 if (pReNative->PostponedEfl.fEFlags) 8479 { 8480 /* Jcc l_NonPrimaryCodeStreamTarget */ 8481 uint32_t const offFixup1 = off; 8482 off = iemNativeEmitJccToFixedEx(pCodeBuf, off, off + 1, enmCond); 8483 8484 /* JMP l_PrimaryCodeStreamResume */ 8485 uint32_t const offFixup2 = off; 8486 off = iemNativeEmitJmpToFixedEx(pCodeBuf, off, off + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 8487 8488 /* l_NonPrimaryCodeStreamTarget: */ 8489 iemNativeFixupFixedJump(pReNative, offFixup1, off); 8490 off = iemNativeEmitTbExitEx<a_enmExitReason, false /*a_fActuallyExitingTb*/, true>(pReNative, pCodeBuf, off); 8491 8492 /* l_PrimaryCodeStreamResume: */ 8493 iemNativeFixupFixedJump(pReNative, offFixup2, off); 8494 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8495 return off; 8496 } 8497 #endif 8309 8498 8310 8499 #if defined(RT_ARCH_AMD64) … … 8312 8501 pCodeBuf[off++] = 0x0f; 8313 8502 pCodeBuf[off++] = (uint8_t)enmCond | 0x80; 8314 iemNativeAddTbExitFixup(pReNative, off, enmExitReason);8503 iemNativeAddTbExitFixup(pReNative, off, a_enmExitReason); 8315 8504 pCodeBuf[off++] = 0x00; 8316 8505 pCodeBuf[off++] = 0x00; … … 8321 8510 /* ARM64 doesn't have the necessary jump range, so we jump via local label 8322 8511 just like when we keep everything local. */ 8323 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/);8512 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, a_enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8324 8513 off = iemNativeEmitJccToLabelEx(pReNative, pCodeBuf, off, idxLabel, enmCond); 8325 8514 #endif … … 8331 8520 * Emits a Jcc rel32 / B.cc imm19 to the epilog. 8332 8521 */ 8333 DECL_INLINE_THROW(uint32_t) 8334 iemNativeEmitJccTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVELABELTYPE enmExitReason, IEMNATIVEINSTRCOND enmCond)8522 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8523 DECL_INLINE_THROW(uint32_t) iemNativeEmitTbExitJcc(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVEINSTRCOND enmCond) 8335 8524 { 8336 8525 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8337 IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(pReNative, X86_EFL_STATUS_BITS); /** @todo emit postponed stuff here and invert the condition. */ 8338 Assert(IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason)); 8339 8340 #ifdef RT_ARCH_AMD64 8341 off = iemNativeEmitJccTbExitEx(pReNative, iemNativeInstrBufEnsure(pReNative, off, 6), off, enmExitReason, enmCond); 8342 #elif defined(RT_ARCH_ARM64) 8343 off = iemNativeEmitJccTbExitEx(pReNative, iemNativeInstrBufEnsure(pReNative, off, 2), off, enmExitReason, enmCond); 8526 AssertCompile(IEMNATIVELABELTYPE_IS_EXIT_REASON(a_enmExitReason)); 8527 8528 #ifdef RT_ARCH_AMD64 8529 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 6 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS + 5); 8530 #elif defined(RT_ARCH_ARM64) 8531 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS + 1); 8344 8532 #else 8345 8533 # error "Port me!" 8346 8534 #endif 8535 off = iemNativeEmitTbExitJccEx<a_enmExitReason, a_fPostponedEfl>(pReNative, pCodeBuf, off, enmCond); 8347 8536 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8348 8537 return off; … … 8353 8542 * Emits a JNZ/JNE rel32 / B.NE imm19 to the TB exit routine with the given reason. 8354 8543 */ 8355 DECL_INLINE_THROW(uint32_t) iemNativeEmitJnzTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVELABELTYPE enmExitReason) 8356 { 8357 #ifdef RT_ARCH_AMD64 8358 return iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kIemNativeInstrCond_ne); 8359 #elif defined(RT_ARCH_ARM64) 8360 return iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kArmv8InstrCond_Ne); 8544 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8545 DECL_INLINE_THROW(uint32_t) iemNativeEmitTbExitJnz(PIEMRECOMPILERSTATE pReNative, uint32_t off) 8546 { 8547 #ifdef RT_ARCH_AMD64 8548 return iemNativeEmitTbExitJcc<a_enmExitReason, a_fPostponedEfl>(pReNative, off, kIemNativeInstrCond_ne); 8549 #elif defined(RT_ARCH_ARM64) 8550 return iemNativeEmitTbExitJcc<a_enmExitReason, a_fPostponedEfl>(pReNative, off, kArmv8InstrCond_Ne); 8361 8551 #else 8362 8552 # error "Port me!" … … 8368 8558 * Emits a JZ/JE rel32 / B.EQ imm19 to the TB exit routine with the given reason. 8369 8559 */ 8370 DECL_INLINE_THROW(uint32_t) iemNativeEmitJzTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVELABELTYPE enmExitReason) 8371 { 8372 #ifdef RT_ARCH_AMD64 8373 return iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kIemNativeInstrCond_e); 8374 #elif defined(RT_ARCH_ARM64) 8375 return iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kArmv8InstrCond_Eq); 8560 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8561 DECL_INLINE_THROW(uint32_t) iemNativeEmitTbExitJz(PIEMRECOMPILERSTATE pReNative, uint32_t off) 8562 { 8563 #ifdef RT_ARCH_AMD64 8564 return iemNativeEmitTbExitJcc<a_enmExitReason, a_fPostponedEfl>(pReNative, off, kIemNativeInstrCond_e); 8565 #elif defined(RT_ARCH_ARM64) 8566 return iemNativeEmitTbExitJcc<a_enmExitReason, a_fPostponedEfl>(pReNative, off, kArmv8InstrCond_Eq); 8376 8567 #else 8377 8568 # error "Port me!" … … 8383 8574 * Emits a JA/JNBE rel32 / B.HI imm19 to the TB exit. 8384 8575 */ 8385 DECL_INLINE_THROW(uint32_t) iemNativeEmitJaTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVELABELTYPE enmExitReason) 8386 { 8387 #ifdef RT_ARCH_AMD64 8388 return iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kIemNativeInstrCond_nbe); 8389 #elif defined(RT_ARCH_ARM64) 8390 return iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kArmv8InstrCond_Hi); 8576 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8577 DECL_INLINE_THROW(uint32_t) iemNativeEmitTbExitJa(PIEMRECOMPILERSTATE pReNative, uint32_t off) 8578 { 8579 #ifdef RT_ARCH_AMD64 8580 return iemNativeEmitTbExitJcc<a_enmExitReason, a_fPostponedEfl>(pReNative, off, kIemNativeInstrCond_nbe); 8581 #elif defined(RT_ARCH_ARM64) 8582 return iemNativeEmitTbExitJcc<a_enmExitReason, a_fPostponedEfl>(pReNative, off, kArmv8InstrCond_Hi); 8391 8583 #else 8392 8584 # error "Port me!" … … 8398 8590 * Emits a JL/JNGE rel32 / B.LT imm19 to the TB exit with the given reason. 8399 8591 */ 8400 DECL_INLINE_THROW(uint32_t) iemNativeEmitJlTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVELABELTYPE enmExitReason) 8401 { 8402 #ifdef RT_ARCH_AMD64 8403 return iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kIemNativeInstrCond_l); 8404 #elif defined(RT_ARCH_ARM64) 8405 return iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kArmv8InstrCond_Lt); 8592 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8593 DECL_INLINE_THROW(uint32_t) iemNativeEmitTbExitJl(PIEMRECOMPILERSTATE pReNative, uint32_t off) 8594 { 8595 #ifdef RT_ARCH_AMD64 8596 return iemNativeEmitTbExitJcc<a_enmExitReason, a_fPostponedEfl>(pReNative, off, kIemNativeInstrCond_l); 8597 #elif defined(RT_ARCH_ARM64) 8598 return iemNativeEmitTbExitJcc<a_enmExitReason, a_fPostponedEfl>(pReNative, off, kArmv8InstrCond_Lt); 8406 8599 #else 8407 8600 # error "Port me!" … … 8410 8603 8411 8604 8412 DECL_INLINE_THROW(uint32_t) 8413 iemNativeEmitTbExitEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off, IEMNATIVELABELTYPE enmExitReason) 8414 { 8415 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8416 IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(pReNative, X86_EFL_STATUS_BITS); /** @todo emit postponed stuff here. */ 8417 Assert(IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason)); 8418 8419 iemNativeMarkCurCondBranchAsExiting(pReNative); 8420 8421 #ifdef RT_ARCH_AMD64 8422 /* jmp rel32 */ 8423 pCodeBuf[off++] = 0xe9; 8424 iemNativeAddTbExitFixup(pReNative, off, enmExitReason); 8425 pCodeBuf[off++] = 0xfe; 8426 pCodeBuf[off++] = 0xff; 8427 pCodeBuf[off++] = 0xff; 8428 pCodeBuf[off++] = 0xff; 8429 8430 #elif defined(RT_ARCH_ARM64) 8431 iemNativeAddTbExitFixup(pReNative, off, enmExitReason); 8432 pCodeBuf[off++] = Armv8A64MkInstrB(-1); 8433 8434 #else 8435 # error "Port me!" 8436 #endif 8437 return off; 8438 } 8439 8440 8441 DECL_INLINE_THROW(uint32_t) 8442 iemNativeEmitTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVELABELTYPE enmExitReason, 8443 bool fActuallyExitingTb = true) 8444 { 8445 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8446 IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(pReNative, X86_EFL_STATUS_BITS); /** @todo emit postponed stuff here. */ 8447 Assert(IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason)); 8448 8449 if (fActuallyExitingTb) 8450 iemNativeMarkCurCondBranchAsExiting(pReNative); 8451 8452 #ifdef RT_ARCH_AMD64 8453 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 6); 8454 8455 /* jmp rel32 */ 8456 pCodeBuf[off++] = 0xe9; 8457 iemNativeAddTbExitFixup(pReNative, off, enmExitReason); 8458 pCodeBuf[off++] = 0xfe; 8459 pCodeBuf[off++] = 0xff; 8460 pCodeBuf[off++] = 0xff; 8461 pCodeBuf[off++] = 0xff; 8462 8463 #elif defined(RT_ARCH_ARM64) 8464 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1); 8465 iemNativeAddTbExitFixup(pReNative, off, enmExitReason); 8466 pCodeBuf[off++] = Armv8A64MkInstrB(-1); 8467 8468 #else 8469 # error "Port me!" 8470 #endif 8471 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8472 return off; 8473 } 8474 8475 8476 /** 8477 * Emits a jump to the TB exit with @a enmExitReason on the condition _any_ of the bits in @a fBits 8478 * are set in @a iGprSrc. 8479 */ 8480 DECL_INLINE_THROW(uint32_t) 8481 iemNativeEmitTestAnyBitsInGprAndTbExitIfAnySet(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8482 uint8_t iGprSrc, uint64_t fBits, IEMNATIVELABELTYPE enmExitReason) 8605 /** 8606 * Emits a jump to the TB exit with @a a_enmExitReason on the condition _any_ of 8607 * the bits in @a fBits are set in @a iGprSrc. 8608 */ 8609 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8610 DECL_INLINE_THROW(uint32_t) 8611 iemNativeEmitTbExitIfAnyBitsSetInGpr(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc, uint64_t fBits) 8483 8612 { 8484 8613 Assert(fBits); Assert(!RT_IS_POWER_OF_TWO(fBits)); 8485 8614 8486 8615 off = iemNativeEmitTestAnyBitsInGpr(pReNative, off, iGprSrc, fBits); 8487 return iemNativeEmitJnzTbExit(pReNative, off, enmExitReason); 8488 } 8489 8490 8616 return iemNativeEmitTbExitJnz<a_enmExitReason, a_fPostponedEfl>(pReNative, off); 8617 } 8618 8619 8620 #if 0 /* unused */ 8491 8621 /** 8492 8622 * Emits a jump to @a idxLabel on the condition _none_ of the bits in @a fBits 8493 8623 * are set in @a iGprSrc. 8494 8624 */ 8495 DECL_INLINE_THROW(uint32_t) 8496 iemNativeEmitTestAnyBitsInGprAndTbExitIfNoneSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8497 uint8_t iGprSrc, uint64_t fBits, IEMNATIVELABELTYPE enmExitReason)8625 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8626 DECL_INLINE_THROW(uint32_t) 8627 iemNativeEmitTbExitIfNoBitsSetInGpr(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc, uint64_t fBits) 8498 8628 { 8499 8629 Assert(fBits); Assert(!RT_IS_POWER_OF_TWO(fBits)); 8500 8630 8501 8631 off = iemNativeEmitTestAnyBitsInGpr(pReNative, off, iGprSrc, fBits); 8502 return iemNativeEmitJzTbExit(pReNative, off, enmExitReason); 8503 } 8504 8505 8632 return iemNativeEmitJzTbExit<a_enmExitReason, a_fPostponedEfl>(pReNative, off); 8633 } 8634 #endif 8635 8636 8637 #if 0 /* unused */ 8506 8638 /** 8507 8639 * Emits code that exits the TB with the given reason if @a iGprLeft and @a iGprRight 8508 8640 * differs. 8509 8641 */ 8510 DECL_INLINE_THROW(uint32_t) 8511 iemNativeEmitTestIfGprNotEqualGprAndTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8512 uint8_t iGprLeft, uint8_t iGprRight, IEMNATIVELABELTYPE enmExitReason)8642 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8643 DECL_INLINE_THROW(uint32_t) 8644 iemNativeEmitTbExitIfGprNotEqualGpr(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprLeft, uint8_t iGprRight) 8513 8645 { 8514 8646 off = iemNativeEmitCmpGprWithGpr(pReNative, off, iGprLeft, iGprRight); 8515 off = iemNativeEmitJnzTbExit(pReNative, off, enmExitReason); 8516 return off; 8517 } 8647 off = iemNativeEmitJnzTbExit<a_enmExitReason, a_fPostponedEfl>(pReNative, off); 8648 return off; 8649 } 8650 #endif 8518 8651 8519 8652 … … 8522 8655 * @a uImm. 8523 8656 */ 8524 DECL_INLINE_THROW(uint32_t) 8525 iemNativeEmitTestIfGpr32NotEqualImmAndTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8526 uint8_t iGprSrc, uint32_t uImm, IEMNATIVELABELTYPE enmExitReason)8657 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8658 DECL_INLINE_THROW(uint32_t) 8659 iemNativeEmitTbExitIfGpr32NotEqualImm(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc, uint32_t uImm) 8527 8660 { 8528 8661 off = iemNativeEmitCmpGpr32WithImm(pReNative, off, iGprSrc, uImm); 8529 off = iemNativeEmit JnzTbExit(pReNative, off, enmExitReason);8662 off = iemNativeEmitTbExitJnz<a_enmExitReason, a_fPostponedEfl>(pReNative, off); 8530 8663 return off; 8531 8664 } … … 8535 8668 * Emits code that exits the current TB if @a iGprSrc differs from @a uImm. 8536 8669 */ 8537 DECL_INLINE_THROW(uint32_t) 8538 iemNativeEmitTestIfGprNotEqualImmAndTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8539 uint8_t iGprSrc, uint64_t uImm, IEMNATIVELABELTYPE enmExitReason)8670 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8671 DECL_INLINE_THROW(uint32_t) 8672 iemNativeEmitTbExitIfGprNotEqualImm(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc, uint64_t uImm) 8540 8673 { 8541 8674 off = iemNativeEmitCmpGprWithImm(pReNative, off, iGprSrc, uImm); 8542 off = iemNativeEmit JnzTbExit(pReNative, off, enmExitReason);8675 off = iemNativeEmitTbExitJnz<a_enmExitReason, a_fPostponedEfl>(pReNative, off); 8543 8676 return off; 8544 8677 } … … 8548 8681 * Emits code that exits the current TB with the given reason if 32-bit @a iGprSrc equals @a uImm. 8549 8682 */ 8550 DECL_INLINE_THROW(uint32_t) 8551 iemNativeEmitTestIfGpr32EqualsImmAndTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8552 uint8_t iGprSrc, uint32_t uImm, IEMNATIVELABELTYPE enmExitReason)8683 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8684 DECL_INLINE_THROW(uint32_t) 8685 iemNativeEmitTbExitIfGpr32EqualsImm(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc, uint32_t uImm) 8553 8686 { 8554 8687 off = iemNativeEmitCmpGpr32WithImm(pReNative, off, iGprSrc, uImm); 8555 off = iemNativeEmit JzTbExit(pReNative, off, enmExitReason);8556 return off; 8557 } 8558 8559 8560 /** 8561 * Emits code to exit the current TB with the reason @a enmExitReason on the condition that bit @a iBitNo _is_ _set_ in8562 * @a iGprSrc.8688 off = iemNativeEmitTbExitJz<a_enmExitReason, a_fPostponedEfl>(pReNative, off); 8689 return off; 8690 } 8691 8692 8693 /** 8694 * Emits code to exit the current TB with the reason @a a_enmExitReason on the 8695 * condition that bit @a iBitNo _is_ _set_ in @a iGprSrc. 8563 8696 * 8564 8697 * @note On ARM64 the range is only +/-8191 instructions. 8565 8698 */ 8566 DECL_INLINE_THROW(uint32_t) 8567 iemNativeEmitTestBitInGprAndTbExitIfSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8568 uint8_t iGprSrc, uint8_t iBitNo, IEMNATIVELABELTYPE enmExitReason)8569 { 8570 Assert (IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason));8699 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8700 DECL_INLINE_THROW(uint32_t) 8701 iemNativeEmitTbExitIfBitSetInGpr(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc, uint8_t iBitNo) 8702 { 8703 AssertCompile(IEMNATIVELABELTYPE_IS_EXIT_REASON(a_enmExitReason)); 8571 8704 8572 8705 #if defined(RT_ARCH_AMD64) … … 8581 8714 pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 0, iGprSrc & 7); 8582 8715 pbCodeBuf[off++] = (uint8_t)1 << iBitNo; 8583 off = iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kIemNativeInstrCond_ne); 8716 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8717 off = iemNativeEmitTbExitJcc<a_enmExitReason, a_fPostponedEfl>(pReNative, off, kIemNativeInstrCond_ne); 8584 8718 } 8585 8719 else … … 8594 8728 pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4, iGprSrc & 7); 8595 8729 pbCodeBuf[off++] = iBitNo; 8596 off = iemNativeEmitJccTbExit(pReNative, off, enmExitReason, kIemNativeInstrCond_c); 8597 } 8598 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8599 return off; 8600 8601 #else 8602 /* ARM64 doesn't have the necessary jump range, so we jump via local label 8603 just like when we keep everything local. */ 8730 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8731 off = iemNativeEmitTbExitJcc<a_enmExitReason, a_fPostponedEfl>(pReNative, off, kIemNativeInstrCond_c); 8732 } 8733 return off; 8734 8735 #elif defined(RT_ARCH_ARM64) 8604 8736 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8605 IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(pReNative, X86_EFL_STATUS_BITS); /** @todo emit postponed stuff here and invert the condition. */ 8606 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8737 /** @todo Perhaps we should always apply the PostponedEfl code pattern here, 8738 * it's the same number of instructions as the TST + B.CC stuff? */ 8739 # ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 8740 if RT_CONSTEXPR(a_fPostponedEfl) 8741 if (pReNative->PostponedEfl.fEFlags) 8742 { 8743 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 8744 3 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 8745 pCodeBuf[off++] = Armv8A64MkInstrTbnz(1 /*l_NonPrimaryCodeStreamTarget*/, iGprSrc, iBitNo); 8746 uint32_t const offFixup = off; 8747 pCodeBuf[off++] = Armv8A64MkInstrB(0 /*l_PrimaryCodeStreamResume*/); 8748 /* l_NonPrimaryCodeStreamTarget: */ 8749 off = iemNativeEmitTbExitEx<a_enmExitReason, false /*a_fActuallyExitingTb*/, true>(pReNative, pCodeBuf, off); 8750 /* l_PrimaryCodeStreamResume: */ 8751 iemNativeFixupFixedJump(pReNative, offFixup, off); 8752 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8753 return off; 8754 } 8755 # endif 8756 /* ARM64 doesn't have the necessary range to reach the per-chunk code, so 8757 we go via a local trampoline. */ 8758 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, a_enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8607 8759 return iemNativeEmitTestBitInGprAndJmpToLabelIfCc(pReNative, off, iGprSrc, iBitNo, idxLabel, true /*fJmpIfSet*/); 8608 #endif 8609 } 8610 8611 8612 /** 8613 * Emits code that exits the current TB with @a enmExitReason if @a iGprSrc is not zero. 8760 #else 8761 # error "port me" 8762 #endif 8763 } 8764 8765 8766 /** 8767 * Emits code that exits the current TB with @a a_enmExitReason if @a iGprSrc is 8768 * not zero. 8614 8769 * 8615 8770 * The operand size is given by @a f64Bit. 8616 8771 */ 8772 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8617 8773 DECL_FORCE_INLINE_THROW(uint32_t) 8618 iemNativeEmitT estIfGprIsNotZeroAndTbExitEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off,8619 uint8_t iGprSrc, bool f64Bit, IEMNATIVELABELTYPE enmExitReason)8620 { 8621 Assert (IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason));8774 iemNativeEmitTbExitIfGprIsNotZeroEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off, 8775 uint8_t iGprSrc, bool f64Bit) 8776 { 8777 AssertCompile(IEMNATIVELABELTYPE_IS_EXIT_REASON(a_enmExitReason)); 8622 8778 8623 8779 #if defined(RT_ARCH_AMD64) … … 8631 8787 8632 8788 /* jnz idxLabel */ 8633 return iemNativeEmitJccTbExitEx(pReNative, pCodeBuf, off, enmExitReason, kIemNativeInstrCond_ne); 8634 8635 #else 8636 /* ARM64 doesn't have the necessary jump range, so we jump via local label 8637 just like when we keep everything local. */ 8789 return iemNativeEmitTbExitJccEx<a_enmExitReason, a_fPostponedEfl>(pReNative, pCodeBuf, off, kIemNativeInstrCond_ne); 8790 8791 #elif defined(RT_ARCH_ARM64) 8638 8792 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8639 IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(pReNative, X86_EFL_STATUS_BITS); /** @todo emit postponed stuff here and invert the condition. */ 8640 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8793 # ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 8794 if RT_CONSTEXPR(a_fPostponedEfl) 8795 if (pReNative->PostponedEfl.fEFlags) 8796 { 8797 pCodeBuf[off++] = Armv8A64MkInstrCbnz(1 /*l_NonPrimaryCodeStreamTarget*/, iGprSrc, f64Bit); 8798 uint32_t const offFixup = off; 8799 pCodeBuf[off++] = Armv8A64MkInstrB(0 /*l_PrimaryCodeStreamResume*/); 8800 /* l_NonPrimaryCodeStreamTarget: */ 8801 off = iemNativeEmitTbExitEx<a_enmExitReason, false /*a_fActuallyExitingTb*/, true>(pReNative, pCodeBuf, off); 8802 /* l_PrimaryCodeStreamResume: */ 8803 iemNativeFixupFixedJump(pReNative, offFixup, off); 8804 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8805 return off; 8806 } 8807 # endif 8808 /* ARM64 doesn't have the necessary range to reach the per-chunk code, so 8809 we go via a local trampoline. */ 8810 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, a_enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8641 8811 return iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToLabelEx(pReNative, pCodeBuf, off, iGprSrc, 8642 8812 f64Bit, true /*fJmpIfNotZero*/, idxLabel); 8643 #endif 8644 } 8645 8646 8647 /** 8648 * Emits code to exit the current TB with the given reason @a enmExitReason if @a iGprSrc is not zero. 8813 #else 8814 # error "port me" 8815 #endif 8816 } 8817 8818 8819 /** 8820 * Emits code to exit the current TB with the given reason @a a_enmExitReason if 8821 * @a iGprSrc is not zero. 8649 8822 * 8650 8823 * The operand size is given by @a f64Bit. 8651 8824 */ 8652 DECL_INLINE_THROW(uint32_t) 8653 iemNativeEmitTestIfGprIsNotZeroAndTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8654 uint8_t iGprSrc, bool f64Bit, IEMNATIVELABELTYPE enmExitReason)8825 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8826 DECL_INLINE_THROW(uint32_t) 8827 iemNativeEmitTbExitIfGprIsNotZero(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc, bool f64Bit) 8655 8828 { 8656 8829 #if defined(RT_ARCH_AMD64) 8657 off = iemNativeEmitTestIfGprIsNotZeroAndTbExitEx(pReNative, iemNativeInstrBufEnsure(pReNative, off, 3 + 6), 8658 off, iGprSrc, f64Bit, enmExitReason); 8659 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8660 return off; 8661 #else 8662 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8663 IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(pReNative, X86_EFL_STATUS_BITS); /** @todo emit postponed stuff here and invert the condition. */ 8664 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8665 return iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToLabel(pReNative, off, iGprSrc, f64Bit, true /*fJmpIfNotZero*/, idxLabel); 8666 #endif 8667 } 8668 8669 8670 /** 8671 * Emits code that exits the current TB with @a enmExitReason if @a iGprSrc is zero. 8830 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3 + 6 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 8831 8832 #else 8833 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 8834 #endif 8835 off = iemNativeEmitTbExitIfGprIsNotZeroEx<a_enmExitReason, a_fPostponedEfl>(pReNative, pCodeBuf, off, iGprSrc, f64Bit); 8836 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8837 return off; 8838 } 8839 8840 8841 /** 8842 * Emits code that exits the current TB with @a a_enmExitReason if @a iGprSrc is 8843 * zero. 8672 8844 * 8673 8845 * The operand size is given by @a f64Bit. 8674 8846 */ 8847 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8675 8848 DECL_FORCE_INLINE_THROW(uint32_t) 8676 iemNativeEmitTestIfGprIsZeroAndTbExitEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off, 8677 uint8_t iGprSrc, bool f64Bit, IEMNATIVELABELTYPE enmExitReason) 8678 { 8679 Assert(IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason)); 8849 iemNativeEmitTbExitIfGprIsZeroEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off, 8850 uint8_t iGprSrc, bool f64Bit) 8851 { 8852 AssertCompile(IEMNATIVELABELTYPE_IS_EXIT_REASON(a_enmExitReason)); 8853 8680 8854 #if defined(RT_ARCH_AMD64) 8681 8855 /* test reg32,reg32 / test reg64,reg64 */ … … 8688 8862 8689 8863 /* jnz idxLabel */ 8690 return iemNativeEmitJccTbExitEx(pReNative, pCodeBuf, off, enmExitReason, kIemNativeInstrCond_e); 8691 8692 #else 8693 /* ARM64 doesn't have the necessary jump range, so we jump via local label 8694 just like when we keep everything local. */ 8864 return iemNativeEmitTbExitJccEx<a_enmExitReason, a_fPostponedEfl>(pReNative, pCodeBuf, off, kIemNativeInstrCond_e); 8865 8866 #elif defined(RT_ARCH_ARM64) 8695 8867 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8696 IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(pReNative, X86_EFL_STATUS_BITS); /** @todo emit postponed stuff here and invert the condition. */ 8697 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8868 # ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING 8869 if RT_CONSTEXPR(a_fPostponedEfl) 8870 if (pReNative->PostponedEfl.fEFlags) 8871 { 8872 pCodeBuf[off++] = Armv8A64MkInstrCbz(1 /*l_NonPrimaryCodeStreamTarget*/, iGprSrc, f64Bit); 8873 uint32_t const offFixup = off; 8874 pCodeBuf[off++] = Armv8A64MkInstrB(0 /*l_PrimaryCodeStreamResume*/); 8875 /* l_NonPrimaryCodeStreamTarget: */ 8876 off = iemNativeEmitTbExitEx<a_enmExitReason, false /*a_fActuallyExitingTb*/, true>(pReNative, pCodeBuf, off); 8877 /* l_PrimaryCodeStreamResume: */ 8878 iemNativeFixupFixedJump(pReNative, offFixup, off); 8879 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8880 return off; 8881 } 8882 # endif 8883 /* ARM64 doesn't have the necessary range to reach the per-chunk code, so 8884 we go via a local trampoline. */ 8885 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, a_enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8698 8886 return iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToLabelEx(pReNative, pCodeBuf, off, iGprSrc, 8699 8887 f64Bit, false /*fJmpIfNotZero*/, idxLabel); 8700 #endif 8701 } 8702 8703 8704 /** 8705 * Emits code to exit the current TB with the given reason @a enmExitReason if @a iGprSrc is zero. 8888 #else 8889 # error "port me" 8890 #endif 8891 } 8892 8893 8894 /** 8895 * Emits code to exit the current TB with the given reason @a a_enmExitReason if @a iGprSrc is zero. 8706 8896 * 8707 8897 * The operand size is given by @a f64Bit. 8708 8898 */ 8709 DECL_INLINE_THROW(uint32_t) 8710 iemNativeEmitTestIfGprIsZeroAndTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off, 8711 uint8_t iGprSrc, bool f64Bit, IEMNATIVELABELTYPE enmExitReason)8899 template<IEMNATIVELABELTYPE const a_enmExitReason, bool const a_fPostponedEfl = true> 8900 DECL_INLINE_THROW(uint32_t) 8901 iemNativeEmitTbExitIfGprIsZero(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc, bool f64Bit) 8712 8902 { 8713 8903 #if defined(RT_ARCH_AMD64) 8714 off = iemNativeEmitTestIfGprIsZeroAndTbExitEx(pReNative, iemNativeInstrBufEnsure(pReNative, off, 3 + 6), 8715 off, iGprSrc, f64Bit, enmExitReason); 8716 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8717 return off; 8718 #else 8719 IEMNATIVE_ASSERT_EFLAGS_SKIPPING_ONLY(pReNative, X86_EFL_STATUS_BITS); 8720 IEMNATIVE_ASSERT_EFLAGS_POSTPONING_ONLY(pReNative, X86_EFL_STATUS_BITS); /** @todo emit postponed stuff here and invert the condition. */ 8721 uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/); 8722 return iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToLabel(pReNative, off, iGprSrc, f64Bit, false /*fJmpIfNotZero*/, idxLabel); 8723 #endif 8904 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3 + 6 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 8905 8906 #else 8907 PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3 + IEMNATIVE_MAX_POSTPONED_EFLAGS_INSTRUCTIONS); 8908 #endif 8909 off = iemNativeEmitTbExitIfGprIsZeroEx<a_enmExitReason, a_fPostponedEfl>(pReNative, pCodeBuf, off, iGprSrc, f64Bit); 8910 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 8911 return off; 8724 8912 } 8725 8913
Note:
See TracChangeset
for help on using the changeset viewer.