VirtualBox

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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