VirtualBox

Ignore:
Timestamp:
Mar 5, 2024 2:10:37 AM (11 months ago)
Author:
vboxsync
Message:

VMM/IEM: Implemented iemNativeEmit_sub_r_r_efl and enabled it for both hosts. bugref:10376

File:
1 edited

Legend:

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

    r103657 r103675  
    3333
    3434
     35#ifdef RT_ARCH_AMD64
     36DECL_FORCE_INLINE(uint32_t)
     37iemNativeEmitAmd64ModRmInstrRREx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t bOpcode8, uint8_t bOpcodeOther,
     38                                 uint8_t cOpBits, uint8_t idxRegReg, uint8_t idxRegRm)
     39{
     40    Assert(idxRegReg < 16); Assert(idxRegRm < 16);
     41    switch (cOpBits)
     42    {
     43        case 16:
     44            pCodeBuf[off++] = X86_OP_PRF_SIZE_OP;
     45            RT_FALL_THRU();
     46        case 32:
     47            if (idxRegReg >= 8 || idxRegRm >= 8)
     48                pCodeBuf[off++] = (idxRegReg >= 8 ? X86_OP_REX_R : 0) | (idxRegRm >= 8 ? X86_OP_REX_B : 0);
     49            pCodeBuf[off++] = bOpcodeOther;
     50            break;
     51
     52        default: AssertFailed(); RT_FALL_THRU();
     53        case 64:
     54            pCodeBuf[off++] = X86_OP_REX_W | (idxRegReg >= 8 ? X86_OP_REX_R : 0) | (idxRegRm >= 8 ? X86_OP_REX_B : 0);
     55            pCodeBuf[off++] = bOpcodeOther;
     56            break;
     57
     58        case 8:
     59            if (idxRegReg >= 8 || idxRegRm >= 8)
     60                pCodeBuf[off++] = (idxRegReg >= 8 ? X86_OP_REX_R : 0) | (idxRegRm >= 8 ? X86_OP_REX_B : 0);
     61            else if (idxRegReg >= 4 || idxRegRm >= 4)
     62                pCodeBuf[off++] = X86_OP_REX;
     63            pCodeBuf[off++] = bOpcode8;
     64            break;
     65    }
     66    pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, idxRegReg & 7, idxRegRm & 7);
     67    return off;
     68}
     69#endif /* RT_ARCH_AMD64 */
     70
     71
    3572/**
    36  * This is an implementation of IEM_EFL_UPDATE_STATUS_BITS_FOR_LOGICAL
    37  * and friends.
     73 * This is an implementation of IEM_EFL_UPDATE_STATUS_BITS_FOR_LOGICAL.
    3874 *
    3975 * It takes liveness stuff into account.
     
    121157    }
    122158    return off;
     159}
     160
     161
     162/**
     163 * This is an implementation of IEM_EFL_UPDATE_STATUS_BITS_FOR_ARITHMETIC.
     164 *
     165 * It takes liveness stuff into account.
     166 */
     167DECL_FORCE_INLINE_THROW(uint32_t)
     168iemNativeEmitEFlagsForArithmetic(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEfl
     169#ifndef RT_ARCH_AMD64
     170                                 , uint8_t cOpBits, uint8_t idxRegResult, uint8_t idxRegDstIn, uint8_t idxRegSrc, bool fNativeFlags
     171#endif
     172                                 )
     173{
     174#ifdef IEMNATIVE_WITH_LIVENESS_ANALYSIS
     175    if (1) /** @todo check if all bits are clobbered. */
     176#endif
     177    {
     178#ifdef RT_ARCH_AMD64
     179        /*
     180         * Collect flags and merge them with eflags.
     181         */
     182        PIEMNATIVEINSTR pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     183        /* pushf - do this before any reg allocations as they may emit instructions too. */
     184        pCodeBuf[off++] = 0x9c;
     185
     186        uint8_t const idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/);
     187        uint8_t const idxTmpReg = iemNativeRegAllocTmp(pReNative, &off);
     188        pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2 + 7 + 7 + 3);
     189        /* pop   tmp */
     190        if (idxTmpReg >= 8)
     191            pCodeBuf[off++] = X86_OP_REX_B;
     192        pCodeBuf[off++] = 0x58 + (idxTmpReg & 7);
     193        /* Isolate the flags we want. */
     194        off = iemNativeEmitAndGpr32ByImmEx(pCodeBuf, off, idxTmpReg, X86_EFL_STATUS_BITS);
     195        /* Clear the status bits in EFLs. */
     196        off = iemNativeEmitAndGpr32ByImmEx(pCodeBuf, off, idxRegEfl, ~X86_EFL_STATUS_BITS);
     197        /* OR in the flags we collected. */
     198        off = iemNativeEmitOrGpr32ByGprEx(pCodeBuf, off, idxRegEfl, idxTmpReg);
     199        iemNativeVarRegisterRelease(pReNative, idxVarEfl);
     200        iemNativeRegFreeTmp(pReNative, idxTmpReg);
     201
     202#elif defined(RT_ARCH_ARM64)
     203        /*
     204         * Calculate flags.
     205         */
     206        uint8_t const         idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/);
     207        uint8_t const         idxTmpReg = iemNativeRegAllocTmp(pReNative, &off);
     208        PIEMNATIVEINSTR const pCodeBuf  = iemNativeInstrBufEnsure(pReNative, off, 18);
     209
     210        if (fNativeFlags && cOpBits >= 32)
     211        {
     212            /* Invert CF (stored inved on ARM) and load the flags into the temporary register. */
     213            pCodeBuf[off++] = ARMV8_A64_INSTR_CFINV;
     214            pCodeBuf[off++] = Armv8A64MkInstrMrs(idxTmpReg, ARMV8_AARCH64_SYSREG_NZCV); /* Bits: 31=N; 30=Z; 29=C; 28=V; */
     215
     216            /* V -> OF */
     217            pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 28);
     218            pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_OF_BIT, 1, false /*f64Bit*/);
     219
     220            /* C -> CF */
     221            pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 1);
     222            pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_CF_BIT, 1, false /*f64Bit*/);
     223
     224            /* N,Z -> SF,ZF */
     225            pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 1);
     226            pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_ZF_BIT, 2, false /*f64Bit*/);
     227        }
     228        else
     229        {
     230#if 0
     231            pCodeBuf[off++] = Armv8A64MkInstrSetF8SetF16(idxRegResult, cOpBits > 8);
     232            pCodeBuf[off++] = Armv8A64MkInstrMrs(idxTmpReg, ARMV8_AARCH64_SYSREG_NZCV); /* Bits: 31=N; 30=Z; 29=C; 28=V; */
     233
     234            /* V -> OF */
     235            pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 28);
     236            pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_OF_BIT, 1, false /*f64Bit*/);
     237
     238            /* N,Z -> SF,ZF */
     239            pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, 2);
     240            pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_ZF_BIT, 2, false /*f64Bit*/);
     241#else
     242            pCodeBuf[off++] = Armv8A64MkInstrBrk(0x1010);
     243#endif
     244        }
     245
     246        /* Calculate 8-bit parity of the result. */
     247        pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxRegResult, idxRegResult, false /*f64Bit*/,
     248                                             4 /*offShift6*/, kArmv8A64InstrShift_Lsr);
     249        pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg,    idxTmpReg,    false /*f64Bit*/,
     250                                             2 /*offShift6*/, kArmv8A64InstrShift_Lsr);
     251        pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg,    idxTmpReg,    false /*f64Bit*/,
     252                                             1 /*offShift6*/, kArmv8A64InstrShift_Lsr);
     253        Assert(Armv8A64ConvertImmRImmS2Mask32(0, 0) == 1);
     254        pCodeBuf[off++] = Armv8A64MkInstrEorImm(idxTmpReg, idxTmpReg, 0, 0, false /*f64Bit*/);
     255        pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_PF_BIT, 1,  false /*f64Bit*/);
     256
     257        /* Calculate auxilary carry/borrow.  This is related to 8-bit BCD.*/
     258        pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxRegDstIn, idxRegSrc, false /*f64Bit*/);
     259        pCodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg, idxRegResult, false /*f64Bit*/);
     260        pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg, X86_EFL_AF_BIT, false /*f64Bit*/);
     261        pCodeBuf[off++] = Armv8A64MkInstrBfi(idxRegEfl, idxTmpReg, X86_EFL_AF_BIT, 1,  false /*f64Bit*/);
     262
     263        iemNativeVarRegisterRelease(pReNative, idxVarEfl);
     264        iemNativeRegFreeTmp(pReNative, idxTmpReg);
     265#else
     266# error "port me"
     267#endif
     268        IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     269    }
     270    return off;
     271
    123272}
    124273
     
    405554                          uint8_t idxVarDst, uint8_t idxVarSrc, uint8_t idxVarEfl, uint8_t cOpBits)
    406555{
    407     RT_NOREF(idxVarDst, idxVarSrc, idxVarEfl, cOpBits);
    408     AssertFailed();
    409     return iemNativeEmitBrk(pReNative, off, 0x666);
     556    /*
     557     * The SUB instruction will set all flags.
     558     */
     559    uint8_t const idxRegDst = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/);
     560    uint8_t const idxRegSrc = iemNativeVarRegisterAcquire(pReNative, idxVarSrc, &off, true /*fInitialized*/);
     561
     562#ifdef RT_ARCH_ARM64
     563    /* On ARM64 we'll need the two input operands as well as the result in order
     564       to calculate the right flags, even if we use SUBS and translates NZCV into
     565       OF, CF, ZF and SF. */
     566
     567    /* Copy idxRegDst. */
     568    uint8_t const idxRegDstIn = iemNativeRegAllocTmp(pReNative, &off);
     569    PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 4);
     570
     571    /* Do the SUB setting flags. */
     572    if (cOpBits >= 32)
     573    {
     574        off = iemNativeEmitLoadGprFromGprEx(pCodeBuf, off, idxRegDstIn, idxRegDst);
     575        pCodeBuf[off++] = Armv8A64MkInstrSubReg(idxRegDst, idxRegDst, idxRegSrc, cOpBits > 32 /*f64Bit*/, true /*fSetFlags*/);
     576    }
     577    else
     578    {
     579        /* Shift the operands up so we can perform a 32-bit operation and get all four flags. */
     580        uint32_t const cShift = 32 - cOpBits;
     581        pCodeBuf[off++] = Armv8A64MkInstrOrr(idxRegDstIn, ARMV8_A64_REG_XZR, idxRegDst, false /*f64Bit*/, cShift);
     582        pCodeBuf[off++] = Armv8A64MkInstrSubReg(idxRegDst, idxRegDstIn, idxRegSrc, cOpBits > 32 /*f64Bit*/,
     583                                                true /*fSetFlags*/, cShift);
     584        pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxRegDstIn, idxRegDstIn, cShift, false /*f64Bit*/);
     585        pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxRegDst, idxRegDst, cShift, false /*f64Bit*/);
     586    }
     587
     588    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     589
     590    off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl, RT_MAX(cOpBits, 32), idxRegDst,
     591                                           idxRegDstIn, idxRegSrc, true /*fNativeFlags*/);
     592
     593    iemNativeRegFreeTmp(pReNative, idxRegDstIn);
     594    iemNativeVarRegisterRelease(pReNative, idxVarSrc);
     595    iemNativeVarRegisterRelease(pReNative, idxVarDst);
     596
     597#elif defined(RT_ARCH_AMD64)
     598    /* On AMD64 we must use the correctly sized AND instructions to get the
     599       right EFLAGS.SF value, while the rest will just lump 16-bit and 8-bit
     600       in the 32-bit ones. */
     601    off = iemNativeEmitAmd64ModRmInstrRREx(iemNativeInstrBufEnsure(pReNative, off, 4), off,
     602                                           0x2a, 0x2b, cOpBits, idxRegDst, idxRegSrc);
     603    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     604
     605    iemNativeVarRegisterRelease(pReNative, idxVarSrc);
     606    iemNativeVarRegisterRelease(pReNative, idxVarDst);
     607
     608    off = iemNativeEmitEFlagsForArithmetic(pReNative, off, idxVarEfl);
     609
     610#else
     611# error "port me"
     612#endif
     613    return off;
    410614}
    411615
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