VirtualBox

Changeset 103675 in vbox


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

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

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/armv8.h

    r103606 r103675  
    435435/** ICC_IGRPEN1_EL1 register - RW. */
    436436#define ARMV8_AARCH64_SYSREG_ICC_IGRPEN1_EL1        ARMV8_AARCH64_SYSREG_ID_CREATE(3, 0, 12, 12, 7)
     437
     438/** NZCV - Status Flags - ??. */
     439#define ARMV8_AARCH64_SYSREG_NZCV                   ARMV8_AARCH64_SYSREG_ID_CREATE(3, 3, 4, 2, 0)
     440/** DAIF - Interrupt Mask Bits - ??. */
     441#define ARMV8_AARCH64_SYSREG_DAIF                   ARMV8_AARCH64_SYSREG_ID_CREATE(3, 3, 4, 2, 1)
     442/** SVCR - Streaming Vector Control Register - ??. */
     443#define ARMV8_AARCH64_SYSREG_SVCR                   ARMV8_AARCH64_SYSREG_ID_CREATE(3, 3, 4, 2, 2)
     444/** DIT - Data Independent Timing - ??. */
     445#define ARMV8_AARCH64_SYSREG_DIT                    ARMV8_AARCH64_SYSREG_ID_CREATE(3, 3, 4, 2, 5)
     446/** SSBS - Speculative Store Bypass Safe - ??. */
     447#define ARMV8_AARCH64_SYSREG_SSBS                   ARMV8_AARCH64_SYSREG_ID_CREATE(3, 3, 4, 2, 6)
     448/** TCO - Tag Check Override - ??. */
     449#define ARMV8_AARCH64_SYSREG_TCO                    ARMV8_AARCH64_SYSREG_ID_CREATE(3, 3, 4, 2, 7)
    437450
    438451/** CNTV_CTL_EL0 register - RW. */
     
    22262239/** A64: Insert pointer authentication code into LR using XZR and key B. */
    22272240#define ARMV8_A64_INSTR_PACIBZ      UINT32_C(0xd503235f)
     2241/** A64: Invert the carry flag (PSTATE.C). */
     2242#define ARMV8_A64_INSTR_CFINV       UINT32_C(0xd500401f)
    22282243
    22292244
     
    37443759
    37453760    return ((uint32_t)f64Bit       << 31)
    3746          | (UINT32_C(0x5ac00800))
     3761         | UINT32_C(0x5ac00800)
    37473762         | ((uint32_t)f64Bit       << 10)
    37483763         | (iRegSrc                <<  5)
     
    37643779
    37653780    return ((uint32_t)f64Bit       << 31)
    3766          | (UINT32_C(0x5ac00400))
     3781         | UINT32_C(0x5ac00400)
    37673782         | (iRegSrc                <<  5)
    37683783         | iRegDst;
     
    37703785
    37713786
     3787/**
     3788 * A64: Encodes SETF8 & SETF16.
     3789 *
     3790 * @returns The encoded instruction.
     3791 * @param   iRegResult  The register holding the result. SP is NOT valid.
     3792 * @param   f16Bit      Set for SETF16, clear for SETF8.
     3793 */
     3794DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrSetF8SetF16(uint32_t iRegResult, bool f16Bit)
     3795{
     3796    Assert(iRegResult < 32);
     3797
     3798    return UINT32_C(0x3a00080d)
     3799         | ((uint32_t)f16Bit       << 14)
     3800         | (iRegResult             <<  5);
     3801}
     3802
     3803
     3804/**
     3805 * A64: Encodes MRS (for reading a system register into a GPR).
     3806 *
     3807 * @returns The encoded instruction.
     3808 * @param   iRegDst     The register to put the result into. SP is NOT valid.
     3809 * @param   idSysReg    The system register ID (ARMV8_AARCH64_SYSREG_XXX),
     3810 *                      IPRT specific format, of the register to read.
     3811 */
     3812DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrMrs(uint32_t iRegDst, uint32_t idSysReg)
     3813{
     3814    Assert(iRegDst < 32);
     3815    Assert(idSysReg < RT_BIT_32(16) && (idSysReg & RT_BIT_32(15)));
     3816
     3817    /* Note. The top bit of idSysReg must always be set and is also set in
     3818             0xd5300000, otherwise we'll be encoding a different instruction. */
     3819    return UINT32_C(0xd5300000)
     3820         | (idSysReg << 5)
     3821         | iRegDst;
     3822}
     3823
     3824
     3825/**
     3826 * A64: Encodes MSR (for writing a GPR to a system register).
     3827 *
     3828 * @returns The encoded instruction.
     3829 * @param   iRegSrc     The register which value to write. SP is NOT valid.
     3830 * @param   idSysReg    The system register ID (ARMV8_AARCH64_SYSREG_XXX),
     3831 *                      IPRT specific format, of the register to write.
     3832 */
     3833DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrMsr(uint32_t iRegSrc, uint32_t idSysReg)
     3834{
     3835    Assert(iRegSrc < 32);
     3836    Assert(idSysReg < RT_BIT_32(16) && (idSysReg & RT_BIT_32(15)));
     3837
     3838    /* Note. The top bit of idSysReg must always be set and is also set in
     3839             0xd5100000, otherwise we'll be encoding a different instruction. */
     3840    return UINT32_C(0xd5100000)
     3841         | (idSysReg << 5)
     3842         | iRegSrc;
     3843}
     3844
     3845
    37723846/** @} */
    37733847
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstOneByte.cpp.h

    r103658 r103675  
    14631463{
    14641464    IEMOP_MNEMONIC2(MR, SUB, sub, Eb, Gb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES | IEMOPHINT_LOCK_ALLOWED);
    1465     IEMOP_BODY_BINARY_rm_r8_RW(iemAImpl_sub_u8, iemAImpl_sub_u8_locked, sub, 0, 0);
     1465    IEMOP_BODY_BINARY_rm_r8_RW(iemAImpl_sub_u8, iemAImpl_sub_u8_locked, sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
    14661466}
    14671467
     
    14751475{
    14761476    IEMOP_MNEMONIC2(MR, SUB, sub, Ev, Gv, DISOPTYPE_HARMLESS, IEMOPHINT_LOCK_ALLOWED);
    1477     IEMOP_BODY_BINARY_rm_rv_RW(    iemAImpl_sub_u16,        iemAImpl_sub_u32,        iemAImpl_sub_u64,       sub, 0, 0);
     1477    IEMOP_BODY_BINARY_rm_rv_RW(    iemAImpl_sub_u16,        iemAImpl_sub_u32,        iemAImpl_sub_u64,       sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64, 0);
    14781478    IEMOP_BODY_BINARY_rm_rv_LOCKED(iemAImpl_sub_u16_locked, iemAImpl_sub_u32_locked, iemAImpl_sub_u64_locked);
    14791479}
     
    14881488{
    14891489    IEMOP_MNEMONIC2(RM, SUB, sub, Gb, Eb, DISOPTYPE_HARMLESS, IEMOPHINT_IGNORES_OP_SIZES);
    1490     IEMOP_BODY_BINARY_r8_rm(iemAImpl_sub_u8, sub, 0);
     1490    IEMOP_BODY_BINARY_r8_rm(iemAImpl_sub_u8, sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
    14911491}
    14921492
     
    15011501    IEMOP_MNEMONIC2(RM, SUB, sub, Gv, Ev, DISOPTYPE_HARMLESS, 0);
    15021502    uint8_t bRm; IEM_OPCODE_GET_NEXT_U8(&bRm);
    1503     IEMOP_BODY_BINARY_rv_rm(bRm, iemAImpl_sub_u16, iemAImpl_sub_u32, iemAImpl_sub_u64, 1, 0, sub, 0);
     1503    IEMOP_BODY_BINARY_rv_rm(bRm, iemAImpl_sub_u16, iemAImpl_sub_u32, iemAImpl_sub_u64, 1, 0, sub, RT_ARCH_VAL_AMD64 | RT_ARCH_VAL_ARM64);
    15041504}
    15051505
  • 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