VirtualBox

Changeset 106197 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Oct 1, 2024 3:35:13 PM (6 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
164981
Message:

VMM/IEM: Use iemNativeEmitEFlagsForLogical as emitter for all cases. bugref:10720

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

Legend:

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

    r106192 r106197  
    31053105 * @param   off             Current code buffer position.
    31063106 * @param   fFlushGstReg    The guest register set to flush (default is flush everything).
     3107 * @note    Must not modify the host status flags!
    31073108 */
    31083109DECL_HIDDEN_THROW(uint32_t)
     
    31373138 * @param   idxHstReg       The host register.
    31383139 *
    3139  * @note This doesn't do any unshadowing of guest registers from the host register.
     3140 * @note    This doesn't do any unshadowing of guest registers from the host register.
     3141 *
     3142 * @note    Must not modify the host status flags!
    31403143 */
    31413144DECL_HIDDEN_THROW(uint32_t) iemNativeRegFlushDirtyGuestByHostRegShadow(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxHstReg)
     
    31783181 *          recording debug info.  Does NOT throw anything if we're out of
    31793182 *          registers, though.
     3183 *
     3184 * @note    Must not modify the host status flags!
    31803185 */
    31813186static uint8_t iemNativeRegAllocFindFree(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, bool fPreferVolatile,
     
    34703475 *                          registers (@c true, default) or the other way around
    34713476 *                          (@c false, for iemNativeRegAllocTmpForGuestReg()).
     3477 *
     3478 * @note    Must not modify the host status flags!
    34723479 */
    34733480DECL_HIDDEN_THROW(uint8_t) iemNativeRegAllocTmp(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, bool fPreferVolatile /*= true*/)
     
    73217328 *
    73227329 * @returns The host register number.
    7323  * @param   pReNative   The recompiler state.
    7324  * @param   idxVar      The variable.
    7325  * @param   poff        Pointer to the instruction buffer offset.
    7326  *                      In case a register needs to be freed up or the value
    7327  *                      loaded off the stack.
    7328  * @param  fInitialized Set if the variable must already have been initialized.
    7329  *                      Will throw VERR_IEM_VAR_NOT_INITIALIZED if this is not
    7330  *                      the case.
    7331  * @param  idxRegPref   Preferred register number or UINT8_MAX.
     7330 * @param   pReNative       The recompiler state.
     7331 * @param   idxVar          The variable.
     7332 * @param   poff            Pointer to the instruction buffer offset.
     7333 *                          In case a register needs to be freed up or the value
     7334 *                          loaded off the stack.
     7335 * @param   fInitialized    Set if the variable must already have been
     7336 *                          initialized. Will throw VERR_IEM_VAR_NOT_INITIALIZED
     7337 *                          if this is not the case.
     7338 * @param   idxRegPref      Preferred register number or UINT8_MAX.
     7339 *
     7340 * @note    Must not modify the host status flags!
    73327341 */
    73337342DECL_HIDDEN_THROW(uint8_t) iemNativeVarRegisterAcquire(PIEMRECOMPILERSTATE pReNative, uint8_t idxVar, uint32_t *poff,
  • trunk/src/VBox/VMM/VMMAll/target-x86/IEMAllN8veEmit-x86.h

    r106196 r106197  
    255255        pReNative->PostponedEfl.idxReg1 = UINT8_MAX;
    256256        pReNative->PostponedEfl.idxReg2 = UINT8_MAX;
    257 #if defined(VBOX_WITH_STATISTICS) || defined(IEMNATIVE_WITH_TB_DEBUG_INFO)
     257# if defined(VBOX_WITH_STATISTICS) || defined(IEMNATIVE_WITH_TB_DEBUG_INFO)
    258258        STAM_PROFILE_ADD_PERIOD(&pReNative->pVCpu->iem.s.StatNativeEflPostponedEmits, pReNative->PostponedEfl.cEmits);
    259259        pReNative->PostponedEfl.cEmits = 0;
    260 #endif
    261     }
    262 }
    263 
     260# endif
     261    }
     262}
     263
     264#endif /* IEMNATIVE_WITH_EFLAGS_POSTPONING */
     265
     266
     267template<bool const a_fDoOp>
    264268DECL_INLINE_THROW(uint32_t) iemNativeEmitPostponedEFlagsCalcLogical(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t cOpBits,
    265269                                                                    uint8_t idxRegResult, uint8_t idxRegEfl, uint8_t idxRegTmp)
    266270{
    267271#ifdef RT_ARCH_AMD64
     272    /* Do TEST idxRegResult, idxRegResult to set flags. */
     273    if RT_CONSTEXPR_IF(a_fDoOp)
     274        off = iemNativeEmitAmd64OneByteModRmInstrRREx(pCodeBuf, off, 0x84, 0x85, cOpBits, idxRegResult, idxRegResult);
     275
    268276    /*
    269      * Do an AND and collect flags and merge them with eflags.
     277     * Collect the EFLAGS status bits.
     278     * We know that the overflow bit will always be cleared, so LAHF can be used.
    270279     */
    271     /* Do TEST idxRegResult, idxRegResult to set flags. */
    272     off = iemNativeEmitAmd64OneByteModRmInstrRREx(pCodeBuf, off, 0x84, 0x85, cOpBits, idxRegResult, idxRegResult);
    273 
    274280    if (idxRegTmp == X86_GREG_xAX)
    275281    {
     
    295301    else if (idxRegEfl != X86_GREG_xAX)
    296302    {
     303# if 1 /* This is 1 or 4 bytes larger, but avoids the stack. */
     304        /* xchg rax, tmp */
     305        pCodeBuf[off++] = idxRegTmp < 8 ? X86_OP_REX_W : X86_OP_REX_B | X86_OP_REX_W;
     306        pCodeBuf[off++] = 0x90 + (idxRegTmp & 7);
     307
     308        /* lahf ; AH = EFLAGS */
     309        pCodeBuf[off++] = 0x9f;
     310        if (idxRegEfl <= X86_GREG_xBX)
     311        {
     312            /* mov [CDB]L, AH */
     313            pCodeBuf[off++] = 0x88;
     314            pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4 /*AH*/, idxRegEfl);
     315        }
     316        else
     317        {
     318            /* mov   AL, AH */
     319            pCodeBuf[off++] = 0x88;
     320            pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4 /*AH*/, 0 /*AL*/);
     321            /* mov   xxL, AL */
     322            pCodeBuf[off++] = idxRegEfl >= 8 ? X86_OP_REX_B : X86_OP_REX;
     323            pCodeBuf[off++] = 0x88;
     324            pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 0 /*AL*/, idxRegEfl & 7);
     325        }
     326
     327        /* xchg rax, tmp */
     328        pCodeBuf[off++] = idxRegTmp < 8 ? X86_OP_REX_W : X86_OP_REX_B | X86_OP_REX_W;
     329        pCodeBuf[off++] = 0x90 + (idxRegTmp & 7);
     330
     331# else
    297332        /* pushf */
    298333        pCodeBuf[off++] = 0x9c;
     
    302337        pCodeBuf[off++] = 0x58 + (idxRegTmp & 7);
    303338        /* mov   byte(efl), byte(tmp) */
    304         pCodeBuf[off++] = (idxRegEfl >= 8 ? X86_OP_REX_B : X86_OP_REX)
    305                         | (idxRegTmp >= 8 ? X86_OP_REX_R : 0);
     339        if (idxRegEfl >= 4 || idxRegTmp >= 4)
     340            pCodeBuf[off++] = (idxRegEfl >= 8 ? X86_OP_REX_B : X86_OP_REX)
     341                            | (idxRegTmp >= 8 ? X86_OP_REX_R : 0);
    306342        pCodeBuf[off++] = 0x88;
    307343        pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, idxRegTmp & 7, idxRegEfl & 7);
     344# endif
    308345    }
    309346    else
     
    318355        pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4 /*AH*/, 0 /*AL*/);
    319356    }
    320     /* BTC idxEfl, 11; Clear OF */
     357    /* BTR idxEfl, 11; Clear OF */
    321358    if (idxRegEfl >= 8)
    322359        pCodeBuf[off++] = X86_OP_REX_B;
    323360    pCodeBuf[off++] = 0xf;
    324361    pCodeBuf[off++] = 0xba;
    325     pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, idxRegEfl & 7);
     362    pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 6, idxRegEfl & 7);
    326363    pCodeBuf[off++] = X86_EFL_OF_BIT;
    327364
     
    337374    if (cOpBits < 32)
    338375        pCodeBuf[off++] = Armv8A64MkInstrSetF8SetF16(idxRegResult, cOpBits > 8); /* sets NZ */
    339     else
     376    else if RT_CONSTEXPR_IF(a_fDoOp)
    340377        pCodeBuf[off++] = Armv8A64MkInstrAnds(ARMV8_A64_REG_XZR, idxRegResult, idxRegResult, cOpBits > 32 /*f64Bit*/);
    341378    pCodeBuf[off++] = Armv8A64MkInstrMrs(idxRegTmp, ARMV8_AARCH64_SYSREG_NZCV); /* Bits: 31=N; 30=Z; 29=C; 28=V; */
     
    361398}
    362399
     400#ifdef IEMNATIVE_WITH_EFLAGS_POSTPONING
    363401
    364402template<uint32_t const a_bmInputRegs, bool const a_fTlbMiss = false>
     
    366404                                                   uint32_t bmExtraTlbMissRegs = 0)
    367405{
    368 #ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
     406# ifdef IEMNATIVE_WITH_TB_DEBUG_INFO
    369407    iemNativeDbgInfoAddPostponedEFlagsCalc(pReNative, off, pReNative->PostponedEfl.enmOp, pReNative->PostponedEfl.cOpBits,
    370408                                           pReNative->PostponedEfl.cEmits);
    371 #endif
     409# endif
    372410
    373411    /*
     
    416454        if RT_CONSTEXPR_IF(!a_fTlbMiss) Assert(bmAvailableRegs & RT_BIT_32(idxRegEfl));
    417455        bmAvailableRegs &= ~RT_BIT_32(idxRegEfl);
    418 #ifdef VBOX_STRICT
     456# ifdef VBOX_STRICT
    419457        off = iemNativeEmitGuestRegValueCheckEx(pReNative, pCodeBuf, off, idxRegEfl, kIemNativeGstReg_EFlags);
    420 #endif
     458# endif
    421459
    422460        idxRegTmp = ASMBitFirstSetU32(bmAvailableRegs) - 1;
     
    441479        case kIemNativePostponedEflOp_Logical:
    442480            Assert(pReNative->PostponedEfl.idxReg2 == UINT8_MAX);
    443             off = iemNativeEmitPostponedEFlagsCalcLogical(pCodeBuf, off, pReNative->PostponedEfl.cOpBits,
    444                                                           pReNative->PostponedEfl.idxReg1, idxRegEfl, idxRegTmp);
     481            off = iemNativeEmitPostponedEFlagsCalcLogical<true>(pCodeBuf, off, pReNative->PostponedEfl.cOpBits,
     482                                                                pReNative->PostponedEfl.idxReg1, idxRegEfl, idxRegTmp);
    445483            break;
    446484
     
    452490     * Store EFLAGS.
    453491     */
    454 #ifdef VBOX_STRICT
     492# ifdef VBOX_STRICT
    455493    /* check that X86_EFL_1 is set. */
    456494    uint32_t offFixup1;
     
    464502    off = iemNativeEmitBrkEx(pCodeBuf, off, 0x3331);
    465503    iemNativeFixupFixedJump(pReNative, offFixup2, off);
    466 #endif
     504# endif
    467505    off = iemNativeEmitStoreGprToVCpuU32Ex(pCodeBuf, off, idxRegEfl, RT_UOFFSETOF(VMCPU, cpum.GstCtx.eflags));
    468506    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
    469507
    470 #if defined(VBOX_WITH_STATISTICS) || defined(IEMNATIVE_WITH_TB_DEBUG_INFO)
     508# if defined(VBOX_WITH_STATISTICS) || defined(IEMNATIVE_WITH_TB_DEBUG_INFO)
    471509    pReNative->PostponedEfl.cEmits++;
    472 #endif
     510# endif
    473511    return off;
    474512}
     
    513551}
    514552
    515 
    516553#endif /* IEMNATIVE_WITH_EFLAGS_POSTPONING */
    517554
     
    522559 * It takes liveness stuff into account.
    523560 */
     561/** @todo make fNativeFlags a template argument. */
    524562DECL_INLINE_THROW(uint32_t)
    525563iemNativeEmitEFlagsForLogical(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEfl,
     
    577615#endif
    578616    {
    579 #ifdef RT_ARCH_AMD64
    580         /*
    581          * Collect flags and merge them with eflags.
    582          */
    583         /** @todo we could alternatively use LAHF here when host rax is free since,
    584          *        OF is cleared. */
    585         PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
    586         /* pushf - do this before any reg allocations as they may emit instructions too. */
    587         pCodeBuf[off++] = 0x9c;
    588 
    589         uint8_t const idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/);
    590         uint8_t const idxTmpReg = iemNativeRegAllocTmp(pReNative, &off);
    591         pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2 + 7 + 7 + 3);
    592         /* pop   tmp */
    593         if (idxTmpReg >= 8)
    594             pCodeBuf[off++] = X86_OP_REX_B;
    595         pCodeBuf[off++] = 0x58 + (idxTmpReg & 7);
    596         /* and  tmp, X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF */
    597         off = iemNativeEmitAndGpr32ByImmEx(pCodeBuf, off, idxTmpReg, X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF);
    598         /* Clear the status bits in EFLs. */
    599         off = iemNativeEmitAndGpr32ByImmEx(pCodeBuf, off, idxRegEfl, ~X86_EFL_STATUS_BITS);
    600         /* OR in the flags we collected. */
    601         off = iemNativeEmitOrGpr32ByGprEx(pCodeBuf, off, idxRegEfl, idxTmpReg);
     617        uint8_t const         idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/);
     618        uint8_t const         idxRegTmp = iemNativeRegAllocTmp(pReNative, &off);
     619#ifdef RT_ARCH_AMD64
     620        PIEMNATIVEINSTR const pCodeBuf  = iemNativeInstrBufEnsure(pReNative, off, 32);
     621#elif defined(RT_ARCH_ARM64)
     622        PIEMNATIVEINSTR const pCodeBuf  = iemNativeInstrBufEnsure(pReNative, off, 16);
     623#else
     624# error "port me"
     625#endif
     626#ifndef RT_ARCH_AMD64
     627        if (!fNativeFlags)
     628            off = iemNativeEmitPostponedEFlagsCalcLogical<true>(pCodeBuf, off, cOpBits, idxRegResult, idxRegEfl, idxRegTmp);
     629        else
     630#endif
     631            off = iemNativeEmitPostponedEFlagsCalcLogical<false>(pCodeBuf, off, cOpBits, idxRegResult, idxRegEfl, idxRegTmp);
     632        IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     633
    602634        iemNativeVarRegisterRelease(pReNative, idxVarEfl);
    603         iemNativeRegFreeTmp(pReNative, idxTmpReg);
    604 
    605 #elif defined(RT_ARCH_ARM64)
    606         /*
    607          * Calculate flags.
    608          */
    609         uint8_t const         idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/);
    610         uint8_t const         idxTmpReg = iemNativeRegAllocTmp(pReNative, &off);
    611         PIEMNATIVEINSTR const pCodeBuf  = iemNativeInstrBufEnsure(pReNative, off, 15);
    612 
    613         /* Clear the status bits. ~0x8D5 (or ~0x8FD) can't be AND immediate, so use idxTmpReg for constant. */
    614         off = iemNativeEmitLoadGpr32ImmEx(pCodeBuf, off, idxTmpReg, ~X86_EFL_STATUS_BITS);
    615         off = iemNativeEmitAndGpr32ByGpr32Ex(pCodeBuf, off, idxRegEfl, idxTmpReg);
    616 
    617         /* N,Z -> SF,ZF */
    618         if (cOpBits < 32)
    619             pCodeBuf[off++] = Armv8A64MkInstrSetF8SetF16(idxRegResult, cOpBits > 8); /* sets NZ */
    620         else if (!fNativeFlags)
    621             pCodeBuf[off++] = Armv8A64MkInstrAnds(ARMV8_A64_REG_XZR, idxRegResult, idxRegResult, cOpBits > 32 /*f64Bit*/);
    622         pCodeBuf[off++] = Armv8A64MkInstrMrs(idxTmpReg, ARMV8_AARCH64_SYSREG_NZCV); /* Bits: 31=N; 30=Z; 29=C; 28=V; */
    623         pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 30);
    624         pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_ZF_BIT, 2, false /*f64Bit*/);
    625         AssertCompile(X86_EFL_ZF_BIT + 1 == X86_EFL_SF_BIT);
    626 
    627         /* Calculate 8-bit parity of the result. */
    628         pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxRegResult, idxRegResult, false /*f64Bit*/,
    629                                              4 /*offShift6*/, kArmv8A64InstrShift_Lsr);
    630         pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg,    idxTmpReg,    false /*f64Bit*/,
    631                                              2 /*offShift6*/, kArmv8A64InstrShift_Lsr);
    632         pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg,    idxTmpReg,    false /*f64Bit*/,
    633                                              1 /*offShift6*/, kArmv8A64InstrShift_Lsr);
    634         Assert(Armv8A64ConvertImmRImmS2Mask32(0, 0) == 1);
    635         pCodeBuf[off++] = Armv8A64MkInstrEorImm(idxTmpReg, idxTmpReg, 0, 0, false /*f64Bit*/);
    636         pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_PF_BIT, 1,  false /*f64Bit*/);
    637 
    638         iemNativeVarRegisterRelease(pReNative, idxVarEfl);
    639         iemNativeRegFreeTmp(pReNative, idxTmpReg);
    640 #else
    641 # error "port me"
    642 #endif
    643         IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     635        iemNativeRegFreeTmp(pReNative, idxRegTmp);
    644636    }
    645637
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