VirtualBox

Changeset 104034 in vbox for trunk


Ignore:
Timestamp:
Mar 25, 2024 10:07:26 AM (12 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
162423
Message:

VMM/IEM: Implement experimental (disabled by default) delaying writeback of dirty guest registers (for GPRs only at the moment), bugref:10629

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h

    r104021 r104034  
    112112#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
    113113    /* If for whatever reason it is possible to reference the PC register at some point we need to do the writeback here first. */
     114#endif
     115
     116#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     117#if 0 /** @todo r=aeichner EFLAGS writeback delay. */
     118    if (   enmClass == kIemNativeGstRegRef_EFlags
     119        && pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(kIemNativeGstReg_EFlags))
     120        off = iemNativeRegFlushPendingWrite(pReNative, off, kIemNativeGstReg_EFlags);
     121#else
     122    Assert(!(pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(kIemNativeGstReg_EFlags)));
     123#endif
     124
     125    if (   enmClass == kIemNativeGstRegRef_Gpr
     126        && pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(idxReg))
     127        off = iemNativeRegFlushPendingWrite(pReNative, off, IEMNATIVEGSTREG_GPR(idxReg));
    114128#endif
    115129
     
    12911305    Assert(!pEntry->fInElse);
    12921306
     1307#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     1308    /* Writeback any dirty shadow registers. */
     1309    /** @todo r=aeichner Possible optimization is to only writeback guest registers which became dirty
     1310     *                   in one of the branches and leave guest registers already dirty before the start of the if
     1311     *                   block alone. */
     1312    off = iemNativeRegFlushDirtyGuest(pReNative, off);
     1313#endif
     1314
    12931315    /* Jump to the endif */
    12941316    off = iemNativeEmitJmpToLabel(pReNative, off, pEntry->idxLabelEndIf);
     
    13241346#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
    13251347    Assert(pReNative->Core.offPc == 0);
     1348#endif
     1349#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     1350    /* Writeback any dirty shadow registers (else branch). */
     1351    /** @todo r=aeichner Possible optimization is to only writeback guest registers which became dirty
     1352     *                   in one of the branches and leave guest registers already dirty before the start of the if
     1353     *                   block alone. */
     1354    off = iemNativeRegFlushDirtyGuest(pReNative, off);
    13261355#endif
    13271356
     
    13351364     *        But we'd need more info about future for that to be worth the effort. */
    13361365    PCIEMNATIVECORESTATE const pOther = pEntry->fInElse ? &pEntry->IfFinalState : &pEntry->InitialState;
     1366#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     1367    Assert(   pOther->bmGstRegShadowDirty == 0
     1368           && pReNative->Core.bmGstRegShadowDirty == 0);
     1369#endif
     1370
    13371371    if (memcmp(&pReNative->Core, pOther, sizeof(*pOther)) != 0)
    13381372    {
     
    13531387                    Log12(("iemNativeEmitEndIf: dropping gst %s from hst %s\n",
    13541388                           g_aGstShadowInfo[idxGstReg].pszName, g_apszIemNativeHstRegNames[idxHstReg]));
     1389
     1390#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     1391                    /* Writeback any dirty shadow registers we are about to unshadow. */
     1392                    off = iemNativeRegFlushDirtyGuestByHostRegShadow(pReNative, off, idxHstReg);
     1393#endif
    13551394                    iemNativeRegClearGstRegShadowing(pReNative, idxHstReg, off);
    13561395                }
     
    13581397        }
    13591398        else
     1399        {
    13601400            Assert(pReNative->Core.bmHstRegsWithGstShadow == 0);
     1401#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     1402            Assert(pReNative->Core.bmGstRegShadowDirty == 0);
     1403#endif
     1404        }
    13611405
    13621406        /* Check variables next. For now we must require them to be identical
     
    28222866    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    28232867
     2868#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    28242869    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGRegEx & 15]));
     2870#endif
    28252871
    28262872    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
     
    29182964    iemNativeVarRegisterRelease(pReNative, idxValueVar);
    29192965
     2966#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    29202967    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGRegEx & 15]));
     2968#endif
    29212969    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
    29222970    return off;
     
    29563004    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    29573005
     3006#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    29583007    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3008#endif
    29593009    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
    29603010    return off;
     
    30243074    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    30253075
     3076#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    30263077    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3078#endif
    30273079    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
    30283080    return off;
     
    30413093                                                                 kIemNativeGstRegUse_ForFullWrite);
    30423094    off = iemNativeEmitLoadGprImm64(pReNative, off, idxGstTmpReg, uValue);
     3095#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    30433096    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3097#endif
    30443098    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
    30453099    return off;
     
    30763130     */
    30773131    uint8_t const idxVarReg = iemNativeVarRegisterAcquireForGuestReg(pReNative, idxValueVar, IEMNATIVEGSTREG_GPR(iGReg), &off);
     3132#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    30783133    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxVarReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3134#endif
    30793135#ifdef VBOX_STRICT
    30803136    off = iemNativeEmitTop32BitsClearCheck(pReNative, off, idxVarReg);
     
    30963152                                                                 kIemNativeGstRegUse_ForFullWrite);
    30973153    off = iemNativeEmitLoadGprImm64(pReNative, off, idxGstTmpReg, uValue);
     3154#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    30983155    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3156#endif
    30993157    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
    31003158    return off;
     
    31313189     */
    31323190    uint8_t const idxVarReg = iemNativeVarRegisterAcquireForGuestReg(pReNative, idxValueVar, IEMNATIVEGSTREG_GPR(iGReg), &off);
     3191#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    31333192    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxVarReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3193#else
     3194    RT_NOREF(idxVarReg);
     3195#endif
    31343196    iemNativeVarRegisterRelease(pReNative, idxValueVar);
    31353197    return off;
     
    31483210                                                                 kIemNativeGstRegUse_ForUpdate);
    31493211    off = iemNativeEmitLoadGprFromGpr32(pReNative, off, idxGstTmpReg, idxGstTmpReg);
     3212#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    31503213    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3214#endif
    31513215    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
    31523216    return off;
     
    32013265    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    32023266
     3267#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    32033268    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3269#endif
    32043270
    32053271    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
     
    32573323    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    32583324
     3325#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    32593326    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3327#endif
    32603328
    32613329    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
     
    33083376    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    33093377
     3378#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    33103379    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3380#endif
    33113381
    33123382    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
     
    33643434    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    33653435
     3436#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    33663437    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3438#endif
    33673439
    33683440    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
     
    34203492    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    34213493
     3494#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    34223495    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3496#endif
    34233497
    34243498    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
     
    34723546    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    34733547
     3548#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    34743549    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxGstTmpReg, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[iGReg]));
     3550#endif
    34753551
    34763552    iemNativeRegFreeTmp(pReNative, idxGstTmpReg);
     
    61956271#endif /* IEMNATIVE_WITH_TLB_LOOKUP */
    61966272
     6273#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    61976274    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxRegRsp, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.rsp));
     6275#endif
    61986276    iemNativeRegFreeTmp(pReNative, idxRegRsp);
    61996277    if (idxRegEffSp != idxRegRsp)
     
    64966574#endif
    64976575            iemNativeRegClearAndMarkAsGstRegShadow(pReNative, idxRegMemResult,  IEMNATIVEGSTREG_GPR(idxGReg), off);
     6576#if defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
     6577            pReNative->Core.bmGstRegShadowDirty |= RT_BIT_64(idxGReg);
     6578#endif
     6579#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    64986580            off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxRegMemResult,
    64996581                                                 RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[idxGReg]));
     6582#endif
    65006583        }
    65016584        else
     
    65056588                                                                      kIemNativeGstRegUse_ForUpdate);
    65066589            off = iemNativeEmitGprMergeInGpr16(pReNative, off, idxRegDst, idxRegMemResult);
     6590#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    65076591            off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxRegDst, RT_UOFFSETOF_DYN(VMCPU, cpum.GstCtx.aGRegs[idxGReg]));
     6592#endif
    65086593            iemNativeRegFreeTmp(pReNative, idxRegDst);
    65096594        }
     
    65376622        }
    65386623    }
     6624
     6625#if !defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    65396626    off = iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxRegRsp, RT_UOFFSETOF(VMCPU, cpum.GstCtx.rsp));
     6627#endif
    65406628
    65416629    iemNativeRegFreeTmp(pReNative, idxRegRsp);
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp

    r104033 r104034  
    32573257    pReNative->Core.bmHstRegsWithGstShadow = 0;
    32583258    pReNative->Core.bmGstRegShadows        = 0;
     3259#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     3260    pReNative->Core.bmGstRegShadowDirty    = 0;
     3261#endif
    32593262    pReNative->Core.bmVars                 = 0;
    32603263    pReNative->Core.bmStack                = 0;
     
    37923795    PIEMTBDBGENTRY const pEntry = iemNativeDbgInfoAddNewEntry(pReNative, pReNative->pDbgInfo);
    37933796    pEntry->GuestRegShadowing.uType         = kIemTbDbgEntryType_GuestRegShadowing;
     3797#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     3798    pEntry->GuestRegShadowing.fDirty        = (pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(enmGstReg)) ? 1 : 0;
     3799#endif
    37943800    pEntry->GuestRegShadowing.uUnused       = 0;
    37953801    pEntry->GuestRegShadowing.idxGstReg     = enmGstReg;
    37963802    pEntry->GuestRegShadowing.idxHstReg     = idxHstReg;
    37973803    pEntry->GuestRegShadowing.idxHstRegPrev = idxHstRegPrev;
     3804#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     3805    Assert(   idxHstReg != UINT8_MAX
     3806           || !(pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(enmGstReg)));
     3807#endif
    37983808}
    37993809
     
    40224032
    40234033
     4034#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     4035/**
     4036 * Stores the host reg @a idxHstReg into guest shadow register @a enmGstReg.
     4037 *
     4038 * @returns New code buffer offset on success, UINT32_MAX on failure.
     4039 * @param   pReNative   .
     4040 * @param   off         The current code buffer position.
     4041 * @param   enmGstReg   The guest register to store to.
     4042 * @param   idxHstReg   The host register to store from.
     4043 */
     4044DECL_FORCE_INLINE_THROW(uint32_t)
     4045iemNativeEmitStoreGprWithGstShadowReg(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVEGSTREG enmGstReg, uint8_t idxHstReg)
     4046{
     4047    Assert((unsigned)enmGstReg < (unsigned)kIemNativeGstReg_End);
     4048    Assert(g_aGstShadowInfo[enmGstReg].cb != 0);
     4049
     4050    switch (g_aGstShadowInfo[enmGstReg].cb)
     4051    {
     4052        case sizeof(uint64_t):
     4053            return iemNativeEmitStoreGprToVCpuU64(pReNative, off, idxHstReg, g_aGstShadowInfo[enmGstReg].off);
     4054        case sizeof(uint32_t):
     4055            return iemNativeEmitStoreGprToVCpuU32(pReNative, off, idxHstReg, g_aGstShadowInfo[enmGstReg].off);
     4056        case sizeof(uint16_t):
     4057            return iemNativeEmitStoreGprToVCpuU16(pReNative, off, idxHstReg, g_aGstShadowInfo[enmGstReg].off);
     4058#if 0 /* not present in the table. */
     4059        case sizeof(uint8_t):
     4060            return iemNativeEmitStoreGprToVCpuU8(pReNative, off, idxHstReg, g_aGstShadowInfo[enmGstReg].off);
     4061#endif
     4062        default:
     4063            AssertFailedStmt(IEMNATIVE_DO_LONGJMP(pReNative, VERR_IPE_NOT_REACHED_DEFAULT_CASE));
     4064    }
     4065}
     4066
     4067
     4068/**
     4069 * Emits code to flush a pending write of the given guest register if any.
     4070 *
     4071 * @returns New code buffer offset.
     4072 * @param   pReNative       The native recompile state.
     4073 * @param   off             Current code buffer position.
     4074 * @param   enmGstReg       The guest register to flush.
     4075 */
     4076DECL_HIDDEN_THROW(uint32_t)
     4077iemNativeRegFlushPendingWrite(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVEGSTREG enmGstReg)
     4078{
     4079    uint8_t const idxHstReg = pReNative->Core.aidxGstRegShadows[enmGstReg];
     4080
     4081    Assert(enmGstReg >= kIemNativeGstReg_GprFirst && enmGstReg <= kIemNativeGstReg_GprLast);
     4082    Assert(   idxHstReg != UINT8_MAX
     4083           && pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(enmGstReg));
     4084    Log12(("iemNativeRegFlushPendingWrite: Clearing guest register %s shadowed by host %s\n",
     4085           g_aGstShadowInfo[enmGstReg].pszName, g_apszIemNativeHstRegNames[idxHstReg]));
     4086
     4087    off = iemNativeEmitStoreGprWithGstShadowReg(pReNative, off, enmGstReg, idxHstReg);
     4088
     4089    pReNative->Core.bmGstRegShadowDirty &= ~RT_BIT_64(enmGstReg);
     4090    return off;
     4091}
     4092
     4093
     4094/**
     4095 * Flush the given set of guest registers if marked as dirty.
     4096 *
     4097 * @returns New code buffer offset.
     4098 * @param   pReNative       The native recompile state.
     4099 * @param   off             Current code buffer position.
     4100 * @param   fFlushGstReg    The guest register set to flush (default is flush everything).
     4101 */
     4102DECL_HIDDEN_THROW(uint32_t)
     4103iemNativeRegFlushDirtyGuest(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint64_t fFlushGstReg /*= UINT64_MAX*/)
     4104{
     4105    if (pReNative->Core.bmGstRegShadowDirty & fFlushGstReg)
     4106    {
     4107        uint64_t bmGstRegShadowDirty = pReNative->Core.bmGstRegShadowDirty & fFlushGstReg;
     4108        uint32_t idxGstReg = 0;
     4109
     4110        do
     4111        {
     4112            if (bmGstRegShadowDirty & 0x1)
     4113            {
     4114                off = iemNativeRegFlushPendingWrite(pReNative, off, (IEMNATIVEGSTREG)idxGstReg);
     4115                Assert(!(pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(idxGstReg)));
     4116            }
     4117            idxGstReg++;
     4118            bmGstRegShadowDirty >>= 1;
     4119        } while (bmGstRegShadowDirty);
     4120    }
     4121
     4122    return off;
     4123}
     4124
     4125
     4126/**
     4127 * Flush all shadowed guest registers marked as dirty for the given host register.
     4128 *
     4129 * @returns New code buffer offset.
     4130 * @param   pReNative       The native recompile state.
     4131 * @param   off             Current code buffer position.
     4132 * @param   idxHstReg       The host register.
     4133 *
     4134 * @note This doesn't do any unshadowing of guest registers from the host register.
     4135 */
     4136DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushDirtyGuestByHostRegShadow(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxHstReg)
     4137{
     4138    /* We need to flush any pending guest register writes this host register shadows. */
     4139    uint64_t fGstRegShadows = pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows;
     4140    if (pReNative->Core.bmGstRegShadowDirty & fGstRegShadows)
     4141    {
     4142        uint64_t bmGstRegShadowDirty = pReNative->Core.bmGstRegShadowDirty & fGstRegShadows;
     4143        uint32_t idxGstReg = 0;
     4144        do
     4145        {
     4146            if (bmGstRegShadowDirty & 0x1)
     4147            {
     4148                off = iemNativeRegFlushPendingWrite(pReNative, off, (IEMNATIVEGSTREG)idxGstReg);
     4149                Assert(!(pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(idxGstReg)));
     4150            }
     4151            idxGstReg++;
     4152            bmGstRegShadowDirty >>= 1;
     4153        } while (bmGstRegShadowDirty);
     4154    }
     4155
     4156    return off;
     4157}
     4158#endif
     4159
     4160
    40244161/**
    40254162 * Locate a register, possibly freeing one up.
     
    40894226            if (pReNative->Core.bmGstRegShadows & fToFreeMask)
    40904227            {
     4228#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     4229                /* Writeback any dirty shadow registers we are about to unshadow. */
     4230                *poff = iemNativeRegFlushDirtyGuest(pReNative, *poff, fToFreeMask);
     4231#endif
     4232
    40914233                STAM_COUNTER_INC(&pReNative->pVCpu->iem.s.StatNativeRegFindFreeLivenessUnshadowed);
    40924234                iemNativeRegFlushGuestShadows(pReNative, fToFreeMask);
     
    41194261        Assert(pReNative->Core.bmHstRegsWithGstShadow & RT_BIT_32(idxReg));
    41204262
     4263#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     4264        /* We need to flush any pending guest register writes this host register shadows. */
     4265        *poff = iemNativeRegFlushDirtyGuestByHostRegShadow(pReNative, *poff, idxReg);
     4266#endif
     4267
    41214268        pReNative->Core.bmHstRegsWithGstShadow &= ~RT_BIT_32(idxReg);
    41224269        pReNative->Core.bmGstRegShadows        &= ~pReNative->Core.aHstRegs[idxReg].fGstRegShadows;
     
    41574304                Assert(   RT_BOOL(pReNative->Core.bmHstRegsWithGstShadow & RT_BIT_32(idxReg))
    41584305                       == RT_BOOL(pReNative->Core.aHstRegs[idxReg].fGstRegShadows));
     4306#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     4307                Assert(!(pReNative->Core.aHstRegs[idxReg].fGstRegShadows & pReNative->Core.bmGstRegShadowDirty));
     4308#endif
    41594309
    41604310                if (pReNative->Core.aVars[idxVar].enmKind == kIemNativeVarKind_Stack)
     
    42044354
    42054355    uint64_t fGstRegShadows = pReNative->Core.aHstRegs[idxRegOld].fGstRegShadows;
     4356#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     4357    Assert(!(fGstRegShadows & pReNative->Core.bmGstRegShadowDirty));
     4358#endif
    42064359    Log12(("%s: moving idxVar=%#x from %s to %s (fGstRegShadows=%RX64)\n",
    42074360           pszCaller, idxVar, g_apszIemNativeHstRegNames[idxRegOld], g_apszIemNativeHstRegNames[idxRegNew], fGstRegShadows));
     
    42624415    Assert(   RT_BOOL(pReNative->Core.bmHstRegsWithGstShadow & RT_BIT_32(idxRegOld))
    42634416           == RT_BOOL(pReNative->Core.aHstRegs[idxRegOld].fGstRegShadows));
     4417#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     4418    Assert(!(pReNative->Core.aHstRegs[idxRegOld].fGstRegShadows & pReNative->Core.bmGstRegShadowDirty));
     4419#endif
    42644420
    42654421
     
    44794635                            ? IEMNATIVE_HST_GREG_MASK & ~IEMNATIVE_REG_FIXED_MASK
    44804636                            : IEMNATIVE_HST_GREG_MASK & ~IEMNATIVE_REG_FIXED_MASK & ~IEMNATIVE_CALL_VOLATILE_GREG_MASK;
     4637
     4638#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     4639    /** @todo r=aeichner Implement for registers other than GPR as well. */
     4640    if (   (   enmIntendedUse == kIemNativeGstRegUse_ForFullWrite
     4641            || enmIntendedUse == kIemNativeGstRegUse_ForUpdate)
     4642        && enmGstReg >= kIemNativeGstReg_GprFirst
     4643        && enmGstReg <= kIemNativeGstReg_GprLast
     4644        )
     4645        pReNative->Core.bmGstRegShadowDirty |= RT_BIT_64(enmGstReg);
     4646#endif
    44814647
    44824648    /*
     
    47634929                Assert(   (pReNative->Core.aHstRegs[idxReg].fGstRegShadows & pReNative->Core.bmGstRegShadows)
    47644930                       == pReNative->Core.aHstRegs[idxReg].fGstRegShadows);
     4931#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     4932                Assert(!(pReNative->Core.aHstRegs[idxReg].fGstRegShadows & pReNative->Core.bmGstRegShadowDirty));
     4933#endif
    47654934                pReNative->Core.bmHstRegsWithGstShadow &= ~RT_BIT_32(idxReg);
    47664935                pReNative->Core.bmGstRegShadows        &= ~pReNative->Core.aHstRegs[idxReg].fGstRegShadows;
     
    48695038        pReNative->Core.bmHstRegsWithGstShadow &= ~RT_BIT_32(idxHstReg);
    48705039        uint64_t const fGstRegShadowsOld        = pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows;
     5040#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     5041        Assert(!(pReNative->Core.bmGstRegShadowDirty & fGstRegShadowsOld));
     5042#endif
    48715043        pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows = 0;
    48725044        pReNative->Core.bmGstRegShadows        &= ~fGstRegShadowsOld;
     
    50615233
    50625234            AssertMsg(pReNative->Core.aHstRegs[idxReg].fGstRegShadows != 0, ("idxReg=%#x\n", idxReg));
     5235#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     5236            Assert(!(pReNative->Core.bmGstRegShadowDirty & pReNative->Core.aHstRegs[idxReg].fGstRegShadows));
     5237#endif
    50635238            pReNative->Core.bmGstRegShadows &= ~pReNative->Core.aHstRegs[idxReg].fGstRegShadows;
    50645239            pReNative->Core.aHstRegs[idxReg].fGstRegShadows = 0;
     
    51035278                Assert(pReNative->Core.bmHstRegsWithGstShadow & RT_BIT_32(idxHstReg));
    51045279                Assert(pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows & RT_BIT_64(idxGstReg));
     5280#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     5281                Assert(!(pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(idxGstReg)));
     5282#endif
    51055283
    51065284                uint64_t const fInThisHstReg = (pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows & fGstRegs) | RT_BIT_64(idxGstReg);
     
    51245302                Assert(pReNative->Core.bmHstRegsWithGstShadow & RT_BIT_32(idxHstReg));
    51255303                Assert(pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows & RT_BIT_64(idxGstReg));
     5304#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     5305                Assert(!(pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(idxGstReg)));
     5306#endif
    51265307
    51275308                fGstRegs &= ~(pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows | RT_BIT_64(idxGstReg));
     
    51695350                Assert(   (pReNative->Core.bmGstRegShadows & pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows)
    51705351                       == pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows);
     5352#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     5353                Assert(!(pReNative->Core.bmGstRegShadowDirty & pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows));
     5354#endif
    51715355
    51725356                fGstShadows |= pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows;
     
    51875371                Assert(   (pReNative->Core.bmGstRegShadows & pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows)
    51885372                       == pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows);
     5373#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     5374                Assert(!(pReNative->Core.bmGstRegShadowDirty & pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows));
     5375#endif
    51895376
    51905377                pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows = 0;
     
    52295416
    52305417            uint64_t const fGstRegShadows = pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows;
     5418#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     5419            Assert(!(pReNative->Core.bmGstRegShadowDirty & fGstRegShadows));
     5420#endif
    52315421            Assert((pReNative->Core.bmGstRegShadows & fGstRegShadows) == fGstRegShadows);
    52325422            AssertStmt(fGstRegShadows != 0 && fGstRegShadows < RT_BIT_64(kIemNativeGstReg_End),
     
    60346224#endif
    60356225
     6226#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     6227    off = iemNativeRegFlushDirtyGuest(pReNative, off, ~fGstShwExcept);
     6228    if (   fFlushShadows
     6229        && (pReNative->Core.bmGstRegShadows & ~fGstShwExcept))
     6230    {
     6231        uint64_t bmGstRegShadows = pReNative->Core.bmGstRegShadows & ~fGstShwExcept;
     6232        uint8_t idxGstReg = 0;
     6233        do
     6234        {
     6235            if (bmGstRegShadows & 0x1)
     6236            {
     6237                uint8_t const idxHstReg = pReNative->Core.aidxGstRegShadows[idxGstReg];
     6238
     6239                iemNativeRegClearGstRegShadowing(pReNative, idxHstReg, off);
     6240                iemNativeRegFlushGuestShadows(pReNative, RT_BIT_64(idxGstReg));
     6241            }
     6242            idxGstReg++;
     6243            bmGstRegShadows >>= 1;
     6244        } while (bmGstRegShadows);
     6245    }
     6246#endif
     6247
    60366248#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
    60376249    /** @todo r=bird: There must be a quicker way to check if anything needs
     
    62486460iemNativeEmitGuestRegValueCheck(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxReg, IEMNATIVEGSTREG enmGstReg)
    62496461{
     6462#if defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
     6463    /* We can't check the value against whats in CPUMCTX if the register is already marked as dirty, so skip the check. */
     6464    if (pReNative->Core.bmGstRegShadowDirty & RT_BIT_64(enmGstReg))
     6465        return off;
     6466#endif
     6467
    62506468# ifdef RT_ARCH_AMD64
    62516469    uint8_t * const pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 32);
     
    76207838    {
    76217839        idxReg = g_aidxIemNativeCallRegs[uArgNo];
     7840
     7841#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     7842        /* Writeback any dirty shadow registers we are about to unshadow. */
     7843        *poff = iemNativeRegFlushDirtyGuestByHostRegShadow(pReNative, *poff, idxReg);
     7844#endif
     7845
    76227846        iemNativeRegClearGstRegShadowing(pReNative, idxReg, *poff);
    76237847        Log11(("iemNativeVarRegisterAcquire: idxVar=%#x idxReg=%u (matching arg %u)\n", idxVar, idxReg, uArgNo));
     
    78658089    if (idxReg < RT_ELEMENTS(pReNative->Core.aHstRegs))
    78668090    {
     8091#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     8092        if (enmGstReg >= kIemNativeGstReg_GprFirst && enmGstReg <= kIemNativeGstReg_GprLast)
     8093            pReNative->Core.bmGstRegShadowDirty |= RT_BIT_64(enmGstReg);
     8094#endif
     8095
    78678096        if (pReNative->Core.bmGstRegShadows & RT_BIT_64(enmGstReg))
    78688097        {
     
    92179446                            const char * const    pszGstReg = g_aGstShadowInfo[pEntry->GuestRegShadowing.idxGstReg].pszName;
    92189447                            if (pEntry->GuestRegShadowing.idxHstReg == UINT8_MAX)
    9219                                 pHlp->pfnPrintf(pHlp, "  Guest register %s != host register %s\n", pszGstReg,
    9220                                                 g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstRegPrev]);
     9448                                pHlp->pfnPrintf(pHlp, "  Guest register %s != host register %s (Dirty: %RTbool)\n", pszGstReg,
     9449                                                g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstRegPrev],
     9450                                                RT_BOOL(pEntry->GuestRegShadowing.fDirty));
    92219451                            else if (pEntry->GuestRegShadowing.idxHstRegPrev == UINT8_MAX)
    9222                                 pHlp->pfnPrintf(pHlp, "  Guest register %s == host register %s\n", pszGstReg,
    9223                                                 g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstReg]);
     9452                                pHlp->pfnPrintf(pHlp, "  Guest register %s == host register %s (Dirty: %RTbool)\n", pszGstReg,
     9453                                                g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstReg],
     9454                                                RT_BOOL(pEntry->GuestRegShadowing.fDirty));
    92249455                            else
    9225                                 pHlp->pfnPrintf(pHlp, "  Guest register %s == host register %s (previously in %s)\n", pszGstReg,
     9456                                pHlp->pfnPrintf(pHlp, "  Guest register %s == host register %s (previously in %s, Dirty: %RTbool)\n", pszGstReg,
    92269457                                                g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstReg],
    9227                                                 g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstRegPrev]);
     9458                                                g_apszIemNativeHstRegNames[pEntry->GuestRegShadowing.idxHstRegPrev],
     9459                                                RT_BOOL(pEntry->GuestRegShadowing.fDirty));
    92289460                            continue;
    92299461                        }
  • trunk/src/VBox/VMM/include/IEMInternal.h

    r104019 r104034  
    10501050        /* kIemTbDbgEntryType_GuestRegShadowing. */
    10511051        uint32_t    uType         : 4;
    1052         uint32_t    uUnused       : 4;
     1052        /** Flag whether the register is marked as dirty. */
     1053        uint32_t    fDirty        : 1;
     1054        uint32_t    uUnused       : 3;
    10531055        /** The guest register being shadowed (IEMNATIVEGSTREG). */
    10541056        uint32_t    idxGstReg     : 8;
  • trunk/src/VBox/VMM/include/IEMN8veRecompiler.h

    r104021 r104034  
    7070#endif
    7171
     72/** @def IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     73 * Delay the writeback or dirty registers as long as possible. */
     74#ifdef DEBUG_aeichner
     75# define IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     76#endif
    7277
    7378/** @name Stack Frame Layout
     
    11371142    /** Bitmap marking valid entries in aidxGstRegShadows. */
    11381143    uint64_t                    bmGstRegShadows;
     1144#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     1145    /** Bitmap marking the shadowed guest register as dirty and needing writeback when flushing. */
     1146    uint64_t                    bmGstRegShadowDirty;
     1147#endif
    11391148
    11401149#ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     
    15481557#ifdef IEMNATIVE_WITH_DELAYED_PC_UPDATING
    15491558DECL_HIDDEN_THROW(uint32_t) iemNativeEmitPcWritebackSlow(PIEMRECOMPILERSTATE pReNative, uint32_t off);
     1559#endif
     1560#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     1561DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushPendingWrite(PIEMRECOMPILERSTATE pReNative, uint32_t off, IEMNATIVEGSTREG enmGstReg);
     1562DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushDirtyGuest(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint64_t fFlushGstReg = UINT64_MAX);
     1563DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushDirtyGuestByHostRegShadow(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxHstReg);
    15501564#endif
    15511565
     
    21102124    Assert(   RT_BOOL(pReNative->Core.bmHstRegsWithGstShadow & RT_BIT_32(idxHstReg))
    21112125           == RT_BOOL(pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows));
     2126#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     2127    Assert(!(pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows & pReNative->Core.bmGstRegShadowDirty));
     2128#endif
    21122129
    21132130#ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     
    21482165    Assert(pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows & RT_BIT_64(enmGstReg));
    21492166    Assert(pReNative->Core.bmHstRegsWithGstShadow             & RT_BIT_32(idxHstReg));
     2167#ifdef IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK
     2168    Assert(!(pReNative->Core.aHstRegs[idxHstReg].fGstRegShadows & pReNative->Core.bmGstRegShadowDirty));
     2169#endif
    21502170
    21512171#ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     
    22642284#endif
    22652285
    2266 #ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
     2286#if defined(IEMNATIVE_WITH_SIMD_REG_ALLOCATOR) || defined(IEMNATIVE_WITH_DELAYED_REGISTER_WRITEBACK)
    22672287    /** @todo r=bird: There must be a quicker way to check if anything needs doing here!  */
    22682288    /** @todo This doesn't mix well with fGstShwExcept but we ignore this for now and just flush everything. */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette