VirtualBox

Ignore:
Timestamp:
Mar 5, 2024 3:02:10 PM (14 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
162048
Message:

VMM/IEM: Implemented iemNativeEmit_add_r_r_efl and enabled in on both hosts. bugref:10376

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/target-x86/IEMAllN8veEmit-x86.h

    r103682 r103683  
    168168iemNativeEmitEFlagsForArithmetic(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEfl
    169169#ifndef RT_ARCH_AMD64
    170                                  , uint8_t cOpBits, uint8_t idxRegResult, uint8_t idxRegDstIn, uint8_t idxRegSrc, bool fNativeFlags
     170                                 , uint8_t cOpBits, uint8_t idxRegResult, uint8_t idxRegDstIn, uint8_t idxRegSrc
     171                                 , bool fNativeFlags, bool fInvertCarry
    171172#endif
    172173                                 )
     
    211212        {
    212213            /* Invert CF (stored inved on ARM) and load the flags into the temporary register. */
    213             pCodeBuf[off++] = ARMV8_A64_INSTR_CFINV;
     214            if (fInvertCarry)
     215                pCodeBuf[off++] = ARMV8_A64_INSTR_CFINV;
    214216            pCodeBuf[off++] = Armv8A64MkInstrMrs(idxTmpReg, ARMV8_AARCH64_SYSREG_NZCV); /* Bits: 31=N; 30=Z; 29=C; 28=V; */
    215217
     
    418420
    419421
     422/**
     423 * The ADD instruction will set all status flags.
     424 */
    420425DECL_INLINE_THROW(uint32_t)
    421426iemNativeEmit_add_r_r_efl(PIEMRECOMPILERSTATE pReNative, uint32_t off,
     427                          uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
     428{
     429    uint8_t const idxRegDst = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/);
     430    uint8_t const idxRegSrc = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
     431
     432#ifdef RT_ARCH_AMD64
     433    /* On AMD64 we just use the correctly sized ADD instruction to get the right EFLAGS.SF value. */
     434    off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off,
     435                                           0x02, 0x03, cOpBits, idxRegDst, idxRegSrc);
     436    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     437
     438    iemNativeVarRegisterRelease(pReNative, idxVarSrc);
     439    iemNativeVarRegisterRelease(pReNative, idxVarDst);
     440
     441    off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl);
     442
     443#elif defined(RT_ARCH_ARM64)
     444    /* On ARM64 we'll need the two input operands as well as the result in order
     445       to calculate the right flags, even if we use ADDS and translates NZCV into
     446       OF, CF, ZF and SF. */
     447    uint8_t const         idxRegDstIn = iemNativeRegAllocTmp(pReNative, &off);
     448    PIEMNATIVEINSTR const pCodeBuf    = iemNativeInstrBufEnsure(pReNative, off, 5);
     449    if (cOpBits >= 32)
     450    {
     451        off = iemNativeEmitLoadGprFromGprEx(pCodeBuf, off, idxRegDstIn, idxRegDst);
     452        pCodeBuf[off++] = Armv8A64MkInstrAddReg(idxRegDst, idxRegDst, idxRegSrc, cOpBits > 32 /*f64Bit*/, true /*fSetFlags*/);
     453    }
     454    else
     455    {
     456        /* Shift the operands up so we can perform a 32-bit operation and get all four flags. */
     457        uint32_t const cShift = 32 - cOpBits;
     458        pCodeBuf[off++] = Armv8A64MkInstrOrr(idxRegDstIn, ARMV8_A64_REG_XZR, idxRegDst, false /*f64Bit*/, cShift);
     459        pCodeBuf[off++] = Armv8A64MkInstrAddReg(idxRegDst, idxRegDstIn, idxRegSrc, false /*f64Bit*/,
     460                                                true /*fSetFlags*/, cShift);
     461        pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxRegDstIn, idxRegDstIn, cShift, false /*f64Bit*/);
     462        pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxRegDst, idxRegDst, cShift, false /*f64Bit*/);
     463        cOpBits = 32;
     464    }
     465    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     466
     467    /** @todo Explain why the carry flag shouldn't be inverted for ADDS. */
     468    off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl, cOpBits, idxRegDst,
     469                                           idxRegDstIn, idxRegSrc, true /*fNativeFlags*/, false /*fInvertCarry*/);
     470
     471    iemNativeRegFreeTmp(pReNative, idxRegDstIn);
     472    iemNativeVarRegisterRelease(pReNative, idxVarSrc);
     473    iemNativeVarRegisterRelease(pReNative, idxVarDst);
     474
     475#else
     476# error "port me"
     477#endif
     478    return off;
     479}
     480
     481
     482DECL_INLINE_THROW(uint32_t)
     483iemNativeEmit_adc_r_r_efl(PIEMRECOMPILERSTATE pReNative, uint32_t off,
    422484                          uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
    423485{
     
    428490
    429491
    430 DECL_INLINE_THROW(uint32_t)
    431 iemNativeEmit_adc_r_r_efl(PIEMRECOMPILERSTATE pReNative, uint32_t off,
    432                           uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
    433 {
    434     RT_NOREF(idxVarDst, idxVarSrc, idxVarEfl, cOpBits);
    435     AssertFailed();
    436     return iemNativeEmitBrk(pReNative, off, 0x666);
    437 }
    438 
    439 
     492/**
     493 * The SUB instruction will set all status flags.
     494 */
    440495DECL_INLINE_THROW(uint32_t)
    441496iemNativeEmit_sub_r_r_efl(PIEMRECOMPILERSTATE pReNative, uint32_t off,
    442497                          uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
    443498{
    444     /*
    445      * The SUB instruction will set all flags.
    446      */
    447499    uint8_t const idxRegDst = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/);
    448500    uint8_t const idxRegSrc = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
     
    475527        uint32_t const cShift = 32 - cOpBits;
    476528        pCodeBuf[off++] = Armv8A64MkInstrOrr(idxRegDstIn, ARMV8_A64_REG_XZR, idxRegDst, false /*f64Bit*/, cShift);
    477         pCodeBuf[off++] = Armv8A64MkInstrSubReg(idxRegDst, idxRegDstIn, idxRegSrc, cOpBits > 32 /*f64Bit*/,
     529        pCodeBuf[off++] = Armv8A64MkInstrSubReg(idxRegDst, idxRegDstIn, idxRegSrc, false /*f64Bit*/,
    478530                                                true /*fSetFlags*/, cShift);
    479531        pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxRegDstIn, idxRegDstIn, cShift, false /*f64Bit*/);
     
    484536
    485537    off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl, cOpBits, idxRegDst,
    486                                            idxRegDstIn, idxRegSrc, true /*fNativeFlags*/);
     538                                           idxRegDstIn, idxRegSrc, true /*fNativeFlags*/, true /*fInvertCarry*/);
    487539
    488540    iemNativeRegFreeTmp(pReNative, idxRegDstIn);
     
    497549
    498550
     551/**
     552 * The CMP instruction will set all status flags, but modifies no registers.
     553 */
    499554DECL_INLINE_THROW(uint32_t)
    500555iemNativeEmit_cmp_r_r_efl(PIEMRECOMPILERSTATE pReNative, uint32_t off,
    501556                          uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
    502557{
    503     /*
    504      * The SUB instruction will set all flags.
    505      */
    506558    uint8_t const idxRegDst = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/);
    507559    uint8_t const idxRegSrc = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
     
    531583        uint32_t const cShift = 32 - cOpBits;
    532584        pCodeBuf[off++] = Armv8A64MkInstrOrr(idxRegResult, ARMV8_A64_REG_XZR, idxRegDst, false /*f64Bit*/, cShift);
    533         pCodeBuf[off++] = Armv8A64MkInstrSubReg(idxRegResult, idxRegResult, idxRegSrc, cOpBits > 32 /*f64Bit*/,
     585        pCodeBuf[off++] = Armv8A64MkInstrSubReg(idxRegResult, idxRegResult, idxRegSrc, false /*f64Bit*/,
    534586                                                true /*fSetFlags*/, cShift);
    535587        pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxRegResult, idxRegResult, cShift, false /*f64Bit*/);
     
    539591
    540592    off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl, cOpBits, idxRegResult,
    541                                            idxRegDst, idxRegSrc, true /*fNativeFlags*/);
     593                                           idxRegDst, idxRegSrc, true /*fNativeFlags*/, true /*fInvertCarry*/);
    542594
    543595    iemNativeRegFreeTmp(pReNative, idxRegResult);
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