VirtualBox

Changeset 102699 in vbox for trunk/src/VBox/VMM/include


Ignore:
Timestamp:
Dec 25, 2023 10:22:01 PM (14 months ago)
Author:
vboxsync
Message:

VMM/IEM: Native translation of BODY_LOAD_TLB_AFTER_BRANCH. (only tested on amd64) bugref:10371

Location:
trunk/src/VBox/VMM/include
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/include/IEMN8veRecompiler.h

    r102684 r102699  
    814814                                                    bool fPreferVolatile = true);
    815815DECL_HIDDEN_THROW(uint8_t)  iemNativeRegAllocTmpForGuestReg(PIEMRECOMPILERSTATE pReNative, uint32_t *poff,
    816                                                             IEMNATIVEGSTREG enmGstReg, IEMNATIVEGSTREGUSE enmIntendedUse);
     816                                                            IEMNATIVEGSTREG enmGstReg, IEMNATIVEGSTREGUSE enmIntendedUse,
     817                                                            bool fNoVoltileRegs = false);
    817818DECL_HIDDEN_THROW(uint8_t)  iemNativeRegAllocTmpForGuestRegIfAlreadyPresent(PIEMRECOMPILERSTATE pReNative, uint32_t *poff,
    818819                                                                            IEMNATIVEGSTREG enmGstReg);
  • trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h

    r102662 r102699  
    29032903 * Emits a Jcc rel32 / B.cc imm19 with a fixed displacement.
    29042904 *
    2905  * The @a offTarget is applied x86-style, so zero means the next instruction.
    2906  * The unit is IEMNATIVEINSTR.
    2907  */
    2908 DECL_INLINE_THROW(uint32_t)
    2909 iemNativeEmitJccToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, int32_t offTarget, IEMNATIVEINSTRCOND enmCond)
    2910 {
    2911 #ifdef RT_ARCH_AMD64
    2912     /* jcc rel32 */
     2905 * @note The @a offTarget is the absolute jump target (unit is IEMNATIVEINSTR).
     2906 *
     2907 *       Only use hardcoded jumps forward when emitting for exactly one
     2908 *       platform, otherwise apply iemNativeFixupFixedJump() to ensure hitting
     2909 *       the right target address on all platforms!
     2910 *
     2911 *       Please also note that on x86 it is necessary pass off + 256 or higher
     2912 *       for @a offTarget one believe the intervening code is more than 127
     2913 *       bytes long.
     2914 */
     2915DECL_INLINE_THROW(uint32_t)
     2916iemNativeEmitJccToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t offTarget, IEMNATIVEINSTRCOND enmCond)
     2917{
     2918#ifdef RT_ARCH_AMD64
     2919    /* jcc rel8 / rel32 */
    29132920    uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 6);
    2914     if (offTarget < 128 && offTarget >= -128)
     2921    int32_t         offDisp   = (int32_t)(offTarget - (off + 2));
     2922    if (offDisp < 128 && offDisp >= -128)
    29152923    {
    29162924        pbCodeBuf[off++] = (uint8_t)enmCond | 0x70;
    2917         pbCodeBuf[off++] = RT_BYTE1((uint32_t)offTarget);
    2918     }
    2919     else
    2920     {
     2925        pbCodeBuf[off++] = RT_BYTE1((uint32_t)offDisp);
     2926    }
     2927    else
     2928    {
     2929        offDisp -= 4;
    29212930        pbCodeBuf[off++] = 0x0f;
    29222931        pbCodeBuf[off++] = (uint8_t)enmCond | 0x80;
    2923         pbCodeBuf[off++] = RT_BYTE1((uint32_t)offTarget);
    2924         pbCodeBuf[off++] = RT_BYTE2((uint32_t)offTarget);
    2925         pbCodeBuf[off++] = RT_BYTE3((uint32_t)offTarget);
    2926         pbCodeBuf[off++] = RT_BYTE4((uint32_t)offTarget);
     2932        pbCodeBuf[off++] = RT_BYTE1((uint32_t)offDisp);
     2933        pbCodeBuf[off++] = RT_BYTE2((uint32_t)offDisp);
     2934        pbCodeBuf[off++] = RT_BYTE3((uint32_t)offDisp);
     2935        pbCodeBuf[off++] = RT_BYTE4((uint32_t)offDisp);
    29272936    }
    29282937
    29292938#elif defined(RT_ARCH_ARM64)
    29302939    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
    2931     pu32CodeBuf[off++] = Armv8A64MkInstrBCond(enmCond, offTarget + 1);
     2940    pu32CodeBuf[off++] = Armv8A64MkInstrBCond(enmCond, (int32_t)(offTarget - off));
    29322941
    29332942#else
     
    29422951 * Emits a JZ/JE rel32 / B.EQ imm19 with a fixed displacement.
    29432952 *
    2944  * The @a offTarget is applied x86-style, so zero means the next instruction.
    2945  * The unit is IEMNATIVEINSTR.
    2946  */
    2947 DECL_INLINE_THROW(uint32_t) iemNativeEmitJzToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, int32_t offTarget)
     2953 * See notes on @a offTarget in the iemNativeEmitJccToFixed() documentation.
     2954 */
     2955DECL_INLINE_THROW(uint32_t) iemNativeEmitJzToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t offTarget)
    29482956{
    29492957#ifdef RT_ARCH_AMD64
     
    29602968 * Emits a JNZ/JNE rel32 / B.NE imm19 with a fixed displacement.
    29612969 *
    2962  * The @a offTarget is applied x86-style, so zero means the next instruction.
    2963  * The unit is IEMNATIVEINSTR.
    2964  */
    2965 DECL_INLINE_THROW(uint32_t) iemNativeEmitJnzToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, int32_t offTarget)
     2970 * See notes on @a offTarget in the iemNativeEmitJccToFixed() documentation.
     2971 */
     2972DECL_INLINE_THROW(uint32_t) iemNativeEmitJnzToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t offTarget)
    29662973{
    29672974#ifdef RT_ARCH_AMD64
     
    29782985 * Emits a JBE/JNA rel32 / B.LS imm19 with a fixed displacement.
    29792986 *
    2980  * The @a offTarget is applied x86-style, so zero means the next instruction.
    2981  * The unit is IEMNATIVEINSTR.
    2982  */
    2983 DECL_INLINE_THROW(uint32_t) iemNativeEmitJbeToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, int32_t offTarget)
     2987 * See notes on @a offTarget in the iemNativeEmitJccToFixed() documentation.
     2988 */
     2989DECL_INLINE_THROW(uint32_t) iemNativeEmitJbeToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t offTarget)
    29842990{
    29852991#ifdef RT_ARCH_AMD64
     
    29963002 * Emits a JA/JNBE rel32 / B.HI imm19 with a fixed displacement.
    29973003 *
    2998  * The @a offTarget is applied x86-style, so zero means the next instruction.
    2999  * The unit is IEMNATIVEINSTR.
    3000  */
    3001 DECL_INLINE_THROW(uint32_t) iemNativeEmitJaToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, int32_t offTarget)
     3004 * See notes on @a offTarget in the iemNativeEmitJccToFixed() documentation.
     3005 */
     3006DECL_INLINE_THROW(uint32_t) iemNativeEmitJaToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t offTarget)
    30023007{
    30033008#ifdef RT_ARCH_AMD64
     
    30123017
    30133018/**
     3019 * Emits a JMP rel32/rel8 / B imm26 with a fixed displacement.
     3020 *
     3021 * See notes on @a offTarget in the iemNativeEmitJccToFixed() documentation.
     3022 */
     3023DECL_INLINE_THROW(uint32_t) iemNativeEmitJmpToFixed(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t offTarget)
     3024{
     3025#ifdef RT_ARCH_AMD64
     3026    /* jmp rel8 or rel32 */
     3027    uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 5);
     3028    int32_t         offDisp   = offTarget - (off + 2);
     3029    if (offDisp < 128 && offDisp >= -128)
     3030    {
     3031        pbCodeBuf[off++] = 0xeb;
     3032        pbCodeBuf[off++] = RT_BYTE1((uint32_t)offDisp);
     3033    }
     3034    else
     3035    {
     3036        offDisp -= 3;
     3037        pbCodeBuf[off++] = 0xe9;
     3038        pbCodeBuf[off++] = RT_BYTE1((uint32_t)offDisp);
     3039        pbCodeBuf[off++] = RT_BYTE2((uint32_t)offDisp);
     3040        pbCodeBuf[off++] = RT_BYTE3((uint32_t)offDisp);
     3041        pbCodeBuf[off++] = RT_BYTE4((uint32_t)offDisp);
     3042    }
     3043
     3044#elif defined(RT_ARCH_ARM64)
     3045    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     3046    pu32CodeBuf[off++] = Armv8A64MkInstrB(enmCond, (int32_t)(offTarget - off));
     3047
     3048#else
     3049# error "Port me!"
     3050#endif
     3051    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     3052    return off;
     3053}
     3054
     3055
     3056/**
    30143057 * Fixes up a conditional jump to a fixed label.
    3015  * @see  iemNativeEmitJnzToFixed, iemNativeEmitJzToFixed, ...
    3016  */
    3017 DECLINLINE(void) iemNativeFixupFixedJump(PIEMRECOMPILERSTATE pReNative, uint32_t offFixup, uint32_t offTarget)
    3018 {
    3019 # if defined(RT_ARCH_AMD64)
     3058 * @see  iemNativeEmitJmpToFixed, iemNativeEmitJnzToFixed,
     3059 *       iemNativeEmitJzToFixed, ...
     3060 */
     3061DECL_INLINE_THROW(void) iemNativeFixupFixedJump(PIEMRECOMPILERSTATE pReNative, uint32_t offFixup, uint32_t offTarget)
     3062{
     3063#ifdef RT_ARCH_AMD64
    30203064    uint8_t * const pbCodeBuf = pReNative->pInstrBuf;
    3021     if (pbCodeBuf[offFixup] != 0x0f)
    3022     {
    3023         Assert((uint8_t)(pbCodeBuf[offFixup] - 0x70) <= 0x10);
     3065    uint8_t const   bOpcode   = pbCodeBuf[offFixup];
     3066    if ((uint8_t)(bOpcode - 0x70) < (uint8_t)0x10 || bOpcode == 0xeb)
     3067    {
    30243068        pbCodeBuf[offFixup + 1] = (uint8_t)(offTarget - (offFixup + 2));
    3025         Assert(pbCodeBuf[offFixup + 1] == offTarget - (offFixup + 2));
    3026     }
    3027     else
    3028     {
    3029         Assert((uint8_t)(pbCodeBuf[offFixup + 1] - 0x80) <= 0x10);
    3030         uint32_t const offRel32 = offTarget - (offFixup + 6);
    3031         pbCodeBuf[offFixup + 2] = RT_BYTE1(offRel32);
    3032         pbCodeBuf[offFixup + 3] = RT_BYTE2(offRel32);
    3033         pbCodeBuf[offFixup + 4] = RT_BYTE3(offRel32);
    3034         pbCodeBuf[offFixup + 5] = RT_BYTE4(offRel32);
    3035     }
    3036 
    3037 # elif defined(RT_ARCH_ARM64)
     3069        AssertStmt(pbCodeBuf[offFixup + 1] == offTarget - (offFixup + 2),
     3070                   IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_EMIT_FIXED_JUMP_OUT_OF_RANGE));
     3071    }
     3072    else
     3073    {
     3074        if (bOpcode != 0x0f)
     3075            Assert(bOpcode == 0xe9);
     3076        else
     3077        {
     3078            offFixup += 1;
     3079            Assert((uint8_t)(pbCodeBuf[offFixup] - 0x80) <= 0x10);
     3080        }
     3081        uint32_t const offRel32 = offTarget - (offFixup + 5);
     3082        pbCodeBuf[offFixup + 1] = RT_BYTE1(offRel32);
     3083        pbCodeBuf[offFixup + 2] = RT_BYTE2(offRel32);
     3084        pbCodeBuf[offFixup + 3] = RT_BYTE3(offRel32);
     3085        pbCodeBuf[offFixup + 4] = RT_BYTE4(offRel32);
     3086    }
     3087
     3088#elif defined(RT_ARCH_ARM64)
    30383089    uint32_t * const pu32CodeBuf = pReNative->pInstrBuf;
    3039 
    3040     int32_t const offDisp = offTarget - offFixup;
    3041     Assert(offDisp >= -262144 && offDisp < 262144);
    3042     Assert((pu32CodeBuf[offFixup] & UINT32_C(0xff000000)) == UINT32_C(0x54000000)); /* B.COND + BC.COND */
    3043 
    3044     pu32CodeBuf[offFixup] = (pu32CodeBuf[offFixup] & UINT32_C(0xff00001f))
    3045                           | (((uint32_t)offDisp    & UINT32_C(0x0007ffff)) << 5);
    3046 
    3047 # endif
     3090    if ((pu32CodeBuf[offFixup] & UINT32_C(0xff000000)) == UINT32_C(0x54000000))
     3091    {
     3092        /* B.COND + BC.COND */
     3093        int32_t const offDisp = offTarget - offFixup;
     3094        Assert(offDisp >= -262144 && offDisp < 262144);
     3095        pu32CodeBuf[offFixup] = (pu32CodeBuf[offFixup] & UINT32_C(0xff00001f))
     3096                              | (((uint32_t)offDisp    & UINT32_C(0x0007ffff)) << 5);
     3097    }
     3098    else
     3099    {
     3100        /* B imm26 */
     3101        Assert((pu32CodeBuf[offFixup] & UINT32_C(0xfc000000)) == UINT32_C(0x14000000));
     3102        int32_t const offDisp = offTarget - offFixup;
     3103        Assert(offDisp >= -33554432 && offDisp < 33554432);
     3104        pu32CodeBuf[offFixup] = (pu32CodeBuf[offFixup] & UINT32_C(0xfc000000))
     3105                              | ((uint32_t)offDisp     & UINT32_C(0x03ffffff));
     3106    }
     3107
     3108#else
     3109# error "Port me!"
     3110#endif
    30483111}
    30493112
     
    33273390
    33283391/**
     3392 * Emits code that jumps to @a idxLabel if @a iGprSrc is not zero.
     3393 *
     3394 * The operand size is given by @a f64Bit.
     3395 */
     3396DECL_INLINE_THROW(uint32_t) iemNativeEmitTestIfGprIsNotZeroAndJmpToLabel(PIEMRECOMPILERSTATE pReNative, uint32_t off,
     3397                                                                         uint8_t iGprSrc, bool f64Bit, uint32_t idxLabel)
     3398{
     3399    Assert(idxLabel < pReNative->cLabels);
     3400
     3401#ifdef RT_ARCH_AMD64
     3402    /* test reg32,reg32  / test reg64,reg64 */
     3403    uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3);
     3404    if (f64Bit)
     3405        pbCodeBuf[off++] = X86_OP_REX_W | (iGprSrc < 8 ? 0 : X86_OP_REX_R | X86_OP_REX_B);
     3406    else if (iGprSrc >= 8)
     3407        pbCodeBuf[off++] = X86_OP_REX_R | X86_OP_REX_B;
     3408    pbCodeBuf[off++] = 0x85;
     3409    pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGprSrc & 7, iGprSrc & 7);
     3410    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     3411
     3412    /* jnz idxLabel  */
     3413    off = iemNativeEmitJnzToLabel(pReNative, off, idxLabel);
     3414
     3415#elif defined(RT_ARCH_ARM64)
     3416    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     3417    iemNativeAddFixup(pReNative, off, idxLabel, kIemNativeFixupType_RelImm19At5);
     3418    pu32CodeBuf[off++] = Armv8A64MkInstrCbzCbnz(true /*fJmpIfNotZero*/, 0, iGprSrc, f64Bit);
     3419    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     3420
     3421#else
     3422# error "Port me!"
     3423#endif
     3424    return off;
     3425}
     3426
     3427
     3428/**
     3429 * Emits code that jumps to a new label if @a iGprSrc is not zero.
     3430 *
     3431 * The operand size is given by @a f64Bit.
     3432 */
     3433DECL_INLINE_THROW(uint32_t)
     3434iemNativeEmitTestIfGprIsNotZeroAndJmpToNewLabel(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprSrc, bool f64Bit,
     3435                                               IEMNATIVELABELTYPE enmLabelType, uint16_t uData = 0)
     3436{
     3437    uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmLabelType, UINT32_MAX /*offWhere*/, uData);
     3438    return iemNativeEmitTestIfGprIsNotZeroAndJmpToLabel(pReNative, off, iGprSrc, f64Bit, idxLabel);
     3439}
     3440
     3441
     3442/**
    33293443 * Emits code that jumps to the given label if @a iGprLeft and @a iGprRight
    33303444 * differs.
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