VirtualBox

Changeset 103743 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Mar 9, 2024 2:42:29 AM (9 months ago)
Author:
vboxsync
Message:

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

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

Legend:

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

    r103742 r103743  
    14931493{
    14941494    IEMOP_MNEMONIC2(FIXED, SBB, sbb, AL, Ib, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
    1495     IEMOP_BODY_BINARY_AL_Ib(sbb, 0);
     1495    IEMOP_BODY_BINARY_AL_Ib(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
    14961496}
    14971497
     
    15051505{
    15061506    IEMOP_MNEMONIC2(FIXED, SBB, sbb, rAX, Iz, DISOPTYPE_HARMLESS, 0);
    1507     IEMOP_BODY_BINARY_rAX_Iz_RW(sbb, 0);
     1507    IEMOP_BODY_BINARY_rAX_Iz_RW(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
    15081508}
    15091509
     
    44164416{
    44174417    IEMOP_MNEMONIC(sbb_Eb_Ib, "sbb Eb,Ib");
    4418     IEMOP_BODY_BINARY_Eb_Ib_RW(sbb, 0, 0);
     4418    IEMOP_BODY_BINARY_Eb_Ib_RW(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
    44194419}
    44204420
     
    49894989{
    49904990    IEMOP_MNEMONIC(sbb_Ev_Iz, "sbb Ev,Iz");
    4991     IEMOP_BODY_BINARY_Ev_Iz_RW(sbb, 0, 0);
     4991    IEMOP_BODY_BINARY_Ev_Iz_RW(sbb, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
    49924992}
    49934993
  • trunk/src/VBox/VMM/VMMAll/target-x86/IEMAllN8veEmit-x86.h

    r103742 r103743  
    364364            pCodeBuf[off++] = Armv8A64MkInstrBfxil(idxRegEfl, idxRegResult, cOpBits, 1, false /*f64Bit*/);
    365365
    366             /* The overflow flag is more work. See IEM_EFL_UPDATE_STATUS_BITS_FOR_ARITHMETIC.
    367                It is a bit simpler when the right side is constant. */
     366            /* The overflow flag is more work as we have to compare the signed bits for
     367               both inputs and the result. See IEM_EFL_UPDATE_STATUS_BITS_FOR_ARITHMETIC.
     368
     369               Formula: ~(a_uDst ^ a_uSrcOf) & (a_uResult ^ a_uDst)
     370               With a_uSrcOf as a_uSrc for additions and ~a_uSrc for subtractions.
     371
     372               It is a bit simpler when the right (source) side is constant:
     373               adc: S D R -> OF                     sbb: S D R -> OF
     374                    0 0 0 -> 0  \                        0 0 0 -> 0  \
     375                    0 0 1 -> 1   \                       0 0 1 -> 0   \
     376                    0 1 0 -> 0   / and not(D), R         0 1 0 -> 1   / and D, not(R)
     377                    0 1 1 -> 0  /                        0 1 1 -> 0  /
     378                    1 0 0 -> 0  \                        1 0 0 -> 0  \
     379                    1 0 1 -> 0   \ and D, not(R)         1 0 1 -> 1   \ and not(D), R
     380                    1 1 0 -> 1   /                       1 1 0 -> 0   /
     381                    1 1 1 -> 0  /                        1 1 1 -> 0  / */
    368382            if (idxRegSrc != UINT8_MAX)
    369383            {
     
    377391            else if (uImmSrc & RT_BIT_32(cOpBits - 1))
    378392            {
    379                 if (fInvertCarry) /* sbb w/ top right 1: ~a_uDst & a_uResult ; HACK ALERT: fInvertCarry == sbb */
    380                     pCodeBuf[off++] = Armv8A64MkInstrEon(idxTmpReg, idxRegResult, idxRegDstIn, false);
    381                 else              /* adc w/ top right 1: a_uDst & ~a_uResult */
    382                     pCodeBuf[off++] = Armv8A64MkInstrEon(idxTmpReg, idxRegDstIn, idxRegResult, false);
     393                if (fInvertCarry) /* HACK ALERT: fInvertCarry == sbb */
     394                    pCodeBuf[off++] = Armv8A64MkInstrBic(idxTmpReg, idxRegResult, idxRegDstIn, false);
     395                else
     396                    pCodeBuf[off++] = Armv8A64MkInstrBic(idxTmpReg, idxRegDstIn, idxRegResult, false);
    383397            }
    384398            else
    385399            {
    386                 if (fInvertCarry) /* sbb w/ top right 0: a_uDst & ~a_uResult ; HACK ALERT: fInvertCarry == sbb */
    387                     pCodeBuf[off++] = Armv8A64MkInstrEon(idxTmpReg, idxRegDstIn, idxRegResult, false);
    388                 else              /* adc w/ top right 0: ~a_uDst & a_uResult */
    389                     pCodeBuf[off++] = Armv8A64MkInstrEon(idxTmpReg, idxRegResult, idxRegDstIn, false);
     400                if (fInvertCarry) /* HACK ALERT: fInvertCarry == sbb */
     401                    pCodeBuf[off++] = Armv8A64MkInstrBic(idxTmpReg, idxRegDstIn, idxRegResult, false);
     402                else
     403                    pCodeBuf[off++] = Armv8A64MkInstrBic(idxTmpReg, idxRegResult, idxRegDstIn, false);
    390404            }
    391405            pCodeBuf[off++] = Armv8A64MkInstrLsrImm(idxTmpReg, idxTmpReg,   cOpBits - 1,  false /*f64Bit*/);
     
    11101124    PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 9);
    11111125
    1112     /* Use the BT instruction to set CF according to idxRegEfl. */
    11131126    off = iemNativeEmitAmd64TwoByteModRmInstrRREx(pCodeBuf, off, 0x0f, 0x0b, 0xba, 32 /*cOpBits*/, 4, idxRegEfl);
    11141127    pCodeBuf[off++] = X86_EFL_CF_BIT;
     
    11681181                          uint8_t idxVarDst, uint64_t uImmOp, uint8_t idxVarEfl, uint8_t cOpBits, uint8_t cImmBits)
    11691182{
    1170     RT_NOREF(pReNative, off, idxVarDst, uImmOp, idxVarEfl, cOpBits, cImmBits);
     1183    uint8_t const idxRegDst = iemNativeVarRegisterAcquire(pReNative, idxVarDst, &off, true /*fInitialized*/);
     1184    uint8_t const idxRegEfl = iemNativeVarRegisterAcquire(pReNative, idxVarEfl, &off, true /*fInitialized*/);
     1185
     1186#ifdef RT_ARCH_AMD64
     1187    /* On AMD64 we use BT to set EFLAGS.CF and then issue an SBB instruction
     1188       with matching size to get the correct flags. */
     1189    PIEMNATIVEINSTR const pCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 12);
     1190
     1191    off = iemNativeEmitAmd64TwoByteModRmInstrRREx(pCodeBuf, off, 0x0f, 0x0b, 0xba, 32 /*cOpBits*/, 4, idxRegEfl);
     1192    pCodeBuf[off++] = X86_EFL_CF_BIT;
     1193
     1194    off = iemNativeEmitAmd64OneByteModRmInstrRIEx(pCodeBuf, off, 0x80, 0x83, 0x81, cOpBits, cImmBits, 3, idxRegDst, uImmOp);
     1195    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     1196
     1197    iemNativeVarRegisterRelease(pReNative, idxVarDst);
     1198
     1199    off = iemNativeEmitEFlagsForArithmetic(pReNative, off, UINT8_MAX, idxRegEfl);
     1200
     1201#elif defined(RT_ARCH_ARM64)
     1202    /* On ARM64 we use the RMIF+CFINV instructions to load PSTATE.CF from
     1203       idxRegEfl and then SBCS for the calculation.  We need all inputs and
     1204       result for the two flags (AF,PF) that can't be directly derived from
     1205       PSTATE.NZCV. */
     1206    uint8_t const         idxRegDstIn = iemNativeRegAllocTmp(pReNative, &off);
     1207    uint8_t const         idxRegImm   = iemNativeRegAllocTmpImm(pReNative, &off, uImmOp);
     1208    PIEMNATIVEINSTR const pCodeBuf    = iemNativeInstrBufEnsure(pReNative, off, 5);
     1209
     1210    pCodeBuf[off++] = Armv8A64MkInstrRmif(idxRegEfl, (X86_EFL_CF_BIT - 1) & 63, RT_BIT_32(1) /*fMask=C*/);
     1211    pCodeBuf[off++] = ARMV8_A64_INSTR_CFINV;
     1212    off = iemNativeEmitLoadGprFromGprEx(pCodeBuf, off, idxRegDstIn, idxRegDst);
     1213    if (cOpBits >= 32)
     1214        pCodeBuf[off++] = Armv8A64MkInstrSbcs(idxRegDst, idxRegDst, idxRegImm, cOpBits > 32 /*f64Bit*/);
     1215    else
     1216    {
     1217        /* Since we're also adding in the carry flag here, shifting operands up
     1218           doesn't work. So, we have to calculate carry & overflow manually. */
     1219        pCodeBuf[off++] = Armv8A64MkInstrSbc(idxRegDst, idxRegDst, idxRegImm, false /*f64Bit*/);
     1220        pCodeBuf[off++] = Armv8A64MkInstrSetF8SetF16(idxRegDst, cOpBits > 8); /* NZ are okay, CV aren't.*/
     1221    }
     1222    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     1223
     1224    iemNativeRegFreeTmp(pReNative, idxRegImm);
     1225
     1226    off = iemNativeEmitEFlagsForArithmetic(pReNative, off, UINT8_MAX, idxRegEfl, cOpBits, idxRegDst,
     1227                                           idxRegDstIn, UINT8_MAX, true /*fInvertCarry*/, uImmOp);
     1228
     1229    iemNativeRegFreeTmp(pReNative, idxRegDstIn);
     1230    if (cOpBits < 32)
     1231        off = iemNativeEmitAndGpr32ByImm(pReNative, off, idxRegDst, RT_BIT_32(cOpBits) - 1U);
     1232    iemNativeVarRegisterRelease(pReNative, idxVarDst);
     1233    RT_NOREF(cImmBits);
     1234
     1235#else
     1236# error "port me"
     1237#endif
     1238    iemNativeVarRegisterRelease(pReNative, idxVarEfl);
    11711239    return off;
    11721240}
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