VirtualBox

Changeset 102756 in vbox for trunk/src


Ignore:
Timestamp:
Jan 3, 2024 7:45:42 PM (13 months ago)
Author:
vboxsync
Message:

VMM/IEM: Rough TLB lookup code for fetches and stores. bugref:10371

Location:
trunk/src/VBox/VMM
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompBltIn.cpp

    r102755 r102756  
    242242    iemNativeFixupFixedJump(pReNative, offFixupJumpToVmCheck1, off);
    243243    off = iemNativeEmitLoadGprFromVCpuU64(pReNative, off, idxTmpReg, RT_UOFFSETOF(VMCPUCC, CTX_SUFF(pVM))); /* idxTmpReg = pVM */
    244     off = iemNativeEmitLoadGpr32ByGpr(pReNative, off, idxTmpReg, idxTmpReg, RT_UOFFSETOF(VMCC, fGlobalForcedActions));
     244    off = iemNativeEmitLoadGprByGprU32(pReNative, off, idxTmpReg, idxTmpReg, RT_UOFFSETOF(VMCC, fGlobalForcedActions));
    245245    off = iemNativeEmitAndGpr32ByImm(pReNative, off, idxTmpReg, VM_FF_ALL_MASK, true /*fSetFlags*/);
    246246    off = iemNativeEmitJnzToLabel(pReNative, off, idxLabelReturnBreak);
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp

    r102742 r102756  
    1002110021
    1002210022    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)
    1002410024#ifdef IEMNATIVE_WITH_TLB_LOOKUP
    1002510025        /* 32-bit and 64-bit wraparound will require special handling, so skip these for absolute addresses. */
    1002610026        :           fSkip(   a_pReNative->Core.aVars[a_idxVarGCPtrMem].enmKind == kIemNativeVarKind_Immediate
    1002710027                          &&   (  (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))
    1003010030                             < a_pReNative->Core.aVars[a_idxVarGCPtrMem].u.uValue)
    1003110031#else
     
    1004710047                          ? UINT8_MAX
    1004810048                          : 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) || fSkip
     10049        ,  idxRegSegLimit((a_iSegReg == UINT8_MAX || (a_pReNative->fExec & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_64BIT) || fSkip
    1005010050                          ? UINT8_MAX
    1005110051                          : 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) || fSkip
     10052        , idxRegSegAttrib((a_iSegReg == UINT8_MAX || (a_pReNative->fExec & IEM_F_MODE_CPUMODE_MASK) == IEMMODE_64BIT) || fSkip
    1005310053                          ? UINT8_MAX
    1005410054                          : iemNativeRegAllocTmpForGuestReg(a_pReNative, a_poff, IEMNATIVEGSTREG_SEG_ATTRIB(a_iSegReg)))
     
    1017810178                       uint8_t offDisp = 0)
    1017910179{
    10180     RT_NOREF(offDisp);
    1018110180    Assert(!pTlbState->fSkip);
    1018210181# if defined(RT_ARCH_AMD64)
     
    1019610195    {
    1019710196off = 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);
    1020110205        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        }
    1020310210        /* ja  tlbmiss */
    1020410211        off = iemNativeEmitJccToLabelEx(pReNative, pCodeBuf, off, idxLabelTlbMiss, kIemNativeInstrCond_nbe);
     10212
    1020510213        /* reg1 = segattr & X86DESCATTR_D (0x4000) */
    1020610214        off = iemNativeEmitGpr32EqGprAndImmEx(pCodeBuf, off, pTlbState->idxReg1, pTlbState->idxRegSegAttrib, X86DESCATTR_D);
     
    1021510223        if (pTlbState->idxRegPtr != UINT8_MAX)
    1021610224            off = iemNativeEmitCmpGprWithGprEx(pCodeBuf, off, pTlbState->idxReg1,
    10217                                                cbMem > 1 ? pTlbState->idxReg2 : pTlbState->idxRegPtr);
     10225                                               cbMem > 1 || offDisp != 0 ? pTlbState->idxReg2 : pTlbState->idxRegPtr);
    1021810226        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. */
    1022010229        /* jbe  tlbmiss */
    1022110230        off = iemNativeEmitJccToLabelEx(pReNative, pCodeBuf, off, idxLabelTlbMiss, kIemNativeInstrCond_be);
     
    1024010249    if (iSegReg != UINT8_MAX && (pReNative->fExec & IEM_F_MODE_CPUMODE_MASK) != IEMMODE_64BIT)
    1024110250    {
    10242         /* If we're accessing more than one byte, put the last address we'll be
    10243            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 
    1025010251        /* Check that we've got a segment loaded and that it allows the access.
    1025110252           For write access this means a writable data segment.
     
    1029610297        }
    1029710298
     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
    1029810315        /*
    1029910316         * Check the limit.  If this is a write access, we know that it's a
     
    1032310340           cmp  seglim, regptr/reg2/imm */
    1032410341        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);
    1032610344        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. */
    1032810347        /* jbe  tlbmiss */
    1032910348        off = iemNativeEmitJccToLabelEx(pReNative, pCodeBuf, off, idxLabelTlbMiss, kIemNativeInstrCond_be);
     
    1033310352    }
    1033410353
    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
    1033810358                                ? idxRegMemResult : pTlbState->idxRegPtr;
    1033910359    if (iSegReg != UINT8_MAX)
    1034010360    {
     10361        Assert(idxRegFlatPtr != pTlbState->idxRegPtr);
    1034110362        /* regflat = segbase + regptr/imm */
    1034210363        if ((pReNative->fExec & IEM_F_MODE_MASK) == IEM_F_MODE_X86_64BIT)
     
    1034410365            Assert(iSegReg >= X86_SREG_FS);
    1034510366            if (pTlbState->idxRegPtr != UINT8_MAX)
     10367            {
    1034610368                off = iemNativeEmitGprEqGprPlusGprEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->idxRegSegBase, pTlbState->idxRegPtr);
     10369                if (offDisp != 0)
     10370                    off = iemNativeEmitAddGprImmEx(pCodeBuf, off, idxRegFlatPtr, offDisp);
     10371            }
    1034710372            else
    10348                 off = iemNativeEmitGprEqGprPlusImmEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->idxRegSegBase, pTlbState->uAbsPtr);
     10373                off = iemNativeEmitGprEqGprPlusImmEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->idxRegSegBase,
     10374                                                     pTlbState->uAbsPtr + offDisp);
    1034910375        }
    1035010376        else if (pTlbState->idxRegPtr != UINT8_MAX)
     10377        {
    1035110378            off = iemNativeEmitGpr32EqGprPlusGprEx(pCodeBuf, off, idxRegFlatPtr, pTlbState->idxRegSegBase, pTlbState->idxRegPtr);
     10379            if (offDisp != 0)
     10380                off = iemNativeEmitAddGpr32ImmEx(pCodeBuf, off, idxRegFlatPtr, offDisp);
     10381        }
    1035210382        else
    1035310383            off = iemNativeEmitGpr32EqGprPlusImmEx(pCodeBuf, off, idxRegFlatPtr,
    10354                                                    pTlbState->idxRegSegBase, (uint32_t)pTlbState->uAbsPtr);
     10384                                                   pTlbState->idxRegSegBase, (uint32_t)pTlbState->uAbsPtr + offDisp);
    1035510385    }
    1035610386    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);
    1035810403
    1035910404    /*
     
    1049110536    off = iemNativeEmitGprByGprDisp(pCodeBuf, off, pTlbState->idxReg1, pTlbState->idxReg2, RT_UOFFSETOF(IEMTLBENTRY, uTag));
    1049210537# elif defined(RT_ARCH_ARM64)
    10493     off = iemNativeEmitLoadGprByGprEx(pCodeBuf, off, pTlbState->idxReg3, pTlbState->idxReg2, RT_UOFFSETOF(IEMTLBENTRY, uTag));
     10538    off = iemNativeEmitLoadGprByGprU64Ex(pCodeBuf, off, pTlbState->idxReg3, pTlbState->idxReg2, RT_UOFFSETOF(IEMTLBENTRY, uTag));
    1049410539    off = iemNativeEmitCmpGprWithGprEx(pCodeBuf, off, pTlbState->idxReg1, pTlbState->idxReg3);
    1049510540# else
     
    1052510570                                    RT_UOFFSETOF(VMCPUCC, iem.s.DataTlb.uTlbPhysRev));
    1052610571# elif defined(RT_ARCH_ARM64)
    10527     off = iemNativeEmitLoadGprByGprEx(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));
    1052910574    pCodeBuf[off++] = Armv8A64MkInstrAnd(pTlbState->idxReg1, pTlbState->idxReg1, pTlbState->idxReg3);
    1053010575    off = iemNativeEmitLoadGprFromVCpuU64Ex(pCodeBuf, off, pTlbState->idxReg3, RT_UOFFSETOF(VMCPUCC, iem.s.DataTlb.uTlbPhysRev));
     
    1054110586     */
    1054210587    /* mov  reg1, [reg2->pbMappingR3] */
    10543     off = iemNativeEmitLoadGprByGprEx(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));
    1054510590    /* if (!reg1) goto tlbmiss; */
    1054610591    /** @todo eliminate the need for this test? */
     
    1077310818     * register if we can).
    1077410819     */
    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     *
    1079110845     * Call helper to do the fetching.
    1079210846     * We flush all guest register shadow copies here.
    1079310847     */
    10794     iemNativeLabelDefine(pReNative, idxLabelTlbMiss, off);
     10848    uint32_t const idxLabelTlbMiss = iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbMiss, off, uTlbSeqNo);
    1079510849
    1079610850#ifdef IEMNATIVE_WITH_INSTRUCTION_COUNTING
     
    1080010854#endif
    1080110855
    10802     uint8_t idxRegArgValue;
    10803     if (iSegReg == UINT8_MAX)
    10804         idxRegArgValue = IEMNATIVE_CALL_ARG2_GREG;
    10805     else
    10806     {
    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 
    1081410856    /* IEMNATIVE_CALL_ARG2/3_GREG = uValue (idxVarValue) - if store */
    1081510857    if (enmOp == kIemNativeEmitMemOp_Store)
    1081610858    {
     10859        uint8_t const idxRegArgValue = iSegReg == UINT8_MAX ? IEMNATIVE_CALL_ARG2_GREG : IEMNATIVE_CALL_ARG3_GREG;
    1081710860        if (pReNative->Core.aVars[idxVarValue].enmKind == kIemNativeVarKind_Immediate)
    1081810861            off = iemNativeEmitLoadGprImm64(pReNative, off, idxRegArgValue, pReNative->Core.aVars[idxVarValue].u.uValue);
     
    1086010903    }
    1086110904
     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
    1086210912    /* IEMNATIVE_CALL_ARG0_GREG = pVCpu */
    1086310913    off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_CALL_ARG0_GREG, IEMNATIVE_REG_FIXED_PVMCPU);
     
    1087410924        if (idxRegValueFetch != IEMNATIVE_CALL_RET_GREG)
    1087510925            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)
    1087611074        iemNativeVarRegisterRelease(pReNative, idxVarValue);
    10877     }
    10878 
    10879     iemNativeLabelDefine(pReNative, idxLabelTlbDone, off);
    10880 
    1088111075    return off;
    1088211076}
     
    1178211976    /*
    1178311977     * 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);
    1179111984    IEMNATIVEEMITTLBSTATE const TlbState(pReNative, &off, idxVarGCPtrMem, iSegReg, cbMem);
    11792 
    1179311985    uint32_t const idxLabelTlbLookup = !TlbState.fSkip
    1179411986                                     ? iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbLookup, UINT32_MAX, uTlbSeqNo)
     
    1180211994
    1180311995    /*
    11804      * tlbmiss:
     11996     * TlbMiss:
    1180511997     *
    1180611998     * Call helper to do the fetching.
     
    1187012062
    1187112063        /*
    11872          * tlblookup:
     12064         * TlbLookup:
    1187312065         */
    1187412066        off = iemNativeEmitTlbLookup(pReNative, off, &TlbState, iSegReg, cbMem, fAlignMask, fAccess,
    1187512067                                     idxLabelTlbLookup, idxLabelTlbMiss, idxRegMemResult);
    1187612068
     12069        /* [idxVarUnmapInfo] = 0; */
     12070        off = iemNativeEmitLoadGprImm32(pReNative, off, idxRegUnmapInfo, 0);
     12071
    1187712072        /*
    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:
    1188512074         */
    1188612075        iemNativeLabelDefine(pReNative, idxLabelTlbDone, off);
  • trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h

    r102741 r102756  
    18001800 */
    18011801DECL_FORCE_INLINE_THROW(uint32_t)
    1802 iemNativeEmitLoadGprByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase,
    1803                             int32_t offDisp, uint8_t iGprTmp = UINT8_MAX)
     1802iemNativeEmitLoadGprByGprU64Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprBase,
     1803                               int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX)
    18041804{
    18051805#ifdef RT_ARCH_AMD64
     
    18251825 */
    18261826DECL_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 = iemNativeEmitLoadGprByGprEx(iemNativeInstrBufEnsure(pReNative, off, 8), off, iGprDst, iGprBase, offDisp);
     1827iemNativeEmitLoadGprByGprU64(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);
    18311831    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    18321832
    18331833#elif defined(RT_ARCH_ARM64)
    18341834    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 */
     1853DECL_FORCE_INLINE_THROW(uint32_t)
     1854iemNativeEmitLoadGprByGprU32Ex(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);
    18351868
    18361869#else
     
    18461879 */
    18471880DECL_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);
     1881iemNativeEmitLoadGprByGprU32(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 */
     1906DECL_FORCE_INLINE_THROW(uint32_t)
     1907iemNativeEmitLoadGprByGprU64SignExtendedFromS32Ex(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 */
     1938DECL_FORCE_INLINE_THROW(uint32_t)
     1939iemNativeEmitLoadGprByGprU16Ex(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 */
    18531944    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 */
     1971DECL_FORCE_INLINE_THROW(uint32_t)
     1972iemNativeEmitLoadGprByGprU64SignExtendedFromS16Ex(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 */
     2005DECL_FORCE_INLINE_THROW(uint32_t)
     2006iemNativeEmitLoadGprByGprU32SignExtendedFromS16Ex(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 */
     2038DECL_FORCE_INLINE_THROW(uint32_t)
     2039iemNativeEmitLoadGprByGprU8Ex(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 */
     2070DECL_FORCE_INLINE_THROW(uint32_t)
     2071iemNativeEmitLoadGprByGprU64SignExtendedFromS8Ex(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 */
     2103DECL_FORCE_INLINE_THROW(uint32_t)
     2104iemNativeEmitLoadGprByGprU32SignExtendedFromS8Ex(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 */
     2137DECL_FORCE_INLINE_THROW(uint32_t)
     2138iemNativeEmitLoadGprByGprU16SignExtendedFromS8Ex(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 */
     2189DECL_FORCE_INLINE_THROW(uint32_t)
     2190iemNativeEmitStoreGpr64ByGprEx(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 */
     2219DECL_FORCE_INLINE_THROW(uint32_t)
     2220iemNativeEmitStoreGpr32ByGprEx(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 */
     2250DECL_FORCE_INLINE_THROW(uint32_t)
     2251iemNativeEmitStoreGpr16ByGprEx(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 */
     2281DECL_FORCE_INLINE_THROW(uint32_t)
     2282iemNativeEmitStoreGpr8ByGprEx(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 */
     2317DECL_FORCE_INLINE_THROW(uint32_t)
     2318iemNativeEmitStoreImm64ByGprEx(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 */
     2375DECL_FORCE_INLINE_THROW(uint32_t)
     2376iemNativeEmitStoreImm32ByGprEx(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 */
     2420DECL_FORCE_INLINE_THROW(uint32_t)
     2421iemNativeEmitStoreImm16ByGprEx(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 */
     2462DECL_FORCE_INLINE_THROW(uint32_t)
     2463iemNativeEmitStoreImm8ByGprEx(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
    18672493
    18682494
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette