VirtualBox

Changeset 101576 in vbox for trunk/src


Ignore:
Timestamp:
Oct 24, 2023 9:40:58 AM (16 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
159657
Message:

VMM/IEM: Native IEM_MC_IF_EFL_BITS_NE translation. bugref:10371

Location:
trunk/src/VBox/VMM
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py

    r101570 r101576  
    28922892    'IEM_MC_IF_EFL_BIT_SET_OR_BITS_NE':                          (McBlock.parseMcGenericCond,       True,  False, ),
    28932893    'IEM_MC_IF_EFL_BITS_EQ':                                     (McBlock.parseMcGenericCond,       True,  False, ),
    2894     'IEM_MC_IF_EFL_BITS_NE':                                     (McBlock.parseMcGenericCond,       True,  False, ),
     2894    'IEM_MC_IF_EFL_BITS_NE':                                     (McBlock.parseMcGenericCond,       True,  True, ),
    28952895    'IEM_MC_IF_EFL_NO_BITS_SET':                                 (McBlock.parseMcGenericCond,       True,  True,  ),
    28962896    'IEM_MC_IF_FCW_IM':                                          (McBlock.parseMcGenericCond,       True,  False, ),
  • trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp

    r101570 r101576  
    43754375
    43764376
     4377#define IEM_MC_IF_EFL_BITS_EQ(a_fBit1, a_fBit2)         \
     4378    off = iemNativeEmitIfEflagsTwoBitsComp(pReNative, off, a_fBit1, a_fBit2, false /*fNotEqual*/); \
     4379    AssertReturn(off != UINT32_MAX, UINT32_MAX); \
     4380    do {
     4381
     4382#define IEM_MC_IF_EFL_BITS_NE(a_fBit1, a_fBit2)         \
     4383    off = iemNativeEmitIfEflagsTwoBitsComp(pReNative, off, a_fBit1, a_fBit2, true /*fNotEqual*/); \
     4384    AssertReturn(off != UINT32_MAX, UINT32_MAX); \
     4385    do {
     4386
     4387/** Emits code for IEM_MC_IF_EFL_BITS_EQ and IEM_MC_IF_EFL_BITS_NE. */
     4388DECLINLINE(uint32_t) iemNativeEmitIfEflagsTwoBitsComp(PIEMRECOMPILERSTATE pReNative, uint32_t off,
     4389                                                      uint32_t fBit1InEfl, uint32_t fBit2InEfl, bool fNotEqual)
     4390{
     4391    PIEMNATIVECOND pEntry = iemNativeCondPushIf(pReNative);
     4392    AssertReturn(pEntry, UINT32_MAX);
     4393
     4394    /* Get the eflags. */
     4395    uint8_t const idxEflReg = iemNativeRegAllocTmpForGuestReg(pReNative, &off, kIemNativeGstReg_EFlags,
     4396                                                              kIemNativeGstRegUse_ReadOnly);
     4397    AssertReturn(idxEflReg != UINT8_MAX, UINT32_MAX);
     4398
     4399    unsigned const iBitNo1 = ASMBitFirstSetU32(fBit1InEfl) - 1;
     4400    Assert(RT_BIT_32(iBitNo1) == fBit1InEfl);
     4401
     4402    unsigned const iBitNo2 = ASMBitFirstSetU32(fBit2InEfl) - 1;
     4403    Assert(RT_BIT_32(iBitNo2) == fBit2InEfl);
     4404    Assert(iBitNo1 != iBitNo2);
     4405
     4406#ifdef RT_ARCH_AMD64
     4407    uint8_t const idxTmpReg = iemNativeRegAllocTmpImm(pReNative, &off, fBit1InEfl);
     4408    AssertReturn(idxTmpReg != UINT8_MAX, UINT32_MAX);
     4409
     4410    off = iemNativeEmitAndGpr32ByGpr32(pReNative, off, idxTmpReg, idxEflReg);
     4411    if (iBitNo1 > iBitNo2)
     4412        off = iemNativeEmitShiftGpr32Right(pReNative, off, idxTmpReg, iBitNo1 - iBitNo2);
     4413    else
     4414        off = iemNativeEmitShiftGpr32Left(pReNative, off, idxTmpReg, iBitNo2 - iBitNo1);
     4415    off = iemNativeEmitXorGpr32ByGpr32(pReNative, off, idxTmpReg, idxEflReg);
     4416
     4417    /* Test and jump. */
     4418    if (fNotEqual)
     4419        off = iemNativeEmitTestBitInGprAndJmpToLabelIfSet(pReNative, off, idxTmpReg, iBitNo1, pEntry->idxLabelElse);
     4420    else
     4421        off = iemNativeEmitTestBitInGprAndJmpToLabelIfNotSet(pReNative, off, idxTmpReg, iBitNo1, pEntry->idxLabelElse);
     4422
     4423    iemNativeRegFreeTmp(pReNative, idxTmpReg);
     4424
     4425#elif defined(RT_ARCH_ARM64)
     4426    uint8_t const idxTmpReg = iemNativeRegAllocTmp(pReNative, &off);
     4427    AssertReturn(idxTmpReg != UINT8_MAX, UINT32_MAX);
     4428
     4429    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 2);
     4430    AssertReturn(pu32CodeBuf, UINT32_MAX);
     4431
     4432    /* and tmpreg, eflreg, #1<<iBitNo1 */
     4433    pu32CodeBuf[off++] = Armv8A64MkInstrAndImm(idxTmpReg, idxEflReg, 0 /*uImm7SizeLen -> 32*/, 32 - iBitNo1, false /*f64Bit*/);
     4434
     4435    /* eeyore tmpreg, eflreg, LSL/LSR, #abs(iBitNo2 - iBitNo1) */
     4436    if (iBitNo1 > iBitNo2)
     4437        pu32CodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg, idxEflReg, false /*64bit*/,
     4438                                                iBitNo1 - iBitNo2, kArmv8A64InstrShift_Lsl);
     4439    else
     4440        pu32CodeBuf[off++] = Armv8A64MkInstrEor(idxTmpReg, idxTmpReg, idxEflReg, false /*64bit*/,
     4441                                                iBitNo2 - iBitNo1, kArmv8A64InstrShift_Lsr);
     4442
     4443    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     4444
     4445    /* Test and jump. */
     4446    if (fNotEqual)
     4447        off = iemNativeEmitTestBitInGprAndJmpToLabelIfSet(pReNative, off, idxTmpReg, iBitNo1, pEntry->idxLabelElse);
     4448    else
     4449        off = iemNativeEmitTestBitInGprAndJmpToLabelIfNotSet(pReNative, off, idxTmpReg, iBitNo1, pEntry->idxLabelElse);
     4450
     4451    iemNativeRegFreeTmp(pReNative, idxTmpReg);
     4452
     4453#else
     4454# error "Port me"
     4455#endif
     4456
     4457    /* Free but don't flush the EFlags register. */
     4458    iemNativeRegFreeTmp(pReNative, idxEflReg);
     4459
     4460    /* Make a copy of the core state now as we start the if-block. */
     4461    iemNativeCondStartIfBlock(pReNative, off);
     4462
     4463    return off;
     4464}
     4465
     4466
    43774467
    43784468/*********************************************************************************************************************************
  • trunk/src/VBox/VMM/include/IEMN8veRecompiler.h

    r101568 r101576  
    16831683
    16841684/**
     1685 * Emits code for AND'ing two 64-bit GPRs.
     1686 */
     1687DECLINLINE(uint32_t ) iemNativeEmitAndGprByGpr(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t iGprSrc)
     1688{
     1689#if defined(RT_ARCH_AMD64)
     1690    /* and Gv, Ev */
     1691    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3);
     1692    AssertReturn(pbCodeBuf, UINT32_MAX);
     1693    pbCodeBuf[off++] = X86_OP_REX_W | (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprSrc < 8 ? 0 : X86_OP_REX_B);
     1694    pbCodeBuf[off++] = 0x23;
     1695    pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGprDst & 7, iGprSrc & 7);
     1696
     1697#elif defined(RT_ARCH_ARM64)
     1698    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     1699    AssertReturn(pu32CodeBuf, UINT32_MAX);
     1700    pu32CodeBuf[off++] = Armv8A64MkInstrAnd(iGprDst, iGprDst, iGprSrc);
     1701
     1702#else
     1703# error "Port me"
     1704#endif
     1705    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     1706    return off;
     1707}
     1708
     1709
     1710/**
     1711 * Emits code for AND'ing two 32-bit GPRs.
     1712 */
     1713DECLINLINE(uint32_t ) iemNativeEmitAndGpr32ByGpr32(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t iGprSrc)
     1714{
     1715#if defined(RT_ARCH_AMD64)
     1716    /* and Gv, Ev */
     1717    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3);
     1718    AssertReturn(pbCodeBuf, UINT32_MAX);
     1719    if (iGprDst >= 8 || iGprSrc >= 8)
     1720        pbCodeBuf[off++] = (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprSrc < 8 ? 0 : X86_OP_REX_B);
     1721    pbCodeBuf[off++] = 0x23;
     1722    pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGprDst & 7, iGprSrc & 7);
     1723
     1724#elif defined(RT_ARCH_ARM64)
     1725    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     1726    AssertReturn(pu32CodeBuf, UINT32_MAX);
     1727    pu32CodeBuf[off++] = Armv8A64MkInstrAnd(iGprDst, iGprDst, iGprSrc, false /*f64Bit*/);
     1728
     1729#else
     1730# error "Port me"
     1731#endif
     1732    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     1733    return off;
     1734}
     1735
     1736
     1737/**
     1738 * Emits code for XOR'ing two 64-bit GPRs.
     1739 */
     1740DECLINLINE(uint32_t ) iemNativeEmitXorGprByGpr(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t iGprSrc)
     1741{
     1742#if defined(RT_ARCH_AMD64)
     1743    /* and Gv, Ev */
     1744    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3);
     1745    AssertReturn(pbCodeBuf, UINT32_MAX);
     1746    pbCodeBuf[off++] = X86_OP_REX_W | (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprSrc < 8 ? 0 : X86_OP_REX_B);
     1747    pbCodeBuf[off++] = 0x33;
     1748    pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGprDst & 7, iGprSrc & 7);
     1749
     1750#elif defined(RT_ARCH_ARM64)
     1751    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     1752    AssertReturn(pu32CodeBuf, UINT32_MAX);
     1753    pu32CodeBuf[off++] = Armv8A64MkInstrEor(iGprDst, iGprDst, iGprSrc);
     1754
     1755#else
     1756# error "Port me"
     1757#endif
     1758    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     1759    return off;
     1760}
     1761
     1762
     1763/**
     1764 * Emits code for XOR'ing two 32-bit GPRs.
     1765 */
     1766DECLINLINE(uint32_t ) iemNativeEmitXorGpr32ByGpr32(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t iGprSrc)
     1767{
     1768#if defined(RT_ARCH_AMD64)
     1769    /* and Gv, Ev */
     1770    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 3);
     1771    AssertReturn(pbCodeBuf, UINT32_MAX);
     1772    if (iGprDst >= 8 || iGprSrc >= 8)
     1773        pbCodeBuf[off++] = (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprSrc < 8 ? 0 : X86_OP_REX_B);
     1774    pbCodeBuf[off++] = 0x33;
     1775    pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGprDst & 7, iGprSrc & 7);
     1776
     1777#elif defined(RT_ARCH_ARM64)
     1778    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     1779    AssertReturn(pu32CodeBuf, UINT32_MAX);
     1780    pu32CodeBuf[off++] = Armv8A64MkInstrEor(iGprDst, iGprDst, iGprSrc, false /*f64Bit*/);
     1781
     1782#else
     1783# error "Port me"
     1784#endif
     1785    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     1786    return off;
     1787}
     1788
     1789
     1790/*********************************************************************************************************************************
     1791*   Shifting                                                                                                                     *
     1792*********************************************************************************************************************************/
     1793
     1794/**
     1795 * Emits code for shifting a GPR a fixed number of bits to the left.
     1796 */
     1797DECLINLINE(uint32_t ) iemNativeEmitShiftGprLeft(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t cShift)
     1798{
     1799    Assert(cShift > 0 && cShift < 64);
     1800
     1801#if defined(RT_ARCH_AMD64)
     1802    /* shl dst, cShift */
     1803    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 4);
     1804    AssertReturn(pbCodeBuf, UINT32_MAX);
     1805    pbCodeBuf[off++] = iGprDst < 8 ? X86_OP_REX_W : X86_OP_REX_W | X86_OP_REX_B;
     1806    if (cShift != 1)
     1807    {
     1808        pbCodeBuf[off++] = 0xc1;
     1809        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4, iGprDst & 7);
     1810        pbCodeBuf[off++] = cShift;
     1811    }
     1812    else
     1813    {
     1814        pbCodeBuf[off++] = 0xd1;
     1815        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4, iGprDst & 7);
     1816    }
     1817
     1818#elif defined(RT_ARCH_ARM64)
     1819    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     1820    AssertReturn(pu32CodeBuf, UINT32_MAX);
     1821    pu32CodeBuf[off++] = Armv8A64MkInstrLslImm(iGprDst, iGprDst, cShift);
     1822
     1823#else
     1824# error "Port me"
     1825#endif
     1826    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     1827    return off;
     1828}
     1829
     1830
     1831/**
     1832 * Emits code for shifting a 32-bit GPR a fixed number of bits to the left.
     1833 */
     1834DECLINLINE(uint32_t ) iemNativeEmitShiftGpr32Left(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t cShift)
     1835{
     1836    Assert(cShift > 0 && cShift < 32);
     1837
     1838#if defined(RT_ARCH_AMD64)
     1839    /* shl dst, cShift */
     1840    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 4);
     1841    AssertReturn(pbCodeBuf, UINT32_MAX);
     1842    if (iGprDst >= 8)
     1843        pbCodeBuf[off++] = X86_OP_REX_B;
     1844    if (cShift != 1)
     1845    {
     1846        pbCodeBuf[off++] = 0xc1;
     1847        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4, iGprDst & 7);
     1848        pbCodeBuf[off++] = cShift;
     1849    }
     1850    else
     1851    {
     1852        pbCodeBuf[off++] = 0xd1;
     1853        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 4, iGprDst & 7);
     1854    }
     1855
     1856#elif defined(RT_ARCH_ARM64)
     1857    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     1858    AssertReturn(pu32CodeBuf, UINT32_MAX);
     1859    pu32CodeBuf[off++] = Armv8A64MkInstrLslImm(iGprDst, iGprDst, cShift, false /*64Bit*/);
     1860
     1861#else
     1862# error "Port me"
     1863#endif
     1864    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     1865    return off;
     1866}
     1867
     1868
     1869/**
    16851870 * Emits code for (unsigned) shifting a GPR a fixed number of bits to the right.
    16861871 */
    16871872DECLINLINE(uint32_t ) iemNativeEmitShiftGprRight(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t cShift)
    16881873{
     1874    Assert(cShift > 0 && cShift < 64);
     1875
    16891876#if defined(RT_ARCH_AMD64)
    16901877    /* shr dst, cShift */
     
    16921879    AssertReturn(pbCodeBuf, UINT32_MAX);
    16931880    pbCodeBuf[off++] = iGprDst < 8 ? X86_OP_REX_W : X86_OP_REX_W | X86_OP_REX_B;
    1694     pbCodeBuf[off++] = 0xc0;
    1695     pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 5, iGprDst & 7);
    1696     pbCodeBuf[off++] = cShift;
    1697     Assert(cShift > 0 && cShift < 64);
     1881    if (cShift != 1)
     1882    {
     1883        pbCodeBuf[off++] = 0xc1;
     1884        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 5, iGprDst & 7);
     1885        pbCodeBuf[off++] = cShift;
     1886    }
     1887    else
     1888    {
     1889        pbCodeBuf[off++] = 0xd1;
     1890        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 5, iGprDst & 7);
     1891    }
    16981892
    16991893#elif defined(RT_ARCH_ARM64)
     
    17011895    AssertReturn(pu32CodeBuf, UINT32_MAX);
    17021896    pu32CodeBuf[off++] = Armv8A64MkInstrLsrImm(iGprDst, iGprDst, cShift);
     1897
    17031898#else
    17041899# error "Port me"
     
    17071902    return off;
    17081903}
     1904
     1905
     1906/**
     1907 * Emits code for (unsigned) shifting a 32-bit GPR a fixed number of bits to the
     1908 * right.
     1909 */
     1910DECLINLINE(uint32_t ) iemNativeEmitShiftGpr32Right(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t cShift)
     1911{
     1912    Assert(cShift > 0 && cShift < 32);
     1913
     1914#if defined(RT_ARCH_AMD64)
     1915    /* shr dst, cShift */
     1916    uint8_t *pbCodeBuf = iemNativeInstrBufEnsure(pReNative, off, 4);
     1917    AssertReturn(pbCodeBuf, UINT32_MAX);
     1918    if (iGprDst >= 8)
     1919        pbCodeBuf[off++] = X86_OP_REX_B;
     1920    if (cShift != 1)
     1921    {
     1922        pbCodeBuf[off++] = 0xc1;
     1923        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 5, iGprDst & 7);
     1924        pbCodeBuf[off++] = cShift;
     1925    }
     1926    else
     1927    {
     1928        pbCodeBuf[off++] = 0xd1;
     1929        pbCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 5, iGprDst & 7);
     1930    }
     1931
     1932#elif defined(RT_ARCH_ARM64)
     1933    uint32_t *pu32CodeBuf = iemNativeInstrBufEnsure(pReNative, off, 1);
     1934    AssertReturn(pu32CodeBuf, UINT32_MAX);
     1935    pu32CodeBuf[off++] = Armv8A64MkInstrLsrImm(iGprDst, iGprDst, cShift, false /*64Bit*/);
     1936
     1937#else
     1938# error "Port me"
     1939#endif
     1940    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     1941    return off;
     1942}
     1943
    17091944
    17101945
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