- Timestamp:
- Jan 3, 2024 7:45:42 PM (13 months ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompBltIn.cpp
r102755 r102756 242 242 iemNativeFixupFixedJump(pReNative, offFixupJumpToVmCheck1, off); 243 243 off = iemNativeEmitLoadGprFromVCpuU64(pReNative, off, idxTmpReg, RT_UOFFSETOF(VMCPUCC, CTX_SUFF(pVM))); /* idxTmpReg = pVM */ 244 off = iemNativeEmitLoadGpr 32ByGpr(pReNative, off, idxTmpReg, idxTmpReg, RT_UOFFSETOF(VMCC, fGlobalForcedActions));244 off = iemNativeEmitLoadGprByGprU32(pReNative, off, idxTmpReg, idxTmpReg, RT_UOFFSETOF(VMCC, fGlobalForcedActions)); 245 245 off = iemNativeEmitAndGpr32ByImm(pReNative, off, idxTmpReg, VM_FF_ALL_MASK, true /*fSetFlags*/); 246 246 off = iemNativeEmitJnzToLabel(pReNative, off, idxLabelReturnBreak); -
trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
r102742 r102756 10021 10021 10022 10022 IEMNATIVEEMITTLBSTATE(PIEMRECOMPILERSTATE a_pReNative, uint32_t *a_poff, uint8_t a_idxVarGCPtrMem, 10023 uint8_t a_iSegReg, uint8_t a_cbMem )10023 uint8_t a_iSegReg, uint8_t a_cbMem, uint8_t a_offDisp = 0) 10024 10024 #ifdef IEMNATIVE_WITH_TLB_LOOKUP 10025 10025 /* 32-bit and 64-bit wraparound will require special handling, so skip these for absolute addresses. */ 10026 10026 : fSkip( a_pReNative->Core.aVars[a_idxVarGCPtrMem].enmKind == kIemNativeVarKind_Immediate 10027 10027 && ( (a_pReNative->fExec & IEM_F_MODE_CPUMODE_MASK) != IEMMODE_64BIT 10028 ? (uint64_t)(UINT32_MAX - a_cbMem )10029 : (uint64_t)(UINT64_MAX - a_cbMem ))10028 ? (uint64_t)(UINT32_MAX - a_cbMem - a_offDisp) 10029 : (uint64_t)(UINT64_MAX - a_cbMem - a_offDisp)) 10030 10030 < a_pReNative->Core.aVars[a_idxVarGCPtrMem].u.uValue) 10031 10031 #else … … 10047 10047 ? UINT8_MAX 10048 10048 : iemNativeRegAllocTmpForGuestReg(a_pReNative, a_poff, IEMNATIVEGSTREG_SEG_BASE(a_iSegReg))) 10049 , idxRegSegLimit((a_iSegReg == UINT8_MAX && (a_pReNative->fExec & IEM_F_MODE_CPUMODE_MASK) != IEMMODE_64BIT) || fSkip10049 , idxRegSegLimit((a_iSegReg == UINT8_MAX || (a_pReNative->fExec & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_64BIT) || fSkip 10050 10050 ? UINT8_MAX 10051 10051 : iemNativeRegAllocTmpForGuestReg(a_pReNative, a_poff, IEMNATIVEGSTREG_SEG_LIMIT(a_iSegReg))) 10052 , idxRegSegAttrib((a_iSegReg == UINT8_MAX && (a_pReNative->fExec & IEM_F_MODE_CPUMODE_MASK) != IEMMODE_64BIT) || fSkip10052 , idxRegSegAttrib((a_iSegReg == UINT8_MAX || (a_pReNative->fExec & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_64BIT) || fSkip 10053 10053 ? UINT8_MAX 10054 10054 : iemNativeRegAllocTmpForGuestReg(a_pReNative, a_poff, IEMNATIVEGSTREG_SEG_ATTRIB(a_iSegReg))) … … 10178 10178 uint8_t offDisp = 0) 10179 10179 { 10180 RT_NOREF(offDisp);10181 10180 Assert(!pTlbState->fSkip); 10182 10181 # if defined(RT_ARCH_AMD64) … … 10196 10195 { 10197 10196 off = iemNativeEmitBrkEx(pCodeBuf, off, 1); /** @todo this needs testing */ 10198 /* cmp seglim, regptr */ /** @todo r=bird: why 64-bit compare again? */ 10199 if (pTlbState->idxRegPtr != UINT8_MAX) 10200 off = iemNativeEmitCmpGprWithGprEx(pCodeBuf, off, pTlbState->idxRegSegLimit, pTlbState->idxRegPtr); 10197 /* cmp seglim, regptr */ 10198 if (pTlbState->idxRegPtr != UINT8_MAX && offDisp == 0) 10199 off = iemNativeEmitCmpGpr32WithGprEx(pCodeBuf, off, pTlbState->idxRegSegLimit, pTlbState->idxRegPtr); 10200 else if (pTlbState->idxRegPtr == UINT8_MAX) 10201 off = iemNativeEmitCmpGpr32WithImmEx(pCodeBuf, off, pTlbState->idxRegSegLimit, 10202 (uint32_t)(pTlbState->uAbsPtr + offDisp)); 10203 else if (cbMem == 1) 10204 off = iemNativeEmitCmpGpr32WithGprEx(pCodeBuf, off, pTlbState->idxRegSegLimit, pTlbState->idxReg2); 10201 10205 else 10202 off = iemNativeEmitCmpGpr32WithImmEx(pCodeBuf, off, pTlbState->idxRegSegLimit, (uint32_t)pTlbState->uAbsPtr); 10206 { /* use idxRegMemResult to calc the displaced address. */ 10207 off = iemNativeEmitGpr32EqGprPlusImmEx(pCodeBuf, off, idxRegMemResult, pTlbState->idxRegPtr, offDisp); 10208 off = iemNativeEmitCmpGpr32WithGprEx(pCodeBuf, off, pTlbState->idxRegSegLimit, idxRegMemResult); 10209 } 10203 10210 /* ja tlbmiss */ 10204 10211 off = iemNativeEmitJccToLabelEx(pReNative, pCodeBuf, off, idxLabelTlbMiss, kIemNativeInstrCond_nbe); 10212 10205 10213 /* reg1 = segattr & X86DESCATTR_D (0x4000) */ 10206 10214 off = iemNativeEmitGpr32EqGprAndImmEx(pCodeBuf, off, pTlbState->idxReg1, pTlbState->idxRegSegAttrib, X86DESCATTR_D); … … 10215 10223 if (pTlbState->idxRegPtr != UINT8_MAX) 10216 10224 off = iemNativeEmitCmpGprWithGprEx(pCodeBuf, off, pTlbState->idxReg1, 10217 cbMem > 1 ? pTlbState->idxReg2 : pTlbState->idxRegPtr);10225 cbMem > 1 || offDisp != 0 ? pTlbState->idxReg2 : pTlbState->idxRegPtr); 10218 10226 else 10219 off = iemNativeEmitCmpGpr32WithImmEx(pCodeBuf, off, pTlbState->idxReg1, (uint32_t)(pTlbState->uAbsPtr + cbMem - 1)); 10227 off = iemNativeEmitCmpGpr32WithImmEx(pCodeBuf, off, pTlbState->idxReg1, 10228 (uint32_t)(pTlbState->uAbsPtr + offDisp + cbMem - 1)); /* fSkip=true on overflow. */ 10220 10229 /* jbe tlbmiss */ 10221 10230 off = iemNativeEmitJccToLabelEx(pReNative, pCodeBuf, off, idxLabelTlbMiss, kIemNativeInstrCond_be); … … 10240 10249 if (iSegReg != UINT8_MAX && (pReNative->fExec & IEM_F_MODE_CPUMODE_MASK) != IEMMODE_64BIT) 10241 10250 { 10242 /* If we're accessing more than one byte, put the last address we'll be10243 accessing in idxReg2 (64-bit). */10244 if (cbMem > 1 && pTlbState->idxRegPtr != UINT8_MAX)10245 {10246 /* reg2 = regptr + cbMem - 1 ; 64-bit result so we can fend of wraparounds/overflows. */10247 off = iemNativeEmitGprEqGprPlusImmEx(pCodeBuf, off, pTlbState->idxReg2,/*=*/ pTlbState->idxRegPtr,/*+*/ cbMem - 1);10248 }10249 10250 10251 /* Check that we've got a segment loaded and that it allows the access. 10251 10252 For write access this means a writable data segment. … … 10296 10297 } 10297 10298 10299 /* If we're accessing more than one byte or if we're working with a non-zero offDisp, 10300 put the last address we'll be accessing in idxReg2 (64-bit). */ 10301 if ((cbMem > 1 || offDisp != 0) && pTlbState->idxRegPtr != UINT8_MAX) 10302 { 10303 if (!offDisp) 10304 /* reg2 = regptr + cbMem - 1; 64-bit result so we can fend of wraparounds/overflows. */ 10305 off = iemNativeEmitGprEqGprPlusImmEx(pCodeBuf, off, pTlbState->idxReg2,/*=*/ pTlbState->idxRegPtr,/*+*/ cbMem - 1); 10306 else 10307 { 10308 /* reg2 = (uint32_t)(regptr + offDisp) + cbMem - 1;. */ 10309 off = iemNativeEmitGpr32EqGprPlusImmEx(pCodeBuf, off, 10310 pTlbState->idxReg2,/*=*/ pTlbState->idxRegPtr,/*+*/ + offDisp); 10311 off = iemNativeEmitAddGprImmEx(pCodeBuf, off, pTlbState->idxReg2, cbMem - 1); 10312 } 10313 } 10314 10298 10315 /* 10299 10316 * Check the limit. If this is a write access, we know that it's a … … 10323 10340 cmp seglim, regptr/reg2/imm */ 10324 10341 if (pTlbState->idxRegPtr != UINT8_MAX) 10325 off = iemNativeEmitCmpGprWithGprEx(pCodeBuf, off, pTlbState->idxRegSegLimit, cbMem > 1 ? pTlbState->idxReg2 : pTlbState->idxRegPtr); 10342 off = iemNativeEmitCmpGprWithGprEx(pCodeBuf, off, pTlbState->idxRegSegLimit, 10343 cbMem > 1 || offDisp != 0 ? pTlbState->idxReg2 : pTlbState->idxRegPtr); 10326 10344 else 10327 off = iemNativeEmitCmpGpr32WithImmEx(pCodeBuf, off, pTlbState->idxRegSegLimit, (uint32_t)pTlbState->uAbsPtr); 10345 off = iemNativeEmitCmpGpr32WithImmEx(pCodeBuf, off, pTlbState->idxRegSegLimit, 10346 (uint32_t)pTlbState->uAbsPtr + offDisp + cbMem - 1U); /* fSkip=true on overflow. */ 10328 10347 /* jbe tlbmiss */ 10329 10348 off = iemNativeEmitJccToLabelEx(pReNative, pCodeBuf, off, idxLabelTlbMiss, kIemNativeInstrCond_be); … … 10333 10352 } 10334 10353 10335 /* 1b. Add the segment base. We use idxRegMemResult for the ptr register if this step is 10336 required or if the address is a constant (simplicity). */ 10337 uint8_t const idxRegFlatPtr = iSegReg != UINT8_MAX || pTlbState->idxRegPtr == UINT8_MAX 10354 /* 1b. Add the segment base. We use idxRegMemResult for the ptr register if 10355 this step is required or if the address is a constant (simplicity) or 10356 if offDisp is non-zero. */ 10357 uint8_t const idxRegFlatPtr = iSegReg != UINT8_MAX || pTlbState->idxRegPtr == UINT8_MAX || offDisp != 0 10338 10358 ? idxRegMemResult : pTlbState->idxRegPtr; 10339 10359 if (iSegReg != UINT8_MAX) 10340 10360 { 10361 Assert(idxRegFlatPtr != pTlbState->idxRegPtr); 10341 10362 /* regflat = segbase + regptr/imm */ 10342 10363 if ((pReNative->fExec & IEM_F_MODE_MASK) == IEM_F_MODE_X86_64BIT) … … 10344 10365 Assert(iSegReg >= X86_SREG_FS); 10345 10366 if (pTlbState->idxRegPtr != UINT8_MAX) 10367 { 10346 10368 off = iemNativeEmitGprEqGprPlusGprEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->idxRegSegBase, pTlbState->idxRegPtr); 10369 if (offDisp != 0) 10370 off = iemNativeEmitAddGprImmEx(pCodeBuf, off, idxRegFlatPtr, offDisp); 10371 } 10347 10372 else 10348 off = iemNativeEmitGprEqGprPlusImmEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->idxRegSegBase, pTlbState->uAbsPtr); 10373 off = iemNativeEmitGprEqGprPlusImmEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->idxRegSegBase, 10374 pTlbState->uAbsPtr + offDisp); 10349 10375 } 10350 10376 else if (pTlbState->idxRegPtr != UINT8_MAX) 10377 { 10351 10378 off = iemNativeEmitGpr32EqGprPlusGprEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->idxRegSegBase, pTlbState->idxRegPtr); 10379 if (offDisp != 0) 10380 off = iemNativeEmitAddGpr32ImmEx(pCodeBuf, off, idxRegFlatPtr, offDisp); 10381 } 10352 10382 else 10353 10383 off = iemNativeEmitGpr32EqGprPlusImmEx(pCodeBuf, off, idxRegFlatPtr, 10354 pTlbState->idxRegSegBase, (uint32_t)pTlbState->uAbsPtr );10384 pTlbState->idxRegSegBase, (uint32_t)pTlbState->uAbsPtr + offDisp); 10355 10385 } 10356 10386 else if (pTlbState->idxRegPtr == UINT8_MAX) 10357 off = iemNativeEmitLoadGprImmEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->uAbsPtr); 10387 { 10388 if ((pReNative->fExec & IEM_F_MODE_MASK) == IEM_F_MODE_X86_64BIT) 10389 off = iemNativeEmitLoadGprImmEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->uAbsPtr + offDisp); 10390 else 10391 off = iemNativeEmitLoadGpr32ImmEx(pCodeBuf, off, idxRegFlatPtr, (uint32_t)pTlbState->uAbsPtr + offDisp); 10392 } 10393 else if (offDisp != 0) 10394 { 10395 Assert(idxRegFlatPtr != pTlbState->idxRegPtr); 10396 if ((pReNative->fExec & IEM_F_MODE_MASK) == IEM_F_MODE_X86_64BIT) 10397 off = iemNativeEmitGprEqGprPlusImmEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->idxRegPtr, offDisp); 10398 else 10399 off = iemNativeEmitGpr32EqGprPlusImmEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->idxRegPtr, offDisp); 10400 } 10401 else 10402 Assert(idxRegFlatPtr == pTlbState->idxRegPtr); 10358 10403 10359 10404 /* … … 10491 10536 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, pTlbState->idxReg1, pTlbState->idxReg2, RT_UOFFSETOF(IEMTLBENTRY, uTag)); 10492 10537 # elif defined(RT_ARCH_ARM64) 10493 off = iemNativeEmitLoadGprByGpr Ex(pCodeBuf, off, pTlbState->idxReg3, pTlbState->idxReg2, RT_UOFFSETOF(IEMTLBENTRY, uTag));10538 off = iemNativeEmitLoadGprByGprU64Ex(pCodeBuf, off, pTlbState->idxReg3, pTlbState->idxReg2, RT_UOFFSETOF(IEMTLBENTRY, uTag)); 10494 10539 off = iemNativeEmitCmpGprWithGprEx(pCodeBuf, off, pTlbState->idxReg1, pTlbState->idxReg3); 10495 10540 # else … … 10525 10570 RT_UOFFSETOF(VMCPUCC, iem.s.DataTlb.uTlbPhysRev)); 10526 10571 # elif defined(RT_ARCH_ARM64) 10527 off = iemNativeEmitLoadGprByGpr Ex(pCodeBuf, off, pTlbState->idxReg3, pTlbState->idxReg2,10528 RT_UOFFSETOF(IEMTLBENTRY, fFlagsAndPhysRev));10572 off = iemNativeEmitLoadGprByGprU64Ex(pCodeBuf, off, pTlbState->idxReg3, pTlbState->idxReg2, 10573 RT_UOFFSETOF(IEMTLBENTRY, fFlagsAndPhysRev)); 10529 10574 pCodeBuf[off++] = Armv8A64MkInstrAnd(pTlbState->idxReg1, pTlbState->idxReg1, pTlbState->idxReg3); 10530 10575 off = iemNativeEmitLoadGprFromVCpuU64Ex(pCodeBuf, off, pTlbState->idxReg3, RT_UOFFSETOF(VMCPUCC, iem.s.DataTlb.uTlbPhysRev)); … … 10541 10586 */ 10542 10587 /* mov reg1, [reg2->pbMappingR3] */ 10543 off = iemNativeEmitLoadGprByGpr Ex(pCodeBuf, off, pTlbState->idxReg1, pTlbState->idxReg2,10544 RT_UOFFSETOF(IEMTLBENTRY, pbMappingR3));10588 off = iemNativeEmitLoadGprByGprU64Ex(pCodeBuf, off, pTlbState->idxReg1, pTlbState->idxReg2, 10589 RT_UOFFSETOF(IEMTLBENTRY, pbMappingR3)); 10545 10590 /* if (!reg1) goto tlbmiss; */ 10546 10591 /** @todo eliminate the need for this test? */ … … 10773 10818 * register if we can). 10774 10819 */ 10775 uint16_t const uTlbSeqNo = pReNative->uTlbSeqNo++; 10776 uint32_t const idxLabelTlbMiss = iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbMiss, UINT32_MAX, uTlbSeqNo); 10777 uint32_t const idxLabelTlbDone = iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbDone, UINT32_MAX, uTlbSeqNo); 10778 uint8_t const idxRegValueFetch = enmOp == kIemNativeEmitMemOp_Store ? UINT8_MAX /* special case value storing below */ 10779 : !(pReNative->Core.bmHstRegs & RT_BIT_32(IEMNATIVE_CALL_RET_GREG)) 10780 ? iemNativeVarRegisterSetAndAcquire(pReNative, idxVarValue, IEMNATIVE_CALL_RET_GREG, &off) 10781 : iemNativeVarRegisterAcquire(pReNative, idxVarValue, &off); 10782 10783 /* 10784 * First we try to go via the TLB. 10785 */ 10786 //pReNative->pInstrBuf[off++] = 0xcc; 10787 /** @todo later. */ 10788 RT_NOREF(fAlignMask, cbMem); 10789 10790 /* 10820 uint16_t const uTlbSeqNo = pReNative->uTlbSeqNo++; 10821 uint8_t const idxRegValueFetch = enmOp == kIemNativeEmitMemOp_Store ? UINT8_MAX 10822 : !(pReNative->Core.bmHstRegs & RT_BIT_32(IEMNATIVE_CALL_RET_GREG)) 10823 ? iemNativeVarRegisterSetAndAcquire(pReNative, idxVarValue, IEMNATIVE_CALL_RET_GREG, &off) 10824 : iemNativeVarRegisterAcquire(pReNative, idxVarValue, &off); 10825 IEMNATIVEEMITTLBSTATE const TlbState(pReNative, &off, idxVarGCPtrMem, iSegReg, cbMem, offDisp); 10826 uint8_t const idxRegValueStore = !TlbState.fSkip 10827 && enmOp == kIemNativeEmitMemOp_Store 10828 && pReNative->Core.aVars[idxVarValue].enmKind != kIemNativeVarKind_Immediate 10829 ? iemNativeVarRegisterAcquire(pReNative, idxVarValue, &off) 10830 : UINT8_MAX; 10831 uint32_t const idxRegMemResult = !TlbState.fSkip ? iemNativeRegAllocTmp(pReNative, &off) : UINT8_MAX; 10832 uint32_t const idxLabelTlbLookup = !TlbState.fSkip 10833 ? iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbLookup, UINT32_MAX, uTlbSeqNo) 10834 : UINT32_MAX; 10835 10836 /* 10837 * Jump to the TLB lookup code. 10838 */ 10839 if (!TlbState.fSkip) 10840 off = iemNativeEmitJmpToLabel(pReNative, off, idxLabelTlbLookup); /** @todo short jump */ 10841 10842 /* 10843 * TlbMiss: 10844 * 10791 10845 * Call helper to do the fetching. 10792 10846 * We flush all guest register shadow copies here. 10793 10847 */ 10794 iemNativeLabelDefine(pReNative, idxLabelTlbMiss, off);10848 uint32_t const idxLabelTlbMiss = iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbMiss, off, uTlbSeqNo); 10795 10849 10796 10850 #ifdef IEMNATIVE_WITH_INSTRUCTION_COUNTING … … 10800 10854 #endif 10801 10855 10802 uint8_t idxRegArgValue;10803 if (iSegReg == UINT8_MAX)10804 idxRegArgValue = IEMNATIVE_CALL_ARG2_GREG;10805 else10806 {10807 /* IEMNATIVE_CALL_ARG2_GREG = iSegReg */10808 AssertStmt(iSegReg < 6, IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_EMIT_BAD_SEG_REG_NO));10809 off = iemNativeEmitLoadGpr8Imm(pReNative, off, IEMNATIVE_CALL_ARG2_GREG, iSegReg);10810 10811 idxRegArgValue = IEMNATIVE_CALL_ARG3_GREG;10812 }10813 10814 10856 /* IEMNATIVE_CALL_ARG2/3_GREG = uValue (idxVarValue) - if store */ 10815 10857 if (enmOp == kIemNativeEmitMemOp_Store) 10816 10858 { 10859 uint8_t const idxRegArgValue = iSegReg == UINT8_MAX ? IEMNATIVE_CALL_ARG2_GREG : IEMNATIVE_CALL_ARG3_GREG; 10817 10860 if (pReNative->Core.aVars[idxVarValue].enmKind == kIemNativeVarKind_Immediate) 10818 10861 off = iemNativeEmitLoadGprImm64(pReNative, off, idxRegArgValue, pReNative->Core.aVars[idxVarValue].u.uValue); … … 10860 10903 } 10861 10904 10905 if (iSegReg != UINT8_MAX) 10906 { 10907 /* IEMNATIVE_CALL_ARG2_GREG = iSegReg */ 10908 AssertStmt(iSegReg < 6, IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_EMIT_BAD_SEG_REG_NO)); 10909 off = iemNativeEmitLoadGpr8Imm(pReNative, off, IEMNATIVE_CALL_ARG2_GREG, iSegReg); 10910 } 10911 10862 10912 /* IEMNATIVE_CALL_ARG0_GREG = pVCpu */ 10863 10913 off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU); … … 10874 10924 if (idxRegValueFetch != IEMNATIVE_CALL_RET_GREG) 10875 10925 off = iemNativeEmitLoadGprFromGpr(pReNative, off, idxRegValueFetch, IEMNATIVE_CALL_RET_GREG); 10926 } 10927 10928 #ifdef IEMNATIVE_WITH_TLB_LOOKUP 10929 if (!TlbState.fSkip) 10930 { 10931 /* end of tlbsmiss - Jump to the done label. */ 10932 uint32_t const idxLabelTlbDone = iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbDone, UINT32_MAX, uTlbSeqNo); 10933 off = iemNativeEmitJmpToLabel(pReNative, off, idxLabelTlbDone); 10934 10935 /* 10936 * TlbLookup: 10937 */ 10938 off = iemNativeEmitTlbLookup(pReNative, off, &TlbState, iSegReg, cbMem, fAlignMask, 10939 enmOp == kIemNativeEmitMemOp_Store ? IEM_ACCESS_TYPE_WRITE : IEM_ACCESS_TYPE_READ, 10940 idxLabelTlbLookup, idxLabelTlbMiss, idxRegMemResult, offDisp); 10941 10942 /* 10943 * Emit code to do the actual storing / fetching. 10944 */ 10945 PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 64); 10946 switch (enmOp) 10947 { 10948 case kIemNativeEmitMemOp_Store: 10949 if (pReNative->Core.aVars[idxVarValue].enmKind != kIemNativeVarKind_Immediate) 10950 { 10951 switch (cbMem) 10952 { 10953 case 1: 10954 off = iemNativeEmitStoreGpr8ByGprEx(pCodeBuf, off, idxRegValueStore, idxRegMemResult); 10955 break; 10956 case 2: 10957 off = iemNativeEmitStoreGpr16ByGprEx(pCodeBuf, off, idxRegValueStore, idxRegMemResult); 10958 break; 10959 case 4: 10960 off = iemNativeEmitStoreGpr32ByGprEx(pCodeBuf, off, idxRegValueStore, idxRegMemResult); 10961 break; 10962 case 8: 10963 off = iemNativeEmitStoreGpr64ByGprEx(pCodeBuf, off, idxRegValueStore, idxRegMemResult); 10964 break; 10965 default: 10966 AssertFailed(); 10967 } 10968 } 10969 else 10970 { 10971 switch (cbMem) 10972 { 10973 case 1: 10974 off = iemNativeEmitStoreImm8ByGprEx(pCodeBuf, off, 10975 (uint8_t)pReNative->Core.aVars[idxVarValue].u.uValue, 10976 idxRegMemResult, TlbState.idxReg1); 10977 break; 10978 case 2: 10979 off = iemNativeEmitStoreImm16ByGprEx(pCodeBuf, off, 10980 (uint16_t)pReNative->Core.aVars[idxVarValue].u.uValue, 10981 idxRegMemResult, TlbState.idxReg1); 10982 break; 10983 case 4: 10984 off = iemNativeEmitStoreImm32ByGprEx(pCodeBuf, off, 10985 (uint32_t)pReNative->Core.aVars[idxVarValue].u.uValue, 10986 idxRegMemResult, TlbState.idxReg1); 10987 break; 10988 case 8: 10989 off = iemNativeEmitStoreImm64ByGprEx(pCodeBuf, off, pReNative->Core.aVars[idxVarValue].u.uValue, 10990 idxRegMemResult, TlbState.idxReg1); 10991 break; 10992 default: 10993 AssertFailed(); 10994 } 10995 } 10996 break; 10997 10998 case kIemNativeEmitMemOp_Fetch: 10999 case kIemNativeEmitMemOp_Fetch_Zx_U16: 11000 case kIemNativeEmitMemOp_Fetch_Zx_U32: 11001 case kIemNativeEmitMemOp_Fetch_Zx_U64: 11002 switch (cbMem) 11003 { 11004 case 1: 11005 off = iemNativeEmitLoadGprByGprU8Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult); 11006 break; 11007 case 2: 11008 off = iemNativeEmitLoadGprByGprU16Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult); 11009 break; 11010 case 4: 11011 off = iemNativeEmitLoadGprByGprU32Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult); 11012 break; 11013 case 8: 11014 off = iemNativeEmitLoadGprByGprU64Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult); 11015 break; 11016 default: 11017 AssertFailed(); 11018 } 11019 break; 11020 11021 case kIemNativeEmitMemOp_Fetch_Sx_U16: 11022 Assert(cbMem == 1); 11023 off = iemNativeEmitLoadGprByGprU16SignExtendedFromS8Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult); 11024 break; 11025 11026 case kIemNativeEmitMemOp_Fetch_Sx_U32: 11027 Assert(cbMem == 1 || cbMem == 2); 11028 if (cbMem == 1) 11029 off = iemNativeEmitLoadGprByGprU32SignExtendedFromS8Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult); 11030 else 11031 off = iemNativeEmitLoadGprByGprU32SignExtendedFromS16Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult); 11032 break; 11033 11034 case kIemNativeEmitMemOp_Fetch_Sx_U64: 11035 switch (cbMem) 11036 { 11037 case 1: 11038 off = iemNativeEmitLoadGprByGprU64SignExtendedFromS8Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult); 11039 break; 11040 case 2: 11041 off = iemNativeEmitLoadGprByGprU64SignExtendedFromS16Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult); 11042 break; 11043 case 4: 11044 off = iemNativeEmitLoadGprByGprU64SignExtendedFromS32Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult); 11045 break; 11046 default: 11047 AssertFailed(); 11048 } 11049 break; 11050 11051 default: 11052 AssertFailed(); 11053 } 11054 11055 iemNativeRegFreeTmp(pReNative, idxRegMemResult); 11056 11057 /* 11058 * TlbDone: 11059 */ 11060 iemNativeLabelDefine(pReNative, idxLabelTlbDone, off); 11061 11062 TlbState.freeRegsAndReleaseVars(pReNative, idxVarGCPtrMem); 11063 11064 # ifndef IEMNATIVE_WITH_FREE_AND_FLUSH_VOLATILE_REGS_AT_TLB_LOOKUP 11065 /* Temp Hack: Flush all guest shadows in volatile registers in case of TLB miss. */ 11066 iemNativeRegFlushGuestShadowsByHostMask(pReNative, IEMNATIVE_CALL_VOLATILE_GREG_MASK); 11067 # endif 11068 } 11069 #else 11070 RT_NOREF(fAccess, fAlignMask, idxLabelTlbMiss); 11071 #endif 11072 11073 if (idxRegValueFetch != UINT8_MAX || idxRegValueStore != UINT8_MAX) 10876 11074 iemNativeVarRegisterRelease(pReNative, idxVarValue); 10877 }10878 10879 iemNativeLabelDefine(pReNative, idxLabelTlbDone, off);10880 10881 11075 return off; 10882 11076 } … … 11782 11976 /* 11783 11977 * Define labels and allocate the result register (trying for the return 11784 * register if we can - which we of course can, given the above call). 11785 */ 11786 uint16_t const uTlbSeqNo = pReNative->uTlbSeqNo++; 11787 uint8_t const idxRegMemResult = !(pReNative->Core.bmHstRegs & RT_BIT_32(IEMNATIVE_CALL_RET_GREG)) 11788 ? iemNativeVarRegisterSetAndAcquire(pReNative, idxVarMem, IEMNATIVE_CALL_RET_GREG, &off) 11789 : iemNativeVarRegisterAcquire(pReNative, idxVarMem, &off); 11790 11978 * register if we can). 11979 */ 11980 uint16_t const uTlbSeqNo = pReNative->uTlbSeqNo++; 11981 uint8_t const idxRegMemResult = !(pReNative->Core.bmHstRegs & RT_BIT_32(IEMNATIVE_CALL_RET_GREG)) 11982 ? iemNativeVarRegisterSetAndAcquire(pReNative, idxVarMem, IEMNATIVE_CALL_RET_GREG, &off) 11983 : iemNativeVarRegisterAcquire(pReNative, idxVarMem, &off); 11791 11984 IEMNATIVEEMITTLBSTATE const TlbState(pReNative, &off, idxVarGCPtrMem, iSegReg, cbMem); 11792 11793 11985 uint32_t const idxLabelTlbLookup = !TlbState.fSkip 11794 11986 ? iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbLookup, UINT32_MAX, uTlbSeqNo) … … 11802 11994 11803 11995 /* 11804 * tlbmiss:11996 * TlbMiss: 11805 11997 * 11806 11998 * Call helper to do the fetching. … … 11870 12062 11871 12063 /* 11872 * tlblookup:12064 * TlbLookup: 11873 12065 */ 11874 12066 off = iemNativeEmitTlbLookup(pReNative, off, &TlbState, iSegReg, cbMem, fAlignMask, fAccess, 11875 12067 idxLabelTlbLookup, idxLabelTlbMiss, idxRegMemResult); 11876 12068 12069 /* [idxVarUnmapInfo] = 0; */ 12070 off = iemNativeEmitLoadGprImm32(pReNative, off, idxRegUnmapInfo, 0); 12071 11877 12072 /* 11878 * Lookup tail code, specific to the MC when the above is moved into a separate function. 11879 */ 11880 /* [idxVarUnmapInfo] = 0 - allocate register for it. There must be free ones now, so no spilling required. */ 11881 off = iemNativeEmitLoadGprImm32(pReNative, off, idxRegUnmapInfo, 0); 11882 11883 /* 11884 * tlbdone: 12073 * TlbDone: 11885 12074 */ 11886 12075 iemNativeLabelDefine(pReNative, idxLabelTlbDone, off); -
trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h
r102741 r102756 1800 1800 */ 1801 1801 DECL_FORCE_INLINE_THROW(uint32_t) 1802 iemNativeEmitLoadGprByGpr Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase,1803 int32_t offDisp, uint8_t iGprTmp = UINT8_MAX)1802 iemNativeEmitLoadGprByGprU64Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, 1803 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 1804 1804 { 1805 1805 #ifdef RT_ARCH_AMD64 … … 1825 1825 */ 1826 1826 DECL_INLINE_THROW(uint32_t) 1827 iemNativeEmitLoadGprByGpr (PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, int32_t offDisp)1828 { 1829 #ifdef RT_ARCH_AMD64 1830 off = iemNativeEmitLoadGprByGpr Ex(iemNativeInstrBufEnsure(pReNative, off, 8), off, iGprDst, iGprBase, offDisp);1827 iemNativeEmitLoadGprByGprU64(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, int32_t offDisp) 1828 { 1829 #ifdef RT_ARCH_AMD64 1830 off = iemNativeEmitLoadGprByGprU64Ex(iemNativeInstrBufEnsure(pReNative, off, 8), off, iGprDst, iGprBase, offDisp); 1831 1831 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 1832 1832 1833 1833 #elif defined(RT_ARCH_ARM64) 1834 1834 off = iemNativeEmitGprByGprLdSt(pReNative, off, iGprDst, iGprBase, offDisp, kArmv8A64InstrLdStType_Ld_Dword, sizeof(uint64_t)); 1835 1836 #else 1837 # error "port me" 1838 #endif 1839 return off; 1840 } 1841 1842 1843 /** 1844 * Emits a 32-bit GPR load via a GPR base address with a displacement. 1845 * 1846 * @note ARM64: Misaligned @a offDisp values and values not in the 1847 * -0x3ffc...0x3ffc range will require a temporary register (@a iGprTmp) 1848 * if @a iGprReg and @a iGprBase are the same. Will assert / throw if 1849 * caller does not heed this. 1850 * 1851 * @note Bits 63 thru 32 in @a iGprDst will be cleared. 1852 */ 1853 DECL_FORCE_INLINE_THROW(uint32_t) 1854 iemNativeEmitLoadGprByGprU32Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, 1855 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 1856 { 1857 #ifdef RT_ARCH_AMD64 1858 /* mov reg32, mem32 */ 1859 if (iGprDst >= 8 || iGprBase >= 8) 1860 pCodeBuf[off++] = (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 1861 pCodeBuf[off++] = 0x8b; 1862 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprDst, iGprBase, offDisp); 1863 RT_NOREF(iGprTmp); 1864 1865 #elif defined(RT_ARCH_ARM64) 1866 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprDst, iGprBase, offDisp, 1867 kArmv8A64InstrLdStType_Ld_Word, sizeof(uint32_t), iGprTmp); 1835 1868 1836 1869 #else … … 1846 1879 */ 1847 1880 DECL_INLINE_THROW(uint32_t) 1848 iemNativeEmitLoadGpr32ByGpr(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, int32_t offDisp) 1849 { 1850 #ifdef RT_ARCH_AMD64 1851 /* mov reg32, mem32 */ 1852 uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 8); 1881 iemNativeEmitLoadGprByGprU32(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, int32_t offDisp) 1882 { 1883 #ifdef RT_ARCH_AMD64 1884 off = iemNativeEmitLoadGprByGprU32Ex(iemNativeInstrBufEnsure(pReNative, off, 8), off, iGprDst, iGprBase, offDisp); 1885 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 1886 1887 #elif defined(RT_ARCH_ARM64) 1888 off = iemNativeEmitGprByGprLdSt(pReNative, off, iGprDst, iGprBase, offDisp, kArmv8A64InstrLdStType_Ld_Word, sizeof(uint32_t)); 1889 1890 #else 1891 # error "port me" 1892 #endif 1893 return off; 1894 } 1895 1896 1897 /** 1898 * Emits a 32-bit GPR load via a GPR base address with a displacement, 1899 * sign-extending the value to 64 bits. 1900 * 1901 * @note ARM64: Misaligned @a offDisp values and values not in the 1902 * -0x3ffc...0x3ffc range will require a temporary register (@a iGprTmp) 1903 * if @a iGprReg and @a iGprBase are the same. Will assert / throw if 1904 * caller does not heed this. 1905 */ 1906 DECL_FORCE_INLINE_THROW(uint32_t) 1907 iemNativeEmitLoadGprByGprU64SignExtendedFromS32Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, 1908 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 1909 { 1910 #ifdef RT_ARCH_AMD64 1911 /* movsxd reg64, mem32 */ 1912 pCodeBuf[off++] = X86_OP_REX_W | (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 1913 pCodeBuf[off++] = 0x63; 1914 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprDst, iGprBase, offDisp); 1915 RT_NOREF(iGprTmp); 1916 1917 #elif defined(RT_ARCH_ARM64) 1918 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprDst, iGprBase, offDisp, 1919 kArmv8A64InstrLdStType_Ld_SignWord64, sizeof(uint32_t), iGprTmp); 1920 1921 #else 1922 # error "port me" 1923 #endif 1924 return off; 1925 } 1926 1927 1928 /** 1929 * Emits a 16-bit GPR load via a GPR base address with a displacement. 1930 * 1931 * @note ARM64: Misaligned @a offDisp values and values not in the 1932 * -0x1ffe...0x1ffe range will require a temporary register (@a iGprTmp) 1933 * if @a iGprReg and @a iGprBase are the same. Will assert / throw if 1934 * caller does not heed this. 1935 * 1936 * @note Bits 63 thru 16 in @a iGprDst will be cleared. 1937 */ 1938 DECL_FORCE_INLINE_THROW(uint32_t) 1939 iemNativeEmitLoadGprByGprU16Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, 1940 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 1941 { 1942 #ifdef RT_ARCH_AMD64 1943 /* movzx reg32, mem16 */ 1853 1944 if (iGprDst >= 8 || iGprBase >= 8) 1854 pbCodeBuf[off++] = (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 1855 pbCodeBuf[off++] = 0x8b; 1856 off = iemNativeEmitGprByGprDisp(pbCodeBuf, off, iGprDst, iGprBase, offDisp); 1857 IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off); 1858 1859 #elif defined(RT_ARCH_ARM64) 1860 off = iemNativeEmitGprByGprLdSt(pReNative, off, iGprDst, iGprBase, offDisp, kArmv8A64InstrLdStType_Ld_Word, sizeof(uint32_t)); 1861 1862 #else 1863 # error "port me" 1864 #endif 1865 return off; 1866 } 1945 pCodeBuf[off++] = (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 1946 pCodeBuf[off++] = 0x0f; 1947 pCodeBuf[off++] = 0xb7; 1948 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprDst, iGprBase, offDisp); 1949 RT_NOREF(iGprTmp); 1950 1951 #elif defined(RT_ARCH_ARM64) 1952 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprDst, iGprBase, offDisp, 1953 kArmv8A64InstrLdStType_Ld_Half, sizeof(uint16_t), iGprTmp); 1954 1955 #else 1956 # error "port me" 1957 #endif 1958 return off; 1959 } 1960 1961 1962 /** 1963 * Emits a 16-bit GPR load via a GPR base address with a displacement, 1964 * sign-extending the value to 64 bits. 1965 * 1966 * @note ARM64: Misaligned @a offDisp values and values not in the 1967 * -0x1ffe...0x1ffe range will require a temporary register (@a iGprTmp) 1968 * if @a iGprReg and @a iGprBase are the same. Will assert / throw if 1969 * caller does not heed this. 1970 */ 1971 DECL_FORCE_INLINE_THROW(uint32_t) 1972 iemNativeEmitLoadGprByGprU64SignExtendedFromS16Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, 1973 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 1974 { 1975 #ifdef RT_ARCH_AMD64 1976 /* movsx reg64, mem16 */ 1977 pCodeBuf[off++] = X86_OP_REX_W | (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 1978 pCodeBuf[off++] = 0x0f; 1979 pCodeBuf[off++] = 0xbf; 1980 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprDst, iGprBase, offDisp); 1981 RT_NOREF(iGprTmp); 1982 1983 #elif defined(RT_ARCH_ARM64) 1984 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprDst, iGprBase, offDisp, 1985 kArmv8A64InstrLdStType_Ld_SignHalf64, sizeof(uint16_t), iGprTmp); 1986 1987 #else 1988 # error "port me" 1989 #endif 1990 return off; 1991 } 1992 1993 1994 /** 1995 * Emits a 16-bit GPR load via a GPR base address with a displacement, 1996 * sign-extending the value to 32 bits. 1997 * 1998 * @note ARM64: Misaligned @a offDisp values and values not in the 1999 * -0x1ffe...0x1ffe range will require a temporary register (@a iGprTmp) 2000 * if @a iGprReg and @a iGprBase are the same. Will assert / throw if 2001 * caller does not heed this. 2002 * 2003 * @note Bits 63 thru 32 in @a iGprDst will be cleared. 2004 */ 2005 DECL_FORCE_INLINE_THROW(uint32_t) 2006 iemNativeEmitLoadGprByGprU32SignExtendedFromS16Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, 2007 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2008 { 2009 #ifdef RT_ARCH_AMD64 2010 /* movsx reg32, mem16 */ 2011 if (iGprDst >= 8 || iGprBase >= 8) 2012 pCodeBuf[off++] = (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2013 pCodeBuf[off++] = 0x0f; 2014 pCodeBuf[off++] = 0xbf; 2015 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprDst, iGprBase, offDisp); 2016 RT_NOREF(iGprTmp); 2017 2018 #elif defined(RT_ARCH_ARM64) 2019 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprDst, iGprBase, offDisp, 2020 kArmv8A64InstrLdStType_Ld_SignHalf32, sizeof(uint16_t), iGprTmp); 2021 2022 #else 2023 # error "port me" 2024 #endif 2025 return off; 2026 } 2027 2028 2029 /** 2030 * Emits a 8-bit GPR load via a GPR base address with a displacement. 2031 * 2032 * @note ARM64: @a offDisp values not in the 0xfff...0xfff range will require a 2033 * temporary register (@a iGprTmp) if @a iGprReg and @a iGprBase are the 2034 * same. Will assert / throw if caller does not heed this. 2035 * 2036 * @note Bits 63 thru 8 in @a iGprDst will be cleared. 2037 */ 2038 DECL_FORCE_INLINE_THROW(uint32_t) 2039 iemNativeEmitLoadGprByGprU8Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, 2040 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2041 { 2042 #ifdef RT_ARCH_AMD64 2043 /* movzx reg32, mem8 */ 2044 if (iGprDst >= 8 || iGprBase >= 8) 2045 pCodeBuf[off++] = (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2046 pCodeBuf[off++] = 0x0f; 2047 pCodeBuf[off++] = 0xb6; 2048 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprDst, iGprBase, offDisp); 2049 RT_NOREF(iGprTmp); 2050 2051 #elif defined(RT_ARCH_ARM64) 2052 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprDst, iGprBase, offDisp, 2053 kArmv8A64InstrLdStType_Ld_Byte, sizeof(uint8_t), iGprTmp); 2054 2055 #else 2056 # error "port me" 2057 #endif 2058 return off; 2059 } 2060 2061 2062 /** 2063 * Emits a 8-bit GPR load via a GPR base address with a displacement, 2064 * sign-extending the value to 64 bits. 2065 * 2066 * @note ARM64: @a offDisp values not in the 0xfff...0xfff range will require a 2067 * temporary register (@a iGprTmp) if @a iGprReg and @a iGprBase are the 2068 * same. Will assert / throw if caller does not heed this. 2069 */ 2070 DECL_FORCE_INLINE_THROW(uint32_t) 2071 iemNativeEmitLoadGprByGprU64SignExtendedFromS8Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, 2072 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2073 { 2074 #ifdef RT_ARCH_AMD64 2075 /* movsx reg64, mem8 */ 2076 pCodeBuf[off++] = X86_OP_REX_W | (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2077 pCodeBuf[off++] = 0x0f; 2078 pCodeBuf[off++] = 0xbe; 2079 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprDst, iGprBase, offDisp); 2080 RT_NOREF(iGprTmp); 2081 2082 #elif defined(RT_ARCH_ARM64) 2083 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprDst, iGprBase, offDisp, 2084 kArmv8A64InstrLdStType_Ld_SignByte64, sizeof(uint8_t), iGprTmp); 2085 2086 #else 2087 # error "port me" 2088 #endif 2089 return off; 2090 } 2091 2092 2093 /** 2094 * Emits a 8-bit GPR load via a GPR base address with a displacement, 2095 * sign-extending the value to 32 bits. 2096 * 2097 * @note ARM64: @a offDisp values not in the 0xfff...0xfff range will require a 2098 * temporary register (@a iGprTmp) if @a iGprReg and @a iGprBase are the 2099 * same. Will assert / throw if caller does not heed this. 2100 * 2101 * @note Bits 63 thru 32 in @a iGprDst will be cleared. 2102 */ 2103 DECL_FORCE_INLINE_THROW(uint32_t) 2104 iemNativeEmitLoadGprByGprU32SignExtendedFromS8Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, 2105 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2106 { 2107 #ifdef RT_ARCH_AMD64 2108 /* movsx reg32, mem8 */ 2109 if (iGprDst >= 8 || iGprBase >= 8) 2110 pCodeBuf[off++] = (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2111 pCodeBuf[off++] = 0x0f; 2112 pCodeBuf[off++] = 0xbe; 2113 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprDst, iGprBase, offDisp); 2114 RT_NOREF(iGprTmp); 2115 2116 #elif defined(RT_ARCH_ARM64) 2117 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprDst, iGprBase, offDisp, 2118 kArmv8A64InstrLdStType_Ld_SignByte32, sizeof(uint8_t), iGprTmp); 2119 2120 #else 2121 # error "port me" 2122 #endif 2123 return off; 2124 } 2125 2126 2127 /** 2128 * Emits a 8-bit GPR load via a GPR base address with a displacement, 2129 * sign-extending the value to 16 bits. 2130 * 2131 * @note ARM64: @a offDisp values not in the 0xfff...0xfff range will require a 2132 * temporary register (@a iGprTmp) if @a iGprReg and @a iGprBase are the 2133 * same. Will assert / throw if caller does not heed this. 2134 * 2135 * @note Bits 63 thru 16 in @a iGprDst will be cleared. 2136 */ 2137 DECL_FORCE_INLINE_THROW(uint32_t) 2138 iemNativeEmitLoadGprByGprU16SignExtendedFromS8Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase, 2139 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2140 { 2141 #ifdef RT_ARCH_AMD64 2142 /* movsx reg32, mem8 */ 2143 if (iGprDst >= 8 || iGprBase >= 8) 2144 pCodeBuf[off++] = (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2145 pCodeBuf[off++] = 0x0f; 2146 pCodeBuf[off++] = 0xbe; 2147 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprDst, iGprBase, offDisp); 2148 # if 1 /** @todo use 'movzx reg32, reg16' instead of 'and reg32, 0ffffh' ? */ 2149 /* and reg32, 0xffffh */ 2150 if (iGprDst >= 8) 2151 pCodeBuf[off++] = X86_OP_REX_B; 2152 pCodeBuf[off++] = 0x81; 2153 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4, iGprDst & 7); 2154 pCodeBuf[off++] = 0xff; 2155 pCodeBuf[off++] = 0xff; 2156 pCodeBuf[off++] = 0; 2157 pCodeBuf[off++] = 0; 2158 # else 2159 /* movzx reg32, reg16 */ 2160 if (iGprDst >= 8) 2161 pCodeBuf[off++] = X86_OP_REX_B | X86_OP_REX_R; 2162 pCodeBuf[off++] = 0x0f; 2163 pCodeBuf[off++] = 0xb7; 2164 pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGprDst & 7, iGprDst & 7); 2165 # endif 2166 RT_NOREF(iGprTmp); 2167 2168 #elif defined(RT_ARCH_ARM64) 2169 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprDst, iGprBase, offDisp, 2170 kArmv8A64InstrLdStType_Ld_SignByte32, sizeof(uint8_t), iGprTmp); 2171 Assert(Armv8A64ConvertImmRImmS2Mask32(15, 0) == 0xffff); 2172 pCodeBuf[off++] = Armv8A64MkInstrAndImm(iGprDst, iGprDst, 15, 0, false /*64Bit*/); 2173 2174 #else 2175 # error "port me" 2176 #endif 2177 return off; 2178 } 2179 2180 2181 /** 2182 * Emits a 64-bit GPR store via a GPR base address with a displacement. 2183 * 2184 * @note ARM64: Misaligned @a offDisp values and values not in the 2185 * 0x7ff8...0x7ff8 range will require a temporary register (@a iGprTmp) if 2186 * @a iGprReg and @a iGprBase are the same. Will assert / throw if caller 2187 * does not heed this. 2188 */ 2189 DECL_FORCE_INLINE_THROW(uint32_t) 2190 iemNativeEmitStoreGpr64ByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprSrc, uint8_t iGprBase, 2191 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2192 { 2193 #ifdef RT_ARCH_AMD64 2194 /* mov mem64, reg64 */ 2195 pCodeBuf[off++] = X86_OP_REX_W | (iGprSrc < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2196 pCodeBuf[off++] = 0x89; 2197 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprSrc, iGprBase, offDisp); 2198 RT_NOREF(iGprTmp); 2199 2200 #elif defined(RT_ARCH_ARM64) 2201 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprSrc, iGprBase, offDisp, 2202 kArmv8A64InstrLdStType_St_Dword, sizeof(uint64_t), iGprTmp); 2203 2204 #else 2205 # error "port me" 2206 #endif 2207 return off; 2208 } 2209 2210 2211 /** 2212 * Emits a 32-bit GPR store via a GPR base address with a displacement. 2213 * 2214 * @note ARM64: Misaligned @a offDisp values and values not in the 2215 * 0x3ffc...0x3ffc range will require a temporary register (@a iGprTmp) if 2216 * @a iGprReg and @a iGprBase are the same. Will assert / throw if caller 2217 * does not heed this. 2218 */ 2219 DECL_FORCE_INLINE_THROW(uint32_t) 2220 iemNativeEmitStoreGpr32ByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprSrc, uint8_t iGprBase, 2221 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2222 { 2223 #ifdef RT_ARCH_AMD64 2224 /* mov mem32, reg32 */ 2225 if (iGprSrc >= 8 || iGprBase >= 8) 2226 pCodeBuf[off++] = (iGprSrc < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2227 pCodeBuf[off++] = 0x89; 2228 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprSrc, iGprBase, offDisp); 2229 RT_NOREF(iGprTmp); 2230 2231 #elif defined(RT_ARCH_ARM64) 2232 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprSrc, iGprBase, offDisp, 2233 kArmv8A64InstrLdStType_St_Word, sizeof(uint32_t), iGprTmp); 2234 2235 #else 2236 # error "port me" 2237 #endif 2238 return off; 2239 } 2240 2241 2242 /** 2243 * Emits a 16-bit GPR store via a GPR base address with a displacement. 2244 * 2245 * @note ARM64: Misaligned @a offDisp values and values not in the 2246 * 0x1ffe...0x1ffe range will require a temporary register (@a iGprTmp) if 2247 * @a iGprReg and @a iGprBase are the same. Will assert / throw if caller 2248 * does not heed this. 2249 */ 2250 DECL_FORCE_INLINE_THROW(uint32_t) 2251 iemNativeEmitStoreGpr16ByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprSrc, uint8_t iGprBase, 2252 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2253 { 2254 #ifdef RT_ARCH_AMD64 2255 /* mov mem16, reg16 */ 2256 pCodeBuf[off++] = X86_OP_PRF_SIZE_OP; 2257 if (iGprSrc >= 8 || iGprBase >= 8) 2258 pCodeBuf[off++] = (iGprSrc < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2259 pCodeBuf[off++] = 0x89; 2260 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprSrc, iGprBase, offDisp); 2261 RT_NOREF(iGprTmp); 2262 2263 #elif defined(RT_ARCH_ARM64) 2264 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprSrc, iGprBase, offDisp, 2265 kArmv8A64InstrLdStType_St_Half, sizeof(uint16_t), iGprTmp); 2266 2267 #else 2268 # error "port me" 2269 #endif 2270 return off; 2271 } 2272 2273 2274 /** 2275 * Emits a 8-bit GPR store via a GPR base address with a displacement. 2276 * 2277 * @note ARM64: @a offDisp values not in the 0xfff...0xfff range will require a 2278 * temporary register (@a iGprTmp) if @a iGprReg and @a iGprBase are the 2279 * same. Will assert / throw if caller does not heed this. 2280 */ 2281 DECL_FORCE_INLINE_THROW(uint32_t) 2282 iemNativeEmitStoreGpr8ByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprSrc, uint8_t iGprBase, 2283 int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2284 { 2285 #ifdef RT_ARCH_AMD64 2286 /* mov mem8, reg8 */ 2287 if (iGprSrc >= 8 || iGprBase >= 8) 2288 pCodeBuf[off++] = (iGprSrc < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2289 else if (iGprSrc >= 4) 2290 pCodeBuf[off++] = X86_OP_REX; 2291 pCodeBuf[off++] = 0x88; 2292 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iGprSrc, iGprBase, offDisp); 2293 RT_NOREF(iGprTmp); 2294 2295 #elif defined(RT_ARCH_ARM64) 2296 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprSrc, iGprBase, offDisp, 2297 kArmv8A64InstrLdStType_St_Byte, sizeof(uint8_t), iGprTmp); 2298 2299 #else 2300 # error "port me" 2301 #endif 2302 return off; 2303 } 2304 2305 2306 /** 2307 * Emits a 64-bit immediate store via a GPR base address with a displacement. 2308 * 2309 * @note This will always require @a iGprTmpImm on ARM (except for uImm=0), on 2310 * AMD64 it depends on the immediate value. 2311 * 2312 * @note ARM64: Misaligned @a offDisp values and values not in the 2313 * 0x7ff8...0x7ff8 range will require a temporary register (@a iGprTmp) if 2314 * @a iGprReg and @a iGprBase are the same. Will assert / throw if caller 2315 * does not heed this. 2316 */ 2317 DECL_FORCE_INLINE_THROW(uint32_t) 2318 iemNativeEmitStoreImm64ByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint64_t uImm, uint8_t iGprBase, 2319 uint8_t iGprImmTmp = UINT8_MAX, int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2320 { 2321 #ifdef RT_ARCH_AMD64 2322 if ((int32_t)uImm == (int64_t)uImm) 2323 { 2324 /* mov mem64, imm32 (sign-extended) */ 2325 pCodeBuf[off++] = X86_OP_REX_W | (iGprBase < 8 ? 0 : X86_OP_REX_B); 2326 pCodeBuf[off++] = 0xc7; 2327 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, 0, iGprBase, offDisp); 2328 pCodeBuf[off++] = RT_BYTE1(uImm); 2329 pCodeBuf[off++] = RT_BYTE2(uImm); 2330 pCodeBuf[off++] = RT_BYTE3(uImm); 2331 pCodeBuf[off++] = RT_BYTE4(uImm); 2332 } 2333 else if (iGprImmTmp != UINT8_MAX || iGprTmp != UINT8_MAX) 2334 { 2335 /* require temporary register. */ 2336 if (iGprImmTmp == UINT8_MAX) 2337 iGprImmTmp = iGprTmp; 2338 off = iemNativeEmitLoadGprImmEx(pCodeBuf, off, iGprImmTmp, uImm); 2339 off = iemNativeEmitStoreGpr64ByGprEx(pCodeBuf, off, iGprImmTmp, iGprBase, offDisp); 2340 } 2341 else 2342 # ifdef IEM_WITH_THROW_CATCH 2343 AssertFailedStmt(IEMNATIVE_DO_LONGJMP(NULL, VERR_IEM_IPE_9)); 2344 # else 2345 AssertReleaseFailedStmt(off = UINT32_MAX); 2346 # endif 2347 2348 #elif defined(RT_ARCH_ARM64) 2349 if (uImm == 0) 2350 iGprImmTmp = ARMV8_A64_REG_XZR; 2351 else 2352 { 2353 Assert(iGprImmTmp < 31); 2354 off = iemNativeEmitLoadGprImmEx(pCodeBuf, off, iGprImmTmp, uImm); 2355 } 2356 off = iemNativeEmitStoreGpr64ByGprEx(pCodeBuf, off, iGprImmTmp, iGprBase, offDisp, iGprTmp); 2357 2358 #else 2359 # error "port me" 2360 #endif 2361 return off; 2362 } 2363 2364 2365 /** 2366 * Emits a 32-bit GPR store via a GPR base address with a displacement. 2367 * 2368 * @note This will always require @a iGprTmpImm on ARM64 (except for uImm=0). 2369 * 2370 * @note ARM64: Misaligned @a offDisp values and values not in the 2371 * 0x3ffc...0x3ffc range will require a temporary register (@a iGprTmp) if 2372 * @a iGprReg and @a iGprBase are the same. Will assert / throw if caller 2373 * does not heed this. 2374 */ 2375 DECL_FORCE_INLINE_THROW(uint32_t) 2376 iemNativeEmitStoreImm32ByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint32_t uImm, uint8_t iGprBase, 2377 uint8_t iGprImmTmp = UINT8_MAX, int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2378 { 2379 #ifdef RT_ARCH_AMD64 2380 /* mov mem32, imm32 */ 2381 if (iGprBase >= 8) 2382 pCodeBuf[off++] = X86_OP_REX_B; 2383 pCodeBuf[off++] = 0xc7; 2384 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, 0, iGprBase, offDisp); 2385 pCodeBuf[off++] = RT_BYTE1(uImm); 2386 pCodeBuf[off++] = RT_BYTE2(uImm); 2387 pCodeBuf[off++] = RT_BYTE3(uImm); 2388 pCodeBuf[off++] = RT_BYTE4(uImm); 2389 RT_NOREF(iGprImmTmp, iGprTmp); 2390 2391 #elif defined(RT_ARCH_ARM64) 2392 Assert(iGprImmTmp < 31); 2393 if (uImm == 0) 2394 iGprImmTmp = ARMV8_A64_REG_XZR; 2395 else 2396 { 2397 Assert(iGprImmTmp < 31); 2398 off = iemNativeEmitLoadGpr32ImmEx(pCodeBuf, off, iGprImmTmp, uImm); 2399 } 2400 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprImmTmp, iGprBase, offDisp, 2401 kArmv8A64InstrLdStType_St_Word, sizeof(uint32_t), iGprTmp); 2402 2403 #else 2404 # error "port me" 2405 #endif 2406 return off; 2407 } 2408 2409 2410 /** 2411 * Emits a 16-bit GPR store via a GPR base address with a displacement. 2412 * 2413 * @note This will always require @a iGprTmpImm on ARM64 (except for uImm=0). 2414 * 2415 * @note ARM64: Misaligned @a offDisp values and values not in the 2416 * 0x1ffe...0x1ffe range will require a temporary register (@a iGprTmp) if 2417 * @a iGprReg and @a iGprBase are the same. Will assert / throw if caller 2418 * does not heed this. 2419 */ 2420 DECL_FORCE_INLINE_THROW(uint32_t) 2421 iemNativeEmitStoreImm16ByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint16_t uImm, uint8_t iGprBase, 2422 uint8_t iGprImmTmp = UINT8_MAX, int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2423 { 2424 #ifdef RT_ARCH_AMD64 2425 /* mov mem16, imm16 */ 2426 pCodeBuf[off++] = X86_OP_PRF_SIZE_OP; 2427 if (iGprBase >= 8) 2428 pCodeBuf[off++] = X86_OP_REX_B; 2429 pCodeBuf[off++] = 0xc7; 2430 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, 0, iGprBase, offDisp); 2431 pCodeBuf[off++] = RT_BYTE1(uImm); 2432 pCodeBuf[off++] = RT_BYTE2(uImm); 2433 RT_NOREF(iGprImmTmp, iGprTmp); 2434 2435 #elif defined(RT_ARCH_ARM64) 2436 if (uImm == 0) 2437 iGprImmTmp = ARMV8_A64_REG_XZR; 2438 else 2439 { 2440 Assert(iGprImmTmp < 31); 2441 pCodeBuf[off++] = Armv8A64MkInstrMovZ(iGprImmTmp, uImm); 2442 } 2443 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprImmTmp, iGprBase, offDisp, 2444 kArmv8A64InstrLdStType_St_Half, sizeof(uint16_t), iGprTmp); 2445 2446 #else 2447 # error "port me" 2448 #endif 2449 return off; 2450 } 2451 2452 2453 /** 2454 * Emits a 8-bit GPR store via a GPR base address with a displacement. 2455 * 2456 * @note This will always require @a iGprTmpImm on ARM64 (except for uImm=0). 2457 * 2458 * @note ARM64: @a offDisp values not in the 0xfff...0xfff range will require a 2459 * temporary register (@a iGprTmp) if @a iGprReg and @a iGprBase are the 2460 * same. Will assert / throw if caller does not heed this. 2461 */ 2462 DECL_FORCE_INLINE_THROW(uint32_t) 2463 iemNativeEmitStoreImm8ByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t uImm, uint8_t iGprBase, 2464 uint8_t iGprImmTmp = UINT8_MAX, int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX) 2465 { 2466 #ifdef RT_ARCH_AMD64 2467 /* mov mem8, imm8 */ 2468 pCodeBuf[off++] = X86_OP_PRF_SIZE_OP; 2469 if (iGprBase >= 8) 2470 pCodeBuf[off++] = X86_OP_REX_B; 2471 pCodeBuf[off++] = 0xc6; 2472 off = iemNativeEmitGprByGprDisp(pCodeBuf, off, 0, iGprBase, offDisp); 2473 pCodeBuf[off++] = uImm; 2474 RT_NOREF(iGprImmTmp, iGprTmp); 2475 2476 #elif defined(RT_ARCH_ARM64) 2477 if (uImm == 0) 2478 iGprImmTmp = ARMV8_A64_REG_XZR; 2479 else 2480 { 2481 Assert(iGprImmTmp < 31); 2482 pCodeBuf[off++] = Armv8A64MkInstrMovZ(iGprImmTmp, uImm); 2483 } 2484 off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iGprImmTmp, iGprBase, offDisp, 2485 kArmv8A64InstrLdStType_St_Byte, sizeof(uint8_t), iGprTmp); 2486 2487 #else 2488 # error "port me" 2489 #endif 2490 return off; 2491 } 2492 1867 2493 1868 2494
Note:
See TracChangeset
for help on using the changeset viewer.