VirtualBox

Changeset 103911 in vbox


Ignore:
Timestamp:
Mar 19, 2024 9:28:05 AM (11 months ago)
Author:
vboxsync
Message:

VMM/IEM: Implement support for fetching 128-bit/256-bit values from guest memory and implement native emitters for IEM_MC_FETCH_MEM_U128_ALIGN_SSE()/IEM_MC_FETCH_MEM_FLAT_U128_ALIGN_SSE()/IEM_MC_FETCH_MEM_U128_NO_AC()/IEM_MC_FETCH_MEM_FLAT_U128_NO_AC(), bugref:10614

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py

    r103909 r103911  
    30563056    'IEM_MC_FETCH_MEM_R80':                                      (McBlock.parseMcGeneric,           True,  True,  False, ),
    30573057    'IEM_MC_FETCH_MEM_U128':                                     (McBlock.parseMcGeneric,           True,  True,  False, ),
    3058     'IEM_MC_FETCH_MEM_U128_ALIGN_SSE':                           (McBlock.parseMcGeneric,           True,  True,  False, ),
    3059     'IEM_MC_FETCH_MEM_U128_NO_AC':                               (McBlock.parseMcGeneric,           True,  True,  False, ),
     3058    'IEM_MC_FETCH_MEM_U128_ALIGN_SSE':                           (McBlock.parseMcGeneric,           True,  True,  g_fNativeSimd),
     3059    'IEM_MC_FETCH_MEM_U128_NO_AC':                               (McBlock.parseMcGeneric,           True,  True,  g_fNativeSimd),
    30603060    'IEM_MC_FETCH_MEM_U128_AND_XREG_U128':                       (McBlock.parseMcGeneric,           True,  True,  False, ),
    30613061    'IEM_MC_FETCH_MEM_U128_AND_XREG_U128_AND_RAX_RDX_U64':       (McBlock.parseMcGeneric,           True,  True,  False, ),
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8vePython.py

    r103859 r103911  
    4444import IEMAllInstPython as iai;
    4545
     46## Temporary flag for enabling / disabling experimental MCs depending on the
     47## SIMD register allocator.
     48g_fNativeSimd = True;
    4649
    4750## Supplememnts g_dMcStmtParsers.
     
    136139    'IEM_MC_FETCH_MEM_FLAT_R64':                                         (None, True,  True,  False, ),
    137140    'IEM_MC_FETCH_MEM_FLAT_R80':                                         (None, True,  True,  False, ),
    138     'IEM_MC_FETCH_MEM_FLAT_U128_ALIGN_SSE':                              (None, True,  True,  False, ),
    139     'IEM_MC_FETCH_MEM_FLAT_U128_NO_AC':                                  (None, True,  True,  False, ),
     141    'IEM_MC_FETCH_MEM_FLAT_U128_ALIGN_SSE':                              (None, True,  True,  g_fNativeSimd),
     142    'IEM_MC_FETCH_MEM_FLAT_U128_NO_AC':                                  (None, True,  True,  g_fNativeSimd),
    140143    'IEM_MC_FETCH_MEM_FLAT_U128':                                        (None, True,  True,  False, ),
    141144    'IEM_MC_FETCH_MEM_FLAT_U16_DISP':                                    (None, True,  True,  True,  ),
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h

    r103894 r103911  
    46554655               IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND));
    46564656    Assert(iSegReg < 6 || iSegReg == UINT8_MAX);
     4657#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     4658    Assert(   cbMem == 1 || cbMem == 2 || cbMem == 4 || cbMem == 8
     4659           || cbMem == sizeof(RTUINT128U) || cbMem == sizeof(RTUINT256U));
     4660#else
    46574661    Assert(cbMem == 1 || cbMem == 2 || cbMem == 4 || cbMem == 8);
     4662#endif
    46584663    AssertCompile(IEMNATIVE_CALL_ARG_GREG_COUNT >= 4);
    46594664#ifdef VBOX_STRICT
     
    47014706                           : UINT64_C(0xc000b000a0009000) ));
    47024707                break;
     4708#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     4709            case sizeof(RTUINT128U):
     4710                Assert(enmOp == kIemNativeEmitMemOp_Store || enmOp == kIemNativeEmitMemOp_Fetch);
     4711                Assert(   (   enmOp == kIemNativeEmitMemOp_Fetch
     4712                           && (   pfnFunction == (uintptr_t)iemNativeHlpMemFlatFetchDataU128AlignedSse
     4713                               || pfnFunction == (uintptr_t)iemNativeHlpMemFlatFetchDataU128NoAc))
     4714                       || (   enmOp == kIemNativeEmitMemOp_Store
     4715                           && (pfnFunction == UINT64_C(0xc000b000a0009000))));
     4716                break;
     4717#endif
    47034718        }
    47044719    }
     
    47444759                           : UINT64_C(0xc000b000a0009000) ));
    47454760                break;
     4761#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     4762            case sizeof(RTUINT128U):
     4763                Assert(enmOp == kIemNativeEmitMemOp_Store || enmOp == kIemNativeEmitMemOp_Fetch);
     4764                Assert(   (   enmOp == kIemNativeEmitMemOp_Fetch
     4765                           && (   pfnFunction == (uintptr_t)iemNativeHlpMemFetchDataU128AlignedSse
     4766                               || pfnFunction == (uintptr_t)iemNativeHlpMemFetchDataU128NoAc))
     4767                       || (   enmOp == kIemNativeEmitMemOp_Store
     4768                           && (pfnFunction == UINT64_C(0xc000b000a0009000))));
     4769                break;
     4770#endif
    47464771        }
    47474772    }
     
    47834808     */
    47844809    uint16_t const uTlbSeqNo         = pReNative->uTlbSeqNo++;
     4810#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     4811    uint8_t  idxRegValueFetch = UINT8_MAX;
     4812
     4813    if (cbMem == sizeof(RTUINT128U) || cbMem == sizeof(RTUINT256U))
     4814        idxRegValueFetch = enmOp == kIemNativeEmitMemOp_Store ? UINT8_MAX
     4815                         : iemNativeVarSimdRegisterAcquire(pReNative, idxVarValue, &off);
     4816    else
     4817        idxRegValueFetch = enmOp == kIemNativeEmitMemOp_Store ? UINT8_MAX
     4818                         : !(pReNative->Core.bmHstRegs & RT_BIT_32(IEMNATIVE_CALL_RET_GREG))
     4819                         ? iemNativeVarRegisterSetAndAcquire(pReNative, idxVarValue, IEMNATIVE_CALL_RET_GREG, &off)
     4820                         : iemNativeVarRegisterAcquire(pReNative, idxVarValue, &off);
     4821#else
    47854822    uint8_t  const idxRegValueFetch  = enmOp == kIemNativeEmitMemOp_Store ? UINT8_MAX
    47864823                                     : !(pReNative->Core.bmHstRegs & RT_BIT_32(IEMNATIVE_CALL_RET_GREG))
    47874824                                     ? iemNativeVarRegisterSetAndAcquire(pReNative, idxVarValue, IEMNATIVE_CALL_RET_GREG, &off)
    47884825                                     : iemNativeVarRegisterAcquire(pReNative, idxVarValue, &off);
     4826#endif
    47894827    IEMNATIVEEMITTLBSTATE const TlbState(pReNative, &off, idxVarGCPtrMem, iSegReg, cbMem, offDisp);
    47904828    uint8_t  const idxRegValueStore  =    !TlbState.fSkip
     
    48494887    /* IEMNATIVE_CALL_ARG2/3_GREG = uValue (idxVarValue) - if store */
    48504888    uint32_t fVolGregMask = IEMNATIVE_CALL_VOLATILE_GREG_MASK;
     4889#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     4890    if (cbMem == sizeof(RTUINT128U) || cbMem == sizeof(RTUINT256U))
     4891    {
     4892        /*
     4893         * For SIMD based variables we pass the reference on the stack for both fetches and stores.
     4894         *
     4895         * @note There was a register variable assigned to the variable for the TlbLookup case above
     4896         *       which must not be freed or the value loaded into the register will not be synced into the register
     4897         *       further down the road because the variable doesn't know it had a variable assigned.
     4898         *
     4899         * @note For loads it is not required to sync what is in the assigned register with the stack slot
     4900         *       as it will be overwritten anyway.
     4901         */
     4902        uint8_t const idxRegArgValue = iSegReg == UINT8_MAX ? IEMNATIVE_CALL_ARG2_GREG : IEMNATIVE_CALL_ARG3_GREG;
     4903        off = iemNativeEmitLoadArgGregWithSimdVarAddrForMemAccess(pReNative, off, idxRegArgValue, idxVarValue,
     4904                                                                  enmOp == kIemNativeEmitMemOp_Store /*fSyncRegWithStack*/);
     4905        fVolGregMask &= ~RT_BIT_32(idxRegArgValue);
     4906    }
     4907    else
     4908#endif
    48514909    if (enmOp == kIemNativeEmitMemOp_Store)
    48524910    {
     
    48874945    if (enmOp != kIemNativeEmitMemOp_Store)
    48884946    {
    4889         Assert(idxRegValueFetch == pVarValue->idxReg);
    4890         if (idxRegValueFetch != IEMNATIVE_CALL_RET_GREG)
    4891             off = iemNativeEmitLoadGprFromGpr(pReNative, off, idxRegValueFetch, IEMNATIVE_CALL_RET_GREG);
     4947#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     4948        if (   cbMem == sizeof(RTUINT128U)
     4949            || cbMem == sizeof(RTUINT256U))
     4950        {
     4951            Assert(enmOp == kIemNativeEmitMemOp_Fetch);
     4952
     4953            /* Sync the value on the stack with the host register assigned to the variable. */
     4954            off = iemNativeEmitSimdVarSyncStackToRegister(pReNative, off, idxVarValue);
     4955        }
     4956        else
     4957#endif
     4958        {
     4959            Assert(idxRegValueFetch == pVarValue->idxReg);
     4960            if (idxRegValueFetch != IEMNATIVE_CALL_RET_GREG)
     4961                off = iemNativeEmitLoadGprFromGpr(pReNative, off, idxRegValueFetch, IEMNATIVE_CALL_RET_GREG);
     4962        }
    48924963    }
    48934964
     
    50085079                        off = iemNativeEmitLoadGprByGprU64Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult);
    50095080                        break;
     5081                    case sizeof(RTUINT128U):
     5082                        /*
     5083                         * No need to back the register with the stack, this is done by the generic variable handling
     5084                         * code if there is a register assigned to a variable and the stack must be accessed.
     5085                         */
     5086                        off = iemNativeEmitLoadVecRegByGprU128Ex(pCodeBuf, off, idxRegValueFetch, idxRegMemResult);
     5087                        break;
    50105088                    default:
    50115089                        AssertFailed();
     
    52695347                                               (uintptr_t)iemNativeHlpMemFlatFetchDataU64, pCallEntry->idxInstr)
    52705348
     5349#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     5350/* 128-bit segmented: */
     5351#define IEM_MC_FETCH_MEM_U128_ALIGN_SSE(a_u128Dst, a_iSeg, a_GCPtrMem) \
     5352    off = iemNativeEmitMemFetchStoreDataCommon(pReNative, off, a_u128Dst, a_iSeg, a_GCPtrMem, \
     5353                                               sizeof(RTUINT128U), sizeof(RTUINT128U) - 1, kIemNativeEmitMemOp_Fetch, \
     5354                                               (uintptr_t)iemNativeHlpMemFetchDataU128AlignedSse, pCallEntry->idxInstr)
     5355
     5356/* 128-bit flat: */
     5357#define IEM_MC_FETCH_MEM_FLAT_U128_ALIGN_SSE(a_u128Dst, a_GCPtrMem) \
     5358    off = iemNativeEmitMemFetchStoreDataCommon(pReNative, off, a_u128Dst, UINT8_MAX, a_GCPtrMem, \
     5359                                               sizeof(RTUINT128U), sizeof(RTUINT128U) - 1, kIemNativeEmitMemOp_Fetch, \
     5360                                               (uintptr_t)iemNativeHlpMemFlatFetchDataU128AlignedSse, pCallEntry->idxInstr)
     5361
     5362/* 128-bit segmented: */
     5363#define IEM_MC_FETCH_MEM_U128_NO_AC(a_u128Dst, a_iSeg, a_GCPtrMem) \
     5364    off = iemNativeEmitMemFetchStoreDataCommon(pReNative, off, a_u128Dst, a_iSeg, a_GCPtrMem, \
     5365                                               sizeof(RTUINT128U), sizeof(RTUINT128U) - 1, kIemNativeEmitMemOp_Fetch, \
     5366                                               (uintptr_t)iemNativeHlpMemFetchDataU128NoAc, pCallEntry->idxInstr)
     5367
     5368/* 128-bit flat: */
     5369#define IEM_MC_FETCH_MEM_FLAT_U128_NO_AC(a_u128Dst, a_GCPtrMem) \
     5370    off = iemNativeEmitMemFetchStoreDataCommon(pReNative, off, a_u128Dst, UINT8_MAX, a_GCPtrMem, \
     5371                                               sizeof(RTUINT128U), sizeof(RTUINT128U) - 1, kIemNativeEmitMemOp_Fetch, \
     5372                                               (uintptr_t)iemNativeHlpMemFlatFetchDataU128NoAc, pCallEntry->idxInstr)
     5373#endif
    52715374
    52725375
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp

    r103907 r103911  
    18711871
    18721872
     1873#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     1874/**
     1875 * Used by TB code to load 128-bit data w/ segmentation.
     1876 */
     1877IEM_DECL_NATIVE_HLP_DEF(void, iemNativeHlpMemFetchDataU128AlignedSse,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint8_t iSegReg, PRTUINT128U pu128Dst))
     1878{
     1879#ifdef IEMNATIVE_WITH_TLB_LOOKUP_FETCH
     1880    iemMemFetchDataU128AlignedSseSafeJmp(pVCpu, pu128Dst, iSegReg, GCPtrMem);
     1881#else
     1882    iemMemFetchDataU128AlignedSseJmp(pVCpu, pu128Dst, iSegReg, GCPtrMem);
     1883#endif
     1884}
     1885
     1886
     1887/**
     1888 * Used by TB code to load 128-bit data w/ segmentation.
     1889 */
     1890IEM_DECL_NATIVE_HLP_DEF(void, iemNativeHlpMemFetchDataU128NoAc,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint8_t iSegReg, PRTUINT128U pu128Dst))
     1891{
     1892#ifdef IEMNATIVE_WITH_TLB_LOOKUP_FETCH
     1893    iemMemFetchDataU128NoAcSafeJmp(pVCpu, pu128Dst, iSegReg, GCPtrMem);
     1894#else
     1895    iemMemFetchDataU128NoAcJmp(pVCpu, pu128Dst, iSegReg, GCPtrMem);
     1896#endif
     1897}
     1898#endif
     1899
     1900
    18731901/**
    18741902 * Used by TB code to store unsigned 8-bit data w/ segmentation.
     
    21642192#endif
    21652193}
     2194
     2195
     2196#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     2197/**
     2198 * Used by TB code to load unsigned 128-bit data w/ flat address.
     2199 */
     2200IEM_DECL_NATIVE_HLP_DEF(void, iemNativeHlpMemFlatFetchDataU128AlignedSse,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, PRTUINT128U pu128Dst))
     2201{
     2202#ifdef IEMNATIVE_WITH_TLB_LOOKUP_FETCH
     2203    return iemMemFetchDataU128AlignedSseSafeJmp(pVCpu, pu128Dst, UINT8_MAX, GCPtrMem);
     2204#else
     2205    return iemMemFlatFetchDataU128AlignedSseJmp(pVCpu, pu128Dst, UINT8_MAX, GCPtrMem);
     2206#endif
     2207}
     2208
     2209
     2210/**
     2211 * Used by TB code to load unsigned 128-bit data w/ flat address.
     2212 */
     2213IEM_DECL_NATIVE_HLP_DEF(void, iemNativeHlpMemFlatFetchDataU128NoAc,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, PRTUINT128U pu128Dst))
     2214{
     2215#ifdef IEMNATIVE_WITH_TLB_LOOKUP_FETCH
     2216    return iemMemFetchDataU128NoAcSafeJmp(pVCpu, pu128Dst, UINT8_MAX, GCPtrMem);
     2217#else
     2218    return iemMemFlatFetchDataU128NoAcJmp(pVCpu, pu128Dst, UINT8_MAX, GCPtrMem);
     2219#endif
     2220}
     2221#endif
    21662222
    21672223
  • trunk/src/VBox/VMM/include/IEMN8veRecompiler.h

    r103895 r103911  
    16451645IEM_DECL_NATIVE_HLP_PROTO(uint64_t, iemNativeHlpMemFetchDataU32_Sx_U64,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint8_t iSegReg));
    16461646IEM_DECL_NATIVE_HLP_PROTO(uint64_t, iemNativeHlpMemFetchDataU64,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint8_t iSegReg));
     1647#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     1648IEM_DECL_NATIVE_HLP_PROTO(void,     iemNativeHlpMemFetchDataU128AlignedSse,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint8_t iSegReg, PRTUINT128U pu128Dst));
     1649IEM_DECL_NATIVE_HLP_PROTO(void,     iemNativeHlpMemFetchDataU128NoAc,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint8_t iSegReg, PRTUINT128U pu128Dst));
     1650#endif
    16471651IEM_DECL_NATIVE_HLP_PROTO(void,     iemNativeHlpMemStoreDataU8,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint8_t iSegReg, uint8_t u8Value));
    16481652IEM_DECL_NATIVE_HLP_PROTO(void,     iemNativeHlpMemStoreDataU16,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint8_t iSegReg, uint16_t u16Value));
     
    16671671IEM_DECL_NATIVE_HLP_PROTO(uint64_t, iemNativeHlpMemFlatFetchDataU32_Sx_U64,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem));
    16681672IEM_DECL_NATIVE_HLP_PROTO(uint64_t, iemNativeHlpMemFlatFetchDataU64,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem));
     1673#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     1674IEM_DECL_NATIVE_HLP_PROTO(void,     iemNativeHlpMemFlatFetchDataU128AlignedSse,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, PRTUINT128U pu128Dst));
     1675IEM_DECL_NATIVE_HLP_PROTO(void,     iemNativeHlpMemFlatFetchDataU128NoAc,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, PRTUINT128U pu128Dst));
     1676#endif
    16691677IEM_DECL_NATIVE_HLP_PROTO(void,     iemNativeHlpMemFlatStoreDataU8,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint8_t u8Value));
    16701678IEM_DECL_NATIVE_HLP_PROTO(void,     iemNativeHlpMemFlatStoreDataU16,(PVMCPUCC pVCpu, RTGCPTR GCPtrMem, uint16_t u16Value));
  • trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h

    r103894 r103911  
    28542854
    28552855
     2856#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     2857/**
     2858 * Emits a 128-bit vector register load via a GPR base address with a displacement.
     2859 *
     2860 * @note ARM64: Misaligned @a offDisp values and values not in the
     2861 *       -0x7ff8...0x7ff8 range will require a temporary register (@a iGprTmp) if
     2862 *       @a iGprReg and @a iGprBase are the same. Will assert / throw if caller
     2863 *       does not heed this.
     2864 */
     2865DECL_FORCE_INLINE_THROW(uint32_t)
     2866iemNativeEmitLoadVecRegByGprU128Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iVecRegDst, uint8_t iGprBase,
     2867                                   int32_t offDisp = 0, uint8_t iGprTmp = UINT8_MAX)
     2868{
     2869#ifdef RT_ARCH_AMD64
     2870    /* movdqu reg128, mem128 */
     2871    pCodeBuf[off++] = 0xf3;
     2872    if (iVecRegDst >= 8 || iGprBase >= 8)
     2873        pCodeBuf[off++] = (iVecRegDst < 8 ? 0 : X86_OP_REX_R) | (iGprBase < 8 ? 0 : X86_OP_REX_B);
     2874    pCodeBuf[off++] = 0x0f;
     2875    pCodeBuf[off++] = 0x6f;
     2876    off = iemNativeEmitGprByGprDisp(pCodeBuf, off, iVecRegDst, iGprBase, offDisp);
     2877    RT_NOREF(iGprTmp);
     2878
     2879#elif defined(RT_ARCH_ARM64)
     2880    off = iemNativeEmitGprByGprLdStEx(pCodeBuf, off, iVecRegDst, iGprBase, offDisp,
     2881                                      kArmv8A64InstrLdStType_Ld_Vr_128, sizeof(RTUINT128U), iGprTmp);
     2882
     2883#else
     2884# error "port me"
     2885#endif
     2886    return off;
     2887}
     2888
     2889
     2890/**
     2891 * Emits a 128-bit GPR load via a GPR base address with a displacement.
     2892 */
     2893DECL_INLINE_THROW(uint32_t)
     2894iemNativeEmitLoadVecRegByGprU128(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iVecRegDst, uint8_t iGprBase, int32_t offDisp)
     2895{
     2896#ifdef RT_ARCH_AMD64
     2897    off = iemNativeEmitLoadVecRegByGprU128Ex(iemNativeInstrBufEnsure(pReNative, off, 8), off, iVecRegDst, iGprBase, offDisp);
     2898    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     2899
     2900#elif defined(RT_ARCH_ARM64)
     2901    off = iemNativeEmitGprByGprLdSt(pReNative, off, iVecRegDst, iGprBase, offDisp, kArmv8A64InstrLdStType_Ld_Vr_128, sizeof(RTUINT128U));
     2902
     2903#else
     2904# error "port me"
     2905#endif
     2906    return off;
     2907}
     2908#endif
     2909
     2910
    28562911/**
    28572912 * Emits a 64-bit GPR store via a GPR base address with a displacement.
     
    73057360               || pVar->enmKind == kIemNativeVarKind_Stack,
    73067361               IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND));
     7362    AssertStmt(!pVar->fSimdReg,
     7363               IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND));
    73077364
    73087365    uint8_t const idxStackSlot   = iemNativeVarGetStackSlot(pReNative, idxVar);
     
    73107367
    73117368    uint8_t const idxRegVar      = pVar->idxReg;
     7369    if (idxRegVar < RT_ELEMENTS(pReNative->Core.aHstRegs))
     7370    {
     7371        off = iemNativeEmitStoreGprByBp(pReNative, off, offBpDisp, idxRegVar);
     7372        iemNativeRegFreeVar(pReNative, idxRegVar, fFlushShadows);
     7373        Assert(pVar->idxReg == UINT8_MAX);
     7374    }
     7375    Assert(   pVar->idxStackSlot != UINT8_MAX
     7376           && pVar->idxReg       == UINT8_MAX);
     7377
     7378    return iemNativeEmitLeaGprByBp(pReNative, off, idxRegArg, offBpDisp);
     7379}
     7380
     7381
    73127382#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
    7313     if (   idxRegVar != UINT8_MAX
    7314         && pVar->fSimdReg)
    7315     {
    7316         Assert(idxRegVar < RT_ELEMENTS(pReNative->Core.aHstSimdRegs));
    7317         Assert(pVar->cbVar == sizeof(RTUINT128U) || pVar->cbVar == sizeof(RTUINT256U));
    7318 
     7383/**
     7384 * Emits code to load the variable address into an argument GPR.
     7385 *
     7386 * This is a special variant intended for SIMD variables only and only called
     7387 * by the TLB miss path in the memory fetch/store code because there we pass
     7388 * the value by reference and need both the register and stack depending on which
     7389 * path is taken (TLB hit vs. miss).
     7390 */
     7391DECL_FORCE_INLINE_THROW(uint32_t)
     7392iemNativeEmitLoadArgGregWithSimdVarAddrForMemAccess(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxRegArg, uint8_t idxVar,
     7393                                                    bool fSyncRegWithStack = true)
     7394{
     7395    IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVar);
     7396    PIEMNATIVEVAR const pVar = &pReNative->Core.aVars[IEMNATIVE_VAR_IDX_UNPACK(idxVar)];
     7397    AssertStmt(   pVar->enmKind == kIemNativeVarKind_Invalid
     7398               || pVar->enmKind == kIemNativeVarKind_Stack,
     7399               IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND));
     7400    AssertStmt(pVar->fSimdReg,
     7401               IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND));
     7402    Assert(   pVar->idxStackSlot != UINT8_MAX
     7403           && pVar->idxReg != UINT8_MAX);
     7404
     7405    uint8_t const idxStackSlot   = iemNativeVarGetStackSlot(pReNative, idxVar);
     7406    int32_t const offBpDisp      = iemNativeStackCalcBpDisp(idxStackSlot);
     7407
     7408    uint8_t const idxRegVar      = pVar->idxReg;
     7409    Assert(idxRegVar < RT_ELEMENTS(pReNative->Core.aHstSimdRegs));
     7410    Assert(pVar->cbVar == sizeof(RTUINT128U) || pVar->cbVar == sizeof(RTUINT256U));
     7411
     7412    if (fSyncRegWithStack)
     7413    {
    73197414        if (pVar->cbVar == sizeof(RTUINT128U))
    73207415            off = iemNativeEmitStoreVecRegByBpU128(pReNative, off, offBpDisp, idxRegVar);
    73217416        else
    73227417            off = iemNativeEmitStoreVecRegByBpU256(pReNative, off, offBpDisp, idxRegVar);
    7323 
    7324         iemNativeSimdRegFreeVar(pReNative, idxRegVar, fFlushShadows);
    7325         Assert(pVar->idxReg == UINT8_MAX);
    7326     }
    7327     else
    7328 #endif
    7329     if (idxRegVar < RT_ELEMENTS(pReNative->Core.aHstRegs))
    7330     {
    7331         off = iemNativeEmitStoreGprByBp(pReNative, off, offBpDisp, idxRegVar);
    7332         iemNativeRegFreeVar(pReNative, idxRegVar, fFlushShadows);
    7333         Assert(pVar->idxReg == UINT8_MAX);
    7334     }
     7418    }
     7419
     7420    return iemNativeEmitLeaGprByBp(pReNative, off, idxRegArg, offBpDisp);
     7421}
     7422
     7423
     7424/**
     7425 * Emits code to sync the host SIMD register assigned to the given SIMD variable.
     7426 *
     7427 * This is a special helper and only called
     7428 * by the TLB miss path in the memory fetch/store code because there we pass
     7429 * the value by reference and need to sync the value on the stack with the assigned host register
     7430 * after a TLB miss where the value ends up on the stack.
     7431 */
     7432DECL_FORCE_INLINE_THROW(uint32_t)
     7433iemNativeEmitSimdVarSyncStackToRegister(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVar)
     7434{
     7435    IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVar);
     7436    PIEMNATIVEVAR const pVar = &pReNative->Core.aVars[IEMNATIVE_VAR_IDX_UNPACK(idxVar)];
     7437    AssertStmt(   pVar->enmKind == kIemNativeVarKind_Invalid
     7438               || pVar->enmKind == kIemNativeVarKind_Stack,
     7439               IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND));
     7440    AssertStmt(pVar->fSimdReg,
     7441               IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_VAR_UNEXPECTED_KIND));
    73357442    Assert(   pVar->idxStackSlot != UINT8_MAX
    7336            && pVar->idxReg       == UINT8_MAX);
    7337 
    7338     return iemNativeEmitLeaGprByBp(pReNative, off, idxRegArg, offBpDisp);
    7339 }
    7340 
    7341 
    7342 #ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     7443           && pVar->idxReg != UINT8_MAX);
     7444
     7445    uint8_t const idxStackSlot   = iemNativeVarGetStackSlot(pReNative, idxVar);
     7446    int32_t const offBpDisp      = iemNativeStackCalcBpDisp(idxStackSlot);
     7447
     7448    uint8_t const idxRegVar      = pVar->idxReg;
     7449    Assert(idxRegVar < RT_ELEMENTS(pReNative->Core.aHstSimdRegs));
     7450    Assert(pVar->cbVar == sizeof(RTUINT128U) || pVar->cbVar == sizeof(RTUINT256U));
     7451
     7452    if (pVar->cbVar == sizeof(RTUINT128U))
     7453        off = iemNativeEmitLoadVecRegByBpU128(pReNative, off, idxRegVar, offBpDisp);
     7454    else
     7455        off = iemNativeEmitLoadVecRegByBpU256(pReNative, off, idxRegVar, offBpDisp);
     7456
     7457    return off;
     7458}
     7459
    73437460
    73447461/**
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