VirtualBox

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


Ignore:
Timestamp:
Aug 14, 2024 1:57:57 PM (6 months ago)
Author:
vboxsync
Message:

VMM/IEM,TM: Do full-TB looping. Redid timer polling in the recompiler. Rewrote the Blt_CheckIrq code, eliminating a conditional. Fixed some TLB related assertions. Moved some IEMCPU members around in hope of better cache-locality. bugref:10656

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

Legend:

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

    r105664 r105673  
    9292# define IEM_WITH_THROW_CATCH
    9393#endif /*ASM-NOINC-END*/
     94
     95/** @def IEM_WITH_INTRA_TB_JUMPS
     96 * Enables loop-jumps within a TB (currently only to the first call).
     97 */
     98#if defined(DOXYGEN_RUNNING) || 1
     99# define IEM_WITH_INTRA_TB_JUMPS
     100#endif
    94101
    95102/** @def IEMNATIVE_WITH_DELAYED_PC_UPDATING
     
    12451252    uint8_t     uTbLookup;
    12461253
    1247     /** Unused atm. */
    1248     uint8_t     uUnused0;
     1254    /** Flags - IEMTHREADEDCALLENTRY_F_XXX. */
     1255    uint8_t     fFlags;
    12491256
    12501257    /** Generic parameters. */
     
    12701277/** Make a IEMTHRDEDCALLENTRY::uTbLookup value. */
    12711278#define IEM_TB_LOOKUP_TAB_MAKE(a_idxTable, a_fLarge)    ((a_idxTable) | ((a_fLarge) ? 0x80 : 0))
     1279
     1280
     1281/** The call entry is a jump target. */
     1282#define IEMTHREADEDCALLENTRY_F_JUMP_TARGET              UINT8_C(0x01)
     1283
    12721284
    12731285/**
     
    21292141    uint8_t                 abAlignment9[42];
    21302142
    2131     /** @name Recompilation
     2143
     2144    /** @name Recompiled Exection
    21322145     * @{ */
    21332146    /** Pointer to the current translation block.
     
    21562169    uint64_t                u64Unused;
    21572170#endif
    2158     /** Fixed TB used for threaded recompilation.
    2159      * This is allocated once with maxed-out sizes and re-used afterwards. */
    2160     R3PTRTYPE(PIEMTB)       pThrdCompileTbR3;
    21612171    /** Pointer to the ring-3 TB cache for this EMT. */
    21622172    R3PTRTYPE(PIEMTBCACHE)  pTbCacheR3;
     
    21652175     * entry, thus it can always safely be used w/o NULL checking. */
    21662176    R3PTRTYPE(PIEMTB *)     ppTbLookupEntryR3;
     2177#if 0 /* unused */
    21672178    /** The PC (RIP) at the start of pCurTbR3/pCurTbR0.
    21682179     * The TBs are based on physical addresses, so this is needed to correleated
    21692180     * RIP to opcode bytes stored in the TB (AMD-V / VT-x). */
    21702181    uint64_t                uCurTbStartPc;
     2182#endif
     2183
    21712184    /** Number of threaded TBs executed. */
    21722185    uint64_t                cTbExecThreaded;
    21732186    /** Number of native TBs executed. */
    21742187    uint64_t                cTbExecNative;
     2188
     2189    /** The number of IRQ/FF checks till the next timer poll call. */
     2190    uint32_t                cIrqChecksTillNextPoll;
     2191    /** The virtual sync time at the last timer poll call in milliseconds. */
     2192    uint32_t                msRecompilerPollNow;
     2193    /** The virtual sync time at the last timer poll call in nanoseconds. */
     2194    uint64_t                nsRecompilerPollNow;
     2195    /** The previous cIrqChecksTillNextPoll value. */
     2196    uint32_t                cIrqChecksTillNextPollPrev;
     2197    /** The ideal nanosecond interval between two timer polls.
     2198     * @todo make this adaptive?  */
     2199    uint32_t                cNsIdealPollInterval;
     2200
     2201    /** The current instruction number in a native TB.
     2202     * This is set by code that may trigger an unexpected TB exit (throw/longjmp)
     2203     * and will be picked up by the TB execution loop. Only used when
     2204     * IEMNATIVE_WITH_INSTRUCTION_COUNTING is defined. */
     2205    uint8_t                 idxTbCurInstr;
     2206    /** @} */
     2207
     2208    /** @name Recompilation
     2209     * @{ */
    21752210    /** Whether we need to check the opcode bytes for the current instruction.
    21762211     * This is set by a previous instruction if it modified memory or similar.  */
     
    21822217    /** Whether to end the current TB. */
    21832218    bool                    fEndTb;
     2219    /** Indicates that the current instruction is an STI.  This is set by the
     2220     * iemCImpl_sti code and subsequently cleared by the recompiler. */
     2221    bool                    fTbCurInstrIsSti;
     2222    /** Spaced reserved for recompiler data / alignment. */
     2223    bool                    afRecompilerStuff1[1];
    21842224    /** Number of instructions before we need emit an IRQ check call again.
    21852225     * This helps making sure we don't execute too long w/o checking for
     
    21892229     * fTbCurInstrIsSti. */
    21902230    uint8_t                 cInstrTillIrqCheck;
    2191     /** Indicates that the current instruction is an STI.  This is set by the
    2192      * iemCImpl_sti code and subsequently cleared by the recompiler. */
    2193     bool                    fTbCurInstrIsSti;
     2231    /** The index of the last CheckIrq call during threaded recompilation. */
     2232    uint16_t                idxLastCheckIrqCallNo;
    21942233    /** The size of the IEMTB::pabOpcodes allocation in pThrdCompileTbR3. */
    21952234    uint16_t                cbOpcodesAllocated;
    2196     /** The current instruction number in a native TB.
    2197      * This is set by code that may trigger an unexpected TB exit (throw/longjmp)
    2198      * and will be picked up by the TB execution loop. Only used when
    2199      * IEMNATIVE_WITH_INSTRUCTION_COUNTING is defined. */
    2200     uint8_t                 idxTbCurInstr;
    2201     /** Spaced reserved for recompiler data / alignment. */
    2202     bool                    afRecompilerStuff1[3];
    2203     /** The virtual sync time at the last timer poll call. */
    2204     uint32_t                msRecompilerPollNow;
    22052235    /** The IEMTB::cUsed value when to attempt native recompilation of a TB. */
    22062236    uint32_t                uTbNativeRecompileAtUsedCount;
     
    22122242     *  currently not up to date in EFLAGS. */
    22132243    uint32_t                fSkippingEFlags;
     2244    /** Spaced reserved for recompiler data / alignment. */
     2245    uint32_t                u32RecompilerStuff2;
     2246#if 0  /* unused */
    22142247    /** Previous GCPhysInstrBuf value - only valid if fTbCrossedPage is set.   */
    22152248    RTGCPHYS                GCPhysInstrBufPrev;
     2249#endif
     2250
     2251    /** Fixed TB used for threaded recompilation.
     2252     * This is allocated once with maxed-out sizes and re-used afterwards. */
     2253    R3PTRTYPE(PIEMTB)       pThrdCompileTbR3;
    22162254    /** Pointer to the ring-3 TB allocator for this EMT. */
    22172255    R3PTRTYPE(PIEMTBALLOCATOR) pTbAllocatorR3;
     
    22222260    /** Dummy entry for ppTbLookupEntryR3. */
    22232261    R3PTRTYPE(PIEMTB)       pTbLookupEntryDummyR3;
     2262    /** @} */
    22242263
    22252264    /** Dummy TLB entry used for accesses to pages with databreakpoints. */
     
    22302269    /** Statistics: Times BltIn_CheckIrq breaks out of the TB. */
    22312270    STAMCOUNTER             StatCheckIrqBreaks;
     2271    /** Statistics: Times BltIn_CheckTimers breaks direct linking TBs. */
     2272    STAMCOUNTER             StatCheckTimersBreaks;
    22322273    /** Statistics: Times BltIn_CheckMode breaks out of the TB. */
    22332274    STAMCOUNTER             StatCheckModeBreaks;
     
    22402281    /** Statistics: Times a jump or page crossing required a TB with CS.LIM checking. */
    22412282    STAMCOUNTER             StatCheckNeedCsLimChecking;
    2242     /** Statistics: Times a loop was detected within a TB.. */
     2283    /** Statistics: Times a loop was detected within a TB. */
    22432284    STAMCOUNTER             StatTbLoopInTbDetected;
     2285    /** Statistics: Times a loop back to the start of the TB was detected. */
     2286    STAMCOUNTER             StatTbLoopFullTbDetected;
    22442287    /** Exec memory allocator statistics: Number of times allocaintg executable memory failed. */
    22452288    STAMCOUNTER             StatNativeExecMemInstrBufAllocFailed;
     
    24212464    STAMCOUNTER             StatNativeTbExitObsoleteTb;
    24222465
     2466    /** Native recompiler: Number of full TB loops (jumps from end to start). */
     2467    STAMCOUNTER             StatNativeTbExitLoopFullTb;
     2468
    24232469    /** Native recompiler: Failure situations with direct linking scenario \#1.
    24242470     * Counter with StatNativeTbExitReturnBreak. Not in release builds.
     
    24482494
    24492495#ifdef IEM_WITH_TLB_TRACE
    2450     uint64_t                au64Padding[2];
     2496    uint64_t                au64Padding[6];
    24512497#else
    2452     uint64_t                au64Padding[4];
    2453 #endif
    2454     /** @} */
     2498    //uint64_t                au64Padding[1];
     2499#endif
    24552500
    24562501#ifdef IEM_WITH_TLB_TRACE
     
    24912536AssertCompileMemberAlignment(IEMCPU, aMemMappingLocks, 16);
    24922537AssertCompileMemberAlignment(IEMCPU, aBounceBuffers, 64);
     2538AssertCompileMemberAlignment(IEMCPU, pCurTbR3, 64);
    24932539AssertCompileMemberAlignment(IEMCPU, DataTlb, 64);
    24942540AssertCompileMemberAlignment(IEMCPU, CodeTlb, 64);
     
    67426788extern const PFNIEMOP g_apfnIemThreadedRecompilerVecMap3[1024];
    67436789
     6790DECLHIDDEN(int)     iemPollTimers(PVMCC pVM, PVMCPUCC pVCpu) RT_NOEXCEPT;
     6791
    67446792DECLCALLBACK(int)   iemTbInit(PVMCC pVM, uint32_t cInitialTbs, uint32_t cMaxTbs,
    67456793                              uint64_t cbInitialExec, uint64_t cbMaxExec, uint32_t cbChunkExec);
     
    67776825
    67786826IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckIrq);
     6827IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckTimers);
     6828IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckTimersAndIrq);
    67796829IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckMode);
    67806830IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckHwInstrBps);
     
    68066856IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesOnNewPageLoadingTlb);
    68076857IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesOnNewPageLoadingTlbConsiderCsLim);
     6858
     6859IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_Jump);
    68086860
    68096861bool iemThreadedCompileEmitIrqCheckBefore(PVMCPUCC pVCpu, PIEMTB pTb);
  • trunk/src/VBox/VMM/include/IEMN8veRecompiler.h

    r105490 r105673  
    491491    kIemNativeLabelType_LastTbExit        = kIemNativeLabelType_Return,
    492492
     493    /** Loop-jump target. */
     494    kIemNativeLabelType_LoopJumpTarget,
     495
    493496    /*
    494497     * Labels with data, potentially multiple instances per TB:
     
    14491452    /** Condition sequence number (for generating unique labels). */
    14501453    uint16_t                    uCondSeqNo;
    1451     /** Check IRQ seqeunce number (for generating unique labels). */
     1454    /** Check IRQ sequence number (for generating unique labels). */
    14521455    uint16_t                    uCheckIrqSeqNo;
    14531456    /** TLB load sequence number (for generating unique labels). */
     
    16321635                                                 uint32_t offWhere = UINT32_MAX, uint16_t uData = 0);
    16331636DECL_HIDDEN_THROW(void)     iemNativeLabelDefine(PIEMRECOMPILERSTATE pReNative, uint32_t idxLabel, uint32_t offWhere);
     1637DECLHIDDEN(uint32_t)        iemNativeLabelFind(PIEMRECOMPILERSTATE pReNative, IEMNATIVELABELTYPE enmType,
     1638                                               uint32_t offWhere = UINT32_MAX, uint16_t uData = 0) RT_NOEXCEPT;
    16341639DECL_HIDDEN_THROW(void)     iemNativeAddFixup(PIEMRECOMPILERSTATE pReNative, uint32_t offWhere, uint32_t idxLabel,
    16351640                                              IEMNATIVEFIXUPTYPE enmType, int8_t offAddend = 0);
  • trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h

    r105491 r105673  
    503503}
    504504
     505/**
     506 * Special variant of iemNativeEmitGprByVCpuDisp for accessing the VM structure.
     507 */
     508DECL_FORCE_INLINE(uint32_t)
     509iemNativeEmitGprByVCpuSignedDisp(uint8_t *pbCodeBuf, uint32_t off, uint8_t iGprReg, int32_t offVCpu)
     510{
     511    Assert(offVCpu < 0);
     512    if (offVCpu < 128 && offVCpu >= -128)
     513    {
     514        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM1, iGprReg & 7, IEMNATIVE_REG_FIXED_PVMCPU);
     515        pbCodeBuf[off++] = (uint8_t)(int8_t)offVCpu;
     516    }
     517    else
     518    {
     519        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_MEM4, iGprReg & 7, IEMNATIVE_REG_FIXED_PVMCPU);
     520        pbCodeBuf[off++] = RT_BYTE1((uint32_t)offVCpu);
     521        pbCodeBuf[off++] = RT_BYTE2((uint32_t)offVCpu);
     522        pbCodeBuf[off++] = RT_BYTE3((uint32_t)offVCpu);
     523        pbCodeBuf[off++] = RT_BYTE4((uint32_t)offVCpu);
     524    }
     525    return off;
     526}
     527
    505528#elif defined(RT_ARCH_ARM64)
    506529
     
    585608}
    586609
     610
     611/**
     612 * Special variant of iemNativeEmitGprByVCpuLdStEx for accessing the VM
     613 * structure.
     614 *
     615 * @note Loads can use @a iGprReg for large offsets, stores requires a temporary
     616 *       registers (@a iGprTmp).
     617 * @note DON'T try this with prefetch.
     618 */
     619DECL_FORCE_INLINE_THROW(uint32_t)
     620iemNativeEmitGprBySignedVCpuLdStEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprReg, int32_t offVCpu,
     621                                   ARMV8A64INSTRLDSTTYPE enmOperation, unsigned cbData, uint8_t iGprTmp = UINT8_MAX)
     622{
     623    Assert(offVCpu < 0);
     624    Assert((uint32_t)-offVCpu < RT_BIT_32(28)); /* we should be way out of range for problematic sign extending issues. */
     625    Assert(!((uint32_t)-offVCpu & (cbData - 1)));
     626
     627   /*
     628     * For negative offsets we need to use put the displacement in a register
     629     * as the two variants with signed immediates will either post or pre
     630     * increment the base address register.
     631     */
     632    if (!ARMV8A64INSTRLDSTTYPE_IS_STORE(enmOperation) || iGprTmp != UINT8_MAX)
     633    {
     634        uint8_t const idxIndexReg = !ARMV8A64INSTRLDSTTYPE_IS_STORE(enmOperation) ? iGprReg : IEMNATIVE_REG_FIXED_TMP0;
     635        off = iemNativeEmitLoadGpr32ImmEx(pCodeBuf, off, idxIndexReg, offVCpu / (int32_t)cbData);
     636        pCodeBuf[off++] = Armv8A64MkInstrStLdRegIdx(enmOperation, iGprReg, IEMNATIVE_REG_FIXED_PVMCPU, idxIndexReg,
     637                                                    kArmv8A64InstrLdStExtend_Sxtw, cbData > 1 /*fShifted*/);
     638    }
     639    else
     640# ifdef IEM_WITH_THROW_CATCH
     641        AssertFailedStmt(IEMNATIVE_DO_LONGJMP(NULL, VERR_IEM_IPE_9));
     642# else
     643        AssertReleaseFailedStmt(off = UINT32_MAX);
     644# endif
     645
     646    return off;
     647}
     648
     649/**
     650 * Special variant of iemNativeEmitGprByVCpuLdSt for accessing the VM structure.
     651 */
     652DECL_FORCE_INLINE_THROW(uint32_t)
     653iemNativeEmitGprBySignedVCpuLdSt(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprReg,
     654                                 int32_t offVCpu, ARMV8A64INSTRLDSTTYPE enmOperation, unsigned cbData)
     655{
     656    off = iemNativeEmitGprBySignedVCpuLdStEx(iemNativeInstrBufEnsure(pReNative, off, 2 + 1), off, iGprReg,
     657                                             offVCpu, enmOperation, cbData, IEMNATIVE_REG_FIXED_TMP0);
     658    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     659    return off;
     660}
     661
    587662#endif /* RT_ARCH_ARM64 */
    588663
     
    601676        pCodeBuf[off++] = X86_OP_REX_W | X86_OP_REX_R;
    602677    pCodeBuf[off++] = 0x8b;
    603     off = iemNativeEmitGprByVCpuDisp(pCodeBuf, off,iGpr, offVCpu);
     678    off = iemNativeEmitGprByVCpuDisp(pCodeBuf, off, iGpr, offVCpu);
    604679
    605680#elif defined(RT_ARCH_ARM64)
     
    773848#endif
    774849    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     850    return off;
     851}
     852
     853
     854/**
     855 * Emits a store of a GPR value to a 32-bit VCpu field.
     856 *
     857 * @note Limited range on ARM64.
     858 */
     859DECL_INLINE_THROW(uint32_t)
     860iemNativeEmitStoreGprToVCpuU32Ex(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGpr, uint32_t offVCpu)
     861{
     862#ifdef RT_ARCH_AMD64
     863    /* mov mem32, reg32 */
     864    if (iGpr >= 8)
     865        pCodeBuf[off++] = X86_OP_REX_R;
     866    pCodeBuf[off++] = 0x89;
     867    off = iemNativeEmitGprByVCpuDisp(pCodeBuf, off, iGpr, offVCpu);
     868
     869#elif defined(RT_ARCH_ARM64)
     870    off = iemNativeEmitGprByVCpuLdStEx(pCodeBuf, off, iGpr, offVCpu, kArmv8A64InstrLdStType_St_Word, sizeof(uint32_t));
     871
     872#else
     873# error "port me"
     874#endif
    775875    return off;
    776876}
     
    54365536{
    54375537#if defined(RT_ARCH_AMD64)
    5438     /* and Ev, imm */
     5538    /* xor Ev, imm */
    54395539    if (iGprDst >= 8)
    54405540        pCodeBuf[off++] = X86_OP_REX_B;
     
    61306230 */
    61316231DECL_INLINE_THROW(uint32_t)
     6232iemNativeEmitCmpGprWithImmEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprLeft,
     6233                             uint64_t uImm, uint8_t idxTmpReg = UINT8_MAX)
     6234{
     6235#ifdef RT_ARCH_AMD64
     6236    if ((int8_t)uImm == (int64_t)uImm)
     6237    {
     6238        /* cmp Ev, Ib */
     6239        pCodeBuf[off++] = X86_OP_REX_W | (iGprLeft >= 8 ? X86_OP_REX_B : 0);
     6240        pCodeBuf[off++] = 0x83;
     6241        pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, iGprLeft & 7);
     6242        pCodeBuf[off++] = (uint8_t)uImm;
     6243        return off;
     6244    }
     6245    if ((int32_t)uImm == (int64_t)uImm)
     6246    {
     6247        /* cmp Ev, imm */
     6248        pCodeBuf[off++] = X86_OP_REX_W | (iGprLeft >= 8 ? X86_OP_REX_B : 0);
     6249        pCodeBuf[off++] = 0x81;
     6250        pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, iGprLeft & 7);
     6251        pCodeBuf[off++] = RT_BYTE1(uImm);
     6252        pCodeBuf[off++] = RT_BYTE2(uImm);
     6253        pCodeBuf[off++] = RT_BYTE3(uImm);
     6254        pCodeBuf[off++] = RT_BYTE4(uImm);
     6255        return off;
     6256    }
     6257
     6258#elif defined(RT_ARCH_ARM64)
     6259    if (uImm < _4K)
     6260    {
     6261        pCodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(true /*fSub*/, ARMV8_A64_REG_XZR, iGprLeft, (uint32_t)uImm,
     6262                                                      true /*64Bit*/, true /*fSetFlags*/);
     6263        return off;
     6264    }
     6265    if ((uImm & ~(uint64_t)0xfff000) == 0)
     6266    {
     6267        pCodeBuf[off++] = Armv8A64MkInstrAddSubUImm12(true /*fSub*/, ARMV8_A64_REG_XZR, iGprLeft, (uint32_t)uImm >> 12,
     6268                                                      true /*64Bit*/, true /*fSetFlags*/, true /*fShift12*/);
     6269        return off;
     6270    }
     6271
     6272#else
     6273# error "Port me!"
     6274#endif
     6275
     6276    if (idxTmpReg != UINT8_MAX)
     6277    {
     6278        /* Use temporary register for the immediate. */
     6279        off = iemNativeEmitLoadGprImmEx(pCodeBuf, off, idxTmpReg, uImm);
     6280        off = iemNativeEmitCmpGprWithGprEx(pCodeBuf, off, iGprLeft, idxTmpReg);
     6281    }
     6282    else
     6283# ifdef IEM_WITH_THROW_CATCH
     6284        AssertFailedStmt(IEMNATIVE_DO_LONGJMP(NULL, VERR_IEM_IPE_9));
     6285# else
     6286        AssertReleaseFailedStmt(off = UINT32_MAX);
     6287# endif
     6288
     6289    return off;
     6290}
     6291
     6292
     6293/**
     6294 * Emits a compare of a 64-bit GPR with a constant value, settings status
     6295 * flags/whatever for use with conditional instruction.
     6296 */
     6297DECL_INLINE_THROW(uint32_t)
    61326298iemNativeEmitCmpGprWithImm(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprLeft, uint64_t uImm)
    61336299{
    61346300#ifdef RT_ARCH_AMD64
    6135     if (uImm <= UINT32_C(0xff))
     6301    if ((int8_t)uImm == (int64_t)uImm)
    61366302    {
    61376303        /* cmp Ev, Ib */
     
    61426308        pbCodeBuf[off++] = (uint8_t)uImm;
    61436309    }
    6144     else if ((int64_t)uImm == (int32_t)uImm)
     6310    else if ((int32_t)uImm == (int64_t)uImm)
    61456311    {
    61466312        /* cmp Ev, imm */
     
    69747140
    69757141#elif defined(RT_ARCH_ARM64)
     7142    int32_t const    offDisp     = offTarget - offFixup;
    69767143    uint32_t * const pu32CodeBuf = pReNative->pInstrBuf;
    69777144    if ((pu32CodeBuf[offFixup] & UINT32_C(0xff000000)) == UINT32_C(0x54000000))
    69787145    {
    69797146        /* B.COND + BC.COND */
    6980         int32_t const offDisp = offTarget - offFixup;
    69817147        Assert(offDisp >= -262144 && offDisp < 262144);
    69827148        pu32CodeBuf[offFixup] = (pu32CodeBuf[offFixup] & UINT32_C(0xff00001f))
    69837149                              | (((uint32_t)offDisp    & UINT32_C(0x0007ffff)) << 5);
    69847150    }
    6985     else
     7151    else if ((pu32CodeBuf[offFixup] & UINT32_C(0xfc000000)) == UINT32_C(0x14000000))
    69867152    {
    69877153        /* B imm26 */
    6988         Assert((pu32CodeBuf[offFixup] & UINT32_C(0xfc000000)) == UINT32_C(0x14000000));
    6989         int32_t const offDisp = offTarget - offFixup;
    69907154        Assert(offDisp >= -33554432 && offDisp < 33554432);
    69917155        pu32CodeBuf[offFixup] = (pu32CodeBuf[offFixup] & UINT32_C(0xfc000000))
    69927156                              | ((uint32_t)offDisp     & UINT32_C(0x03ffffff));
     7157    }
     7158    else
     7159    {
     7160        /* CBZ / CBNZ reg, imm19 */
     7161        Assert((pu32CodeBuf[offFixup] & UINT32_C(0x7e000000)) == UINT32_C(0x34000000));
     7162        Assert(offDisp >= -1048576 && offDisp < 1048576);
     7163        pu32CodeBuf[offFixup] = (pu32CodeBuf[offFixup]    & UINT32_C(0xff00001f))
     7164                              | (((uint32_t)offDisp << 5) & UINT32_C(0x00ffffe0));
     7165
    69937166    }
    69947167
     
    84518624
    84528625
     8626/**
     8627 * Emits code that exits the current TB with @a enmExitReason if @a iGprSrc is zero.
     8628 *
     8629 * The operand size is given by @a f64Bit.
     8630 */
     8631DECL_FORCE_INLINE_THROW(uint32_t)
     8632iemNativeEmitTestIfGprIsZeroAndTbExitEx(PIEMRECOMPILERSTATE pReNative, PIEMNATIVEINSTR pCodeBuf, uint32_t off,
     8633                                        uint8_t iGprSrc, bool f64Bit, IEMNATIVELABELTYPE enmExitReason)
     8634{
     8635    Assert(IEMNATIVELABELTYPE_IS_EXIT_REASON(enmExitReason));
     8636#if defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) && defined(RT_ARCH_AMD64)
     8637    /* test reg32,reg32  / test reg64,reg64 */
     8638    if (f64Bit)
     8639        pCodeBuf[off++] = X86_OP_REX_W | (iGprSrc < 8 ? 0 : X86_OP_REX_R | X86_OP_REX_B);
     8640    else if (iGprSrc >= 8)
     8641        pCodeBuf[off++] = X86_OP_REX_R | X86_OP_REX_B;
     8642    pCodeBuf[off++] = 0x85;
     8643    pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGprSrc & 7, iGprSrc & 7);
     8644
     8645    /* jnz idxLabel  */
     8646    return iemNativeEmitJccTbExitEx(pReNative, pCodeBuf, off, enmExitReason, kIemNativeInstrCond_e);
     8647
     8648#else
     8649    /* ARM64 doesn't have the necessary jump range, so we jump via local label
     8650       just like when we keep everything local. */
     8651    uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/);
     8652    return iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToLabelEx(pReNative, pCodeBuf, off, iGprSrc,
     8653                                                                f64Bit, false /*fJmpIfNotZero*/, idxLabel);
     8654#endif
     8655}
     8656
     8657
     8658/**
     8659 * Emits code to exit the current TB with the given reason @a enmExitReason if @a iGprSrc is zero.
     8660 *
     8661 * The operand size is given by @a f64Bit.
     8662 */
     8663DECL_INLINE_THROW(uint32_t)
     8664iemNativeEmitTestIfGprIsZeroAndTbExit(PIEMRECOMPILERSTATE pReNative, uint32_t off,
     8665                                      uint8_t iGprSrc, bool f64Bit, IEMNATIVELABELTYPE enmExitReason)
     8666{
     8667#if defined(IEMNATIVE_WITH_RECOMPILER_PER_CHUNK_TAIL_CODE) && defined(RT_ARCH_AMD64)
     8668    off = iemNativeEmitTestIfGprIsZeroAndTbExitEx(pReNative, iemNativeInstrBufEnsure(pReNative, off, 3 + 6),
     8669                                                  off, iGprSrc, f64Bit, enmExitReason);
     8670    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     8671    return off;
     8672#else
     8673    uint32_t const idxLabel = iemNativeLabelCreate(pReNative, enmExitReason, UINT32_MAX /*offWhere*/, 0 /*uData*/);
     8674    return iemNativeEmitTestIfGprIsZeroOrNotZeroAndJmpToLabel(pReNative, off, iGprSrc, f64Bit, false /*fJmpIfNotZero*/, idxLabel);
     8675#endif
     8676}
     8677
     8678
    84538679#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
    84548680/*********************************************************************************************************************************
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