VirtualBox

Changeset 103649 in vbox for trunk


Ignore:
Timestamp:
Mar 3, 2024 7:11:39 AM (7 months ago)
Author:
vboxsync
Message:

VMM/IEM: Delay the RIP update for each instruction if possible to save on potentially two instructions for each executed guest instruction of which one is a memory write, bugref:10373

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

Legend:

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

    r103636 r103649  
    190190
    191191/**
     192 * Flushes pending writes in preparation of raising an exception or aborting the TB.
     193 */
     194#define BODY_FLUSH_PENDING_WRITES() \
     195    off = iemNativeRegFlushPendingWrites(pReNative, off);
     196
     197
     198/**
    192199 * Built-in function that checks for pending interrupts that can be delivered or
    193200 * forced action flags.
     
    200207{
    201208    RT_NOREF(pCallEntry);
     209
     210    BODY_FLUSH_PENDING_WRITES();
    202211
    203212    /* It's too convenient to use iemNativeEmitTestBitInGprAndJmpToLabelIfNotSet below
     
    324333#endif
    325334
    326 /**
    327  * Flushes pending writes in preparation of raising an exception or aborting the TB.
    328  */
    329 #define BODY_FLUSH_PENDING_WRITES() \
    330     off = iemNativeRegFlushPendingWrites(pReNative, off);
    331 
    332335
    333336/**
     
    347350#ifdef VBOX_STRICT
    348351    off = iemNativeEmitMarker(pReNative, off, 0x80000001);
     352#endif
     353
     354#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     355    Assert(pReNative->Core.offPc == 0);
    349356#endif
    350357
     
    453460#ifdef VBOX_STRICT
    454461    off = iemNativeEmitMarker(pReNative, off, 0x80000002);
     462#endif
     463
     464#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     465    Assert(pReNative->Core.offPc == 0);
    455466#endif
    456467
     
    10581069#endif
    10591070
     1071#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     1072    Assert(pReNative->Core.offPc == 0);
     1073#endif
     1074
    10601075    /*
    10611076     * The GCPhysRangePageWithOffset value in the threaded function is a fixed
     
    13521367#endif
    13531368
     1369    BODY_FLUSH_PENDING_WRITES();
     1370
    13541371    /*
    13551372     * Define labels and allocate the register for holding the GCPhys of the new page.
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp

    r103639 r103649  
    29182918    pReNative->uTlbSeqNo                   = 0;
    29192919
     2920#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     2921    pReNative->Core.offPc                  = 0;
     2922    pReNative->Core.cInstrPcUpdateSkipped  = 0;
     2923#endif
    29202924    pReNative->Core.bmHstRegs              = IEMNATIVE_REG_FIXED_MASK
    29212925#if IEMNATIVE_HST_GREG_COUNT < 32
     
    29592963                       | RT_BIT_32(IEMNATIVE_REG_FIXED_TMP0)
    29602964#endif
     2965#ifdef IEMNATIVE_REG_FIXED_TMP1
     2966                       | RT_BIT_32(IEMNATIVE_REG_FIXED_TMP1)
     2967#endif
     2968#ifdef IEMNATIVE_REG_FIXED_PC_DBG
     2969                       | RT_BIT_32(IEMNATIVE_REG_FIXED_PC_DBG)
     2970#endif
    29612971                      );
    29622972    for (uint32_t idxReg = ASMBitFirstSetU32(fRegs) - 1; fRegs != 0; idxReg = ASMBitFirstSetU32(fRegs) - 1)
     
    29722982#ifdef IEMNATIVE_REG_FIXED_TMP0
    29732983    pReNative->Core.aHstRegs[IEMNATIVE_REG_FIXED_TMP0].enmWhat       = kIemNativeWhat_FixedTmp;
     2984#endif
     2985#ifdef IEMNATIVE_REG_FIXED_TMP1
     2986    pReNative->Core.aHstRegs[IEMNATIVE_REG_FIXED_TMP1].enmWhat       = kIemNativeWhat_FixedTmp;
     2987#endif
     2988#ifdef IEMNATIVE_REG_FIXED_PC_DBG
     2989    pReNative->Core.aHstRegs[IEMNATIVE_REG_FIXED_PC_DBG].enmWhat     = kIemNativeWhat_PcShadow;
    29742990#endif
    29752991    return pReNative;
     
    33943410    pEntry->GuestRegShadowing.idxHstRegPrev = idxHstRegPrev;
    33953411}
     3412
     3413
     3414# ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     3415/**
     3416 * Debug Info: Record info about delayed RIP updates.
     3417 */
     3418static void iemNativeDbgInfoAddDelayedPcUpdate(PIEMRECOMPILERSTATE pReNative, uint32_t offPc, uint32_t cInstrSkipped)
     3419{
     3420    PIEMTBDBGENTRY const pEntry = iemNativeDbgInfoAddNewEntry(pReNative, pReNative->pDbgInfo);
     3421    pEntry->DelayedPcUpdate.uType         = kIemTbDbgEntryType_DelayedPcUpdate;
     3422    pEntry->DelayedPcUpdate.offPc         = offPc;
     3423    pEntry->DelayedPcUpdate.cInstrSkipped = cInstrSkipped;
     3424}
     3425# endif
    33963426
    33973427#endif /* IEMNATIVE_WITH_TB_DEBUG_INFO */
     
    47514781                         & ~RT_BIT_32(IEMNATIVE_REG_FIXED_TMP0)
    47524782#endif
     4783#ifdef IEMNATIVE_REG_FIXED_TMP1
     4784                         & ~RT_BIT_32(IEMNATIVE_REG_FIXED_TMP1)
     4785#endif
     4786#ifdef IEMNATIVE_REG_FIXED_PC_DBG
     4787                         & ~RT_BIT_32(IEMNATIVE_REG_FIXED_PC_DBG)
     4788#endif
    47534789                         & ~g_afIemNativeCallRegs[cArgs];
    47544790
     
    47984834                case kIemNativeWhat_pVCpuFixed:
    47994835                case kIemNativeWhat_pCtxFixed:
     4836                case kIemNativeWhat_PcShadow:
    48004837                case kIemNativeWhat_FixedReserved:
    48014838                case kIemNativeWhat_Invalid:
     
    50115048
    50125049
     5050#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     5051# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
     5052static uint32_t iemNativePcAdjustCheck(PIEMRECOMPILERSTATE pReNative, uint32_t off)
     5053{
     5054    /* Compare the shadow with the context value, they should match. */
     5055    off = iemNativeEmitLoadGprFromGpr(pReNative, off, IEMNATIVE_REG_FIXED_TMP1, IEMNATIVE_REG_FIXED_PC_DBG);
     5056    off = iemNativeEmitAddGprImm(pReNative, off, IEMNATIVE_REG_FIXED_TMP1, pReNative->Core.offPc);
     5057    off = iemNativeEmitGuestRegValueCheck(pReNative, off, IEMNATIVE_REG_FIXED_TMP1, kIemNativeGstReg_Pc);
     5058    return off;
     5059}
     5060# endif
     5061
     5062/**
     5063 * Emits code to update the guest RIP value by adding the current offset since the start of the last RIP update.
     5064 */
     5065static uint32_t
     5066iemNativeEmitPcWriteback(PIEMRECOMPILERSTATE pReNative, uint32_t off)
     5067{
     5068    if (pReNative->Core.offPc)
     5069    {
     5070# ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     5071        iemNativeDbgInfoAddNativeOffset(pReNative, off);
     5072        iemNativeDbgInfoAddDelayedPcUpdate(pReNative, pReNative->Core.offPc, pReNative->Core.cInstrPcUpdateSkipped);
     5073# endif
     5074
     5075# ifndef IEMNATIVE_REG_FIXED_PC_DBG
     5076        /* Allocate a temporary PC register. */
     5077        uint8_t const idxPcReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc, kIemNativeGstRegUse_ForUpdate);
     5078
     5079        /* Perform the addition and store the result. */
     5080        off = iemNativeEmitAddGprImm(pReNative, off, idxPcReg, pReNative->Core.offPc);
     5081        off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxPcReg, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
     5082
     5083        /* Free but don't flush the PC register. */
     5084        iemNativeRegFreeTmp(pReNative, idxPcReg);
     5085# else
     5086        /* Compare the shadow with the context value, they should match. */
     5087        off = iemNativeEmitAddGprImm(pReNative, off, IEMNATIVE_REG_FIXED_PC_DBG, pReNative->Core.offPc);
     5088        off = iemNativeEmitGuestRegValueCheck(pReNative, off, IEMNATIVE_REG_FIXED_PC_DBG, kIemNativeGstReg_Pc);
     5089# endif
     5090
     5091        STAM_COUNTER_ADD(&pReNative->pVCpu->iem.s.StatNativePcUpdateDelayed, pReNative->Core.cInstrPcUpdateSkipped);
     5092        pReNative->Core.offPc                 = 0;
     5093        pReNative->Core.cInstrPcUpdateSkipped = 0;
     5094    }
     5095# if 0 /*def IEMNATIVE_WITH_TB_DEBUG_INFO*/
     5096    else
     5097    {
     5098        iemNativeDbgInfoAddNativeOffset(pReNative, off);
     5099        iemNativeDbgInfoAddDelayedPcUpdate(pReNative, pReNative->Core.offPc);
     5100    }
     5101# endif
     5102
     5103    return off;
     5104}
     5105#endif
     5106
     5107
    50135108/**
    50145109 * Flushes delayed write of a specific guest register.
     
    50235118                                                                  IEMNATIVEGSTREGREF enmClass, uint8_t idxReg)
    50245119{
     5120#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     5121    /* If for whatever reason it is possible to reference the PC register at some point we need to do the writeback here first. */
     5122#endif
    50255123    RT_NOREF(pReNative, enmClass, idxReg);
    50265124    return off;
     
    50395137DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushPendingWrites(PIEMRECOMPILERSTATE pReNative, uint32_t off)
    50405138{
    5041     RT_NOREF(pReNative, off);
     5139#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     5140    off = iemNativeEmitPcWriteback(pReNative, off);
     5141#else
     5142    RT_NOREF(pReNative);
     5143#endif
     5144
    50425145    return off;
    50435146}
     
    55415644                       uint8_t cbInstr, uint8_t cAddParams, uint64_t uParam0, uint64_t uParam1, uint64_t uParam2)
    55425645{
     5646    /* Writeback everything. */
     5647    off = iemNativeRegFlushPendingWrites(pReNative, off);
     5648
    55435649    /*
    55445650     * Flush stuff. PC and EFlags are implictly flushed, the latter because we
     
    56065712iemNativeEmitThreadedCall(PIEMRECOMPILERSTATE pReNative, uint32_t off, PCIEMTHRDEDCALLENTRY pCallEntry)
    56075713{
     5714    /* We don't know what the threaded function is doing so we must flush all pending writes. */
     5715    off = iemNativeRegFlushPendingWrites(pReNative, off);
     5716
    56085717    iemNativeRegFlushGuestShadows(pReNative, UINT64_MAX); /** @todo optimize this */
    56095718    off = iemNativeRegMoveAndFreeAndFlushAtCall(pReNative, off, 4);
     
    59256034{
    59266035    *pidxReturnLabel = UINT32_MAX;
     6036
     6037    /* Flush any pending writes before returning from the last instruction (RIP updates, etc.). */
     6038    off = iemNativeRegFlushPendingWrites(pReNative, off);
    59276039
    59286040    /*
     
    62726384#endif
    62736385
     6386    /*
     6387     * As this code can break out of the execution loop when jumping to the ReturnWithFlags label
     6388     * any pending register writes must be flushed.
     6389     */
     6390    off = iemNativeRegFlushPendingWrites(pReNative, off);
     6391
    62746392    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
    62756393                                                              kIemNativeGstRegUse_ForUpdate, false /*fNoVolatileRegs*/,
     
    63016419        RT_NOREF_PV(idxInstr);
    63026420#endif
     6421
     6422        /* As this code returns from the TB any pending register writes must be flushed. */
     6423        off = iemNativeRegFlushPendingWrites(pReNative, off);
     6424
    63036425        return iemNativeEmitJmpToNewLabel(pReNative, off, kIemNativeLabelType_ReturnBreak);
    63046426    }
     
    63206442iemNativeEmitAddToRip64AndFinishingNoFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cbInstr)
    63216443{
     6444#if !defined(IEMNATIVE_WITH_DELAYED_PC_UPDATING) || defined(IEMNATIVE_REG_FIXED_PC_DBG)
     6445# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
     6446    if (!pReNative->Core.offPc)
     6447        off = iemNativeEmitLoadGprFromVCpuU64(pReNative, off, IEMNATIVE_REG_FIXED_PC_DBG, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
     6448# endif
     6449
    63226450    /* Allocate a temporary PC register. */
    63236451    uint8_t const idxPcReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc, kIemNativeGstRegUse_ForUpdate);
     
    63296457    /* Free but don't flush the PC register. */
    63306458    iemNativeRegFreeTmp(pReNative, idxPcReg);
     6459#endif
     6460
     6461#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     6462    STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
     6463
     6464    pReNative->Core.offPc += cbInstr;
     6465# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
     6466    off = iemNativePcAdjustCheck(pReNative, off);
     6467# endif
     6468    if (pReNative->cCondDepth)
     6469        off = iemNativeEmitPcWriteback(pReNative, off);
     6470    else
     6471        pReNative->Core.cInstrPcUpdateSkipped++;
     6472#endif
    63316473
    63326474    return off;
     
    63476489iemNativeEmitAddToEip32AndFinishingNoFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cbInstr)
    63486490{
     6491#if !defined(IEMNATIVE_WITH_DELAYED_PC_UPDATING) || defined(IEMNATIVE_REG_FIXED_PC_DBG)
     6492# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
     6493    if (!pReNative->Core.offPc)
     6494        off = iemNativeEmitLoadGprFromVCpuU64(pReNative, off, IEMNATIVE_REG_FIXED_PC_DBG, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
     6495# endif
     6496
    63496497    /* Allocate a temporary PC register. */
    63506498    uint8_t const idxPcReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc, kIemNativeGstRegUse_ForUpdate);
     
    63566504    /* Free but don't flush the PC register. */
    63576505    iemNativeRegFreeTmp(pReNative, idxPcReg);
     6506#endif
     6507
     6508#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     6509    STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
     6510
     6511    pReNative->Core.offPc += cbInstr;
     6512# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
     6513    off = iemNativePcAdjustCheck(pReNative, off);
     6514# endif
     6515    if (pReNative->cCondDepth)
     6516        off = iemNativeEmitPcWriteback(pReNative, off);
     6517    else
     6518        pReNative->Core.cInstrPcUpdateSkipped++;
     6519#endif
    63586520
    63596521    return off;
     
    63746536iemNativeEmitAddToIp16AndFinishingNoFlags(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t cbInstr)
    63756537{
     6538#if !defined(IEMNATIVE_WITH_DELAYED_PC_UPDATING) || defined(IEMNATIVE_REG_FIXED_PC_DBG)
     6539# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
     6540    if (!pReNative->Core.offPc)
     6541        off = iemNativeEmitLoadGprFromVCpuU64(pReNative, off, IEMNATIVE_REG_FIXED_PC_DBG, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rip));
     6542# endif
     6543
    63766544    /* Allocate a temporary PC register. */
    63776545    uint8_t const idxPcReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc, kIemNativeGstRegUse_ForUpdate);
     
    63846552    /* Free but don't flush the PC register. */
    63856553    iemNativeRegFreeTmp(pReNative, idxPcReg);
     6554#endif
     6555
     6556#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     6557    STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
     6558
     6559    pReNative->Core.offPc += cbInstr;
     6560# if defined(IEMNATIVE_REG_FIXED_PC_DBG)
     6561    off = iemNativePcAdjustCheck(pReNative, off);
     6562# endif
     6563    if (pReNative->cCondDepth)
     6564        off = iemNativeEmitPcWriteback(pReNative, off);
     6565    else
     6566        pReNative->Core.cInstrPcUpdateSkipped++;
     6567#endif
    63866568
    63876569    return off;
     
    64396621    off = iemNativeRegFlushPendingWrites(pReNative, off);
    64406622
     6623#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     6624    Assert(pReNative->Core.offPc == 0);
     6625
     6626    STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
     6627#endif
     6628
    64416629    /* Allocate a temporary PC register. */
    64426630    uint8_t const idxPcReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc, kIemNativeGstRegUse_ForUpdate);
     
    65106698    off = iemNativeRegFlushPendingWrites(pReNative, off);
    65116699
     6700#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     6701    Assert(pReNative->Core.offPc == 0);
     6702
     6703    STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
     6704#endif
     6705
    65126706    /* Allocate a temporary PC register. */
    65136707    uint8_t const idxPcReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc, kIemNativeGstRegUse_ForUpdate);
     
    65676761    /* We speculatively modify PC and may raise #GP(0), so make sure the right values are in CPUMCTX. */
    65686762    off = iemNativeRegFlushPendingWrites(pReNative, off);
     6763
     6764#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     6765    Assert(pReNative->Core.offPc == 0);
     6766
     6767    STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
     6768#endif
    65696769
    65706770    /* Allocate a temporary PC register. */
     
    66696869    /* We speculatively modify PC and may raise #GP(0), so make sure the right values are in CPUMCTX. */
    66706870    off = iemNativeRegFlushPendingWrites(pReNative, off);
     6871
     6872#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     6873    Assert(pReNative->Core.offPc == 0);
     6874
     6875    STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativePcUpdateTotal);
     6876#endif
    66716877
    66726878    /* Get a register with the new PC loaded from idxVarPc.
     
    68157021 *          (too many nestings)
    68167022 */
    6817 DECL_INLINE_THROW(PIEMNATIVECOND) iemNativeCondPushIf(PIEMRECOMPILERSTATE pReNative)
    6818 {
     7023DECL_INLINE_THROW(PIEMNATIVECOND) iemNativeCondPushIf(PIEMRECOMPILERSTATE pReNative, uint32_t *poff)
     7024{
     7025#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     7026    *poff = iemNativeRegFlushPendingWrites(pReNative, *poff);
     7027#endif
     7028
    68197029    uint32_t const idxStack = pReNative->cCondDepth;
    68207030    AssertStmt(idxStack < RT_ELEMENTS(pReNative->aCondStack), IEMNATIVE_DO_LONGJMP(pReNative, VERR_IEM_COND_TOO_DEEPLY_NESTED));
     
    68537063#endif
    68547064
     7065#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     7066    Assert(pReNative->Core.offPc == 0);
     7067#endif
     7068
    68557069    /* Copy the initial state so we can restore it in the 'else' block. */
    68567070    pEntry->InitialState = pReNative->Core;
     
    68787092    pEntry->fInElse = true;
    68797093
     7094#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     7095    Assert(pReNative->Core.offPc == 0);
     7096#endif
     7097
    68807098    /* Snapshot the core state so we can do a merge at the endif and restore
    68817099       the snapshot we took at the start of the if-block. */
     
    68977115    Assert(pReNative->cCondDepth > 0 && pReNative->cCondDepth <= RT_ELEMENTS(pReNative->aCondStack));
    68987116    PIEMNATIVECOND const pEntry = &pReNative->aCondStack[pReNative->cCondDepth - 1];
     7117
     7118#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     7119    Assert(pReNative->Core.offPc == 0);
     7120#endif
    68997121
    69007122    /*
     
    70087230DECL_INLINE_THROW(uint32_t) iemNativeEmitIfEflagAnysBitsSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitsInEfl)
    70097231{
    7010     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7232    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    70117233
    70127234    /* Get the eflags. */
     
    70347256DECL_INLINE_THROW(uint32_t) iemNativeEmitIfEflagNoBitsSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitsInEfl)
    70357257{
    7036     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7258    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    70377259
    70387260    /* Get the eflags. */
     
    70607282DECL_INLINE_THROW(uint32_t) iemNativeEmitIfEflagsBitSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitInEfl)
    70617283{
    7062     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7284    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    70637285
    70647286    /* Get the eflags. */
     
    70897311DECL_INLINE_THROW(uint32_t) iemNativeEmitIfEflagsBitNotSet(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitInEfl)
    70907312{
    7091     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7313    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    70927314
    70937315    /* Get the eflags. */
     
    71247346                                  uint32_t fBit1InEfl, uint32_t fBit2InEfl, bool fInverted)
    71257347{
    7126     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7348    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    71277349
    71287350    /* Get the eflags. */
     
    71977419                                              uint32_t fBit1InEfl, uint32_t fBit2InEfl, bool fInverted)
    71987420{
    7199     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7421    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    72007422
    72017423    /* We need an if-block label for the non-inverted variant. */
     
    72837505DECL_INLINE_THROW(uint32_t) iemNativeEmitIfCxIsNotZero(PIEMRECOMPILERSTATE pReNative, uint32_t off)
    72847506{
    7285     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7507    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    72867508
    72877509    uint8_t const idxGstRcxReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xCX),
     
    73067528DECL_INLINE_THROW(uint32_t) iemNativeEmitIfRcxEcxIsNotZero(PIEMRECOMPILERSTATE pReNative, uint32_t off, bool f64Bit)
    73077529{
    7308     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7530    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    73097531
    73107532    uint8_t const idxGstRcxReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xCX),
     
    73257547DECL_INLINE_THROW(uint32_t) iemNativeEmitIfCxIsNotOne(PIEMRECOMPILERSTATE pReNative, uint32_t off)
    73267548{
    7327     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7549    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    73287550
    73297551    uint8_t const idxGstRcxReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xCX),
     
    73547576DECL_INLINE_THROW(uint32_t) iemNativeEmitIfRcxEcxIsNotOne(PIEMRECOMPILERSTATE pReNative, uint32_t off, bool f64Bit)
    73557577{
    7356     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7578    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    73577579
    73587580    uint8_t const idxGstRcxReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xCX),
     
    73827604iemNativeEmitIfCxIsNotOneAndTestEflagsBit(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint32_t fBitInEfl, bool fCheckIfSet)
    73837605{
    7384     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7606    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    73857607
    73867608    /* We have to load both RCX and EFLAGS before we can start branching,
     
    74437665                                               uint32_t fBitInEfl, bool fCheckIfSet, bool f64Bit)
    74447666{
    7445     PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative);
     7667    PIEMNATIVECOND const pEntry = iemNativeCondPushIf(pReNative, &off);
    74467668
    74477669    /* We have to load both RCX and EFLAGS before we can start branching,
     
    84908712                               IEMNATIVEGSTREGREF enmClass, uint8_t idxRegInClass)
    84918713{
     8714#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     8715    /** @todo If we ever gonna allow referencing the RIP register we need to update guest value here. */
     8716#endif
     8717
    84928718    /*
    84938719     * Get the offset relative to the CPUMCTX structure.
     
    85948820    iemNativeRegAssertSanity(pReNative);
    85958821#endif
     8822
     8823    /* We don't know what the called function makes use of, so flush any pending register writes. */
     8824    off = iemNativeRegFlushPendingWrites(pReNative, off);
    85968825
    85978826    /*
     
    1097811207    if ((bRmEx & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5)
    1097911208    {
     11209#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     11210        /* Need to take the current PC offset into account for the displacement, no need to flush here
     11211         * as the PC is only accessed readonly and there is no branching or calling helpers involved. */
     11212        u32Disp += pReNative->Core.offPc;
     11213#endif
     11214
    1098011215        uint8_t const idxRegRet = iemNativeVarRegisterAcquire(pReNative, idxVarRet, &off);
    1098111216        uint8_t const idxRegPc  = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_Pc,
     
    1400814243                            break;
    1400914244
     14245#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     14246                        case kIemTbDbgEntryType_DelayedPcUpdate:
     14247                            pHlp->pfnPrintf(pHlp,
     14248                                            "  Updating guest PC value by %u (cInstrSkipped=%u)\n",
     14249                                            pDbgInfo->aEntries[iDbgEntry].DelayedPcUpdate.offPc,
     14250                                            pDbgInfo->aEntries[iDbgEntry].DelayedPcUpdate.cInstrSkipped);
     14251                            continue;
     14252#endif
     14253
    1401014254                        default:
    1401114255                            AssertFailed();
  • trunk/src/VBox/VMM/VMMR3/IEMR3.cpp

    r103554 r103649  
    531531        szPat[offFlagChar] = szVal[offFlagChar] = 'S'; STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, true, szPat, "Skippable EFLAGS.SF updating percentage", "/IEM/CPU%u/re/NativeLivenessEFlagsSfSkippablePct", idCpu);
    532532        szPat[offFlagChar] = szVal[offFlagChar] = 'O'; STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, true, szPat, "Skippable EFLAGS.OF updating percentage", "/IEM/CPU%u/re/NativeLivenessEFlagsOfSkippablePct", idCpu);
     533
     534        STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativePcUpdateTotal,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Total RIP updates",   "/IEM/CPU%u/re/NativePcUpdateTotal", idCpu);
     535        STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativePcUpdateDelayed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Delayed RIP updates", "/IEM/CPU%u/re/NativePcUpdateDelayed", idCpu);
     536
     537        /* Ratio of the status bit skippables. */
     538        RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativePcUpdateTotal", idCpu);
     539        RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativePcUpdateDelayed", idCpu);
     540        STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat,
     541                               "Delayed RIP updating percentage",
     542                               "/IEM/CPU%u/re/NativePcUpdateDelayed_StatusDelayedPct", idCpu);
    533543
    534544#  endif /* VBOX_WITH_STATISTICS */
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r103592 r103649  
    8484 || defined(DOXYGEN_RUNNING)
    8585# define IEM_WITH_THROW_CATCH
     86#endif
     87
     88/** @def IEMNATIVE_WITH_DELAYED_PC_UPDATING
     89 * Enables the delayed PC updating optimization (see @bugref{10373}).
     90 */
     91#if defined(DOXYGEN_RUNNING) || 1
     92# define IEMNATIVE_WITH_DELAYED_PC_UPDATING
    8693#endif
    8794
     
    957964    /** Info about a host register shadowing a guest register. */
    958965    kIemTbDbgEntryType_GuestRegShadowing,
     966#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     967    /** Info about a delayed RIP update. */
     968    kIemTbDbgEntryType_DelayedPcUpdate,
     969#endif
    959970    kIemTbDbgEntryType_End
    960971} IEMTBDBGENTRYTYPE;
     
    10281039        uint32_t    idxHstRegPrev : 8;
    10291040    } GuestRegShadowing;
     1041
     1042#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     1043    struct
     1044    {
     1045        /* kIemTbDbgEntryType_DelayedPcUpdate. */
     1046        uint32_t    uType         : 4;
     1047        /* The instruction offset added to the program counter. */
     1048        uint32_t    offPc         : 14;
     1049        /** Number of instructions skipped. */
     1050        uint32_t    cInstrSkipped : 14;
     1051    } DelayedPcUpdate;
     1052#endif
     1053
    10301054} IEMTBDBGENTRY;
    10311055AssertCompileSize(IEMTBDBGENTRY, sizeof(uint32_t));
     
    18431867    STAMCOUNTER             StatNativeLivenessEflOfDelayable;
    18441868
    1845     uint64_t                au64Padding[3];
     1869    /** Native recompiler: Number of potential PC updates in total. */
     1870    STAMCOUNTER             StatNativePcUpdateTotal;
     1871    /** Native recompiler: Number of PC updates which could be delayed. */
     1872    STAMCOUNTER             StatNativePcUpdateDelayed;
     1873
     1874
     1875    uint64_t                u64Padding;
    18461876    /** @} */
    18471877
     
    36443674FNIEMAIMPLMEDIAPSHUFU128 iemAImpl_vpsrlq_imm_u128, iemAImpl_vpsrlq_imm_u128_fallback;
    36453675FNIEMAIMPLMEDIAPSHUFU256 iemAImpl_vpsrlq_imm_u256, iemAImpl_vpsrlq_imm_u256_fallback;
     3676FNIEMAIMPLMEDIAPSHUFU128 iemAImpl_vpsrldq_imm_u128, iemAImpl_vpsrldq_imm_u128_fallback;
     3677FNIEMAIMPLMEDIAPSHUFU256 iemAImpl_vpsrldq_imm_u256, iemAImpl_vpsrldq_imm_u256_fallback;
    36463678
    36473679FNIEMAIMPLMEDIAOPTF3U128     iemAImpl_vpermilps_u128,     iemAImpl_vpermilps_u128_fallback;
  • trunk/src/VBox/VMM/include/IEMN8veRecompiler.h

    r103622 r103649  
    169169# define IEMNATIVE_REG_FIXED_PCPUMCTX       ARMV8_A64_REG_X27
    170170# define IEMNATIVE_REG_FIXED_TMP0           ARMV8_A64_REG_X15
     171# if defined(IEMNATIVE_WITH_DELAYED_PC_UPDATING) && 0 /* debug the updating with a shadow RIP. */
     172#   define IEMNATIVE_REG_FIXED_TMP1         ARMV8_A64_REG_X16
     173#   define IEMNATIVE_REG_FIXED_PC_DBG       ARMV8_A64_REG_X26
     174#   define IEMNATIVE_REG_FIXED_MASK_ADD     (  RT_BIT_32(IEMNATIVE_REG_FIXED_TMP1) \
     175                                             | RT_BIT_32(IEMNATIVE_REG_FIXED_PC_DBG))
     176# else
     177#   define IEMNATIVE_REG_FIXED_MASK_ADD     0
     178# endif
    171179# define IEMNATIVE_REG_FIXED_MASK           (  RT_BIT_32(ARMV8_A64_REG_SP) \
    172180                                             | RT_BIT_32(ARMV8_A64_REG_LR) \
     
    175183                                             | RT_BIT_32(IEMNATIVE_REG_FIXED_PCPUMCTX) \
    176184                                             | RT_BIT_32(ARMV8_A64_REG_X18) \
    177                                              | RT_BIT_32(IEMNATIVE_REG_FIXED_TMP0) )
     185                                             | RT_BIT_32(IEMNATIVE_REG_FIXED_TMP0) \
     186                                             | IEMNATIVE_REG_FIXED_MASK_ADD)
    178187
    179188#else
     
    851860    /** Fixed temporary register. */
    852861    kIemNativeWhat_FixedTmp,
     862#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     863    /** Shadow RIP for the delayed RIP updating debugging. */
     864    kIemNativeWhat_PcShadow,
     865#endif
    853866    /** Register reserved by the CPU or OS architecture. */
    854867    kIemNativeWhat_FixedReserved,
     
    899912typedef struct IEMNATIVECORESTATE
    900913{
     914#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
     915    /** The current instruction offset in bytes from when the guest program counter
     916     * was updated last. Used for delaying the write to the guest context program counter
     917     * as long as possible. */
     918    uint32_t                    offPc;
     919    /** Number of instructions where we could skip the updating. */
     920    uint32_t                    cInstrPcUpdateSkipped;
     921#endif
    901922    /** Allocation bitmap for aHstRegs. */
    902923    uint32_t                    bmHstRegs;
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