VirtualBox

Changeset 94170 in vbox for trunk/src


Ignore:
Timestamp:
Mar 11, 2022 1:43:59 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
150426
Message:

VMM/IEM: AMD eflags for mul,imul,div and idiv. bugref:9898

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

Legend:

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

    r94169 r94170  
    16311631 * MUL
    16321632 */
    1633 # define EMIT_MUL(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnMul) \
    1634 IEM_DECL_IMPL_DEF(int, iemAImpl_mul_u ## a_cBitsWidth, a_Args) \
     1633# define EMIT_MUL_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnMul, a_Suffix, a_fIntelFlags) \
     1634IEM_DECL_IMPL_DEF(int, RT_CONCAT3(iemAImpl_mul_u,a_cBitsWidth,a_Suffix), a_Args) \
    16351635{ \
    16361636    RTUINT ## a_cBitsWidth2x ## U Result; \
     
    16381638    a_fnStore(Result); \
    16391639    \
    1640     /* MUL EFLAGS according to Skylake (similar to IMUL). */ \
    1641     uint32_t fEfl = *pfEFlags & ~(X86_EFL_SF | X86_EFL_CF | X86_EFL_OF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_PF); \
    1642     if (Result.s.Lo & RT_BIT_64(a_cBitsWidth - 1)) \
    1643         fEfl |= X86_EFL_SF; \
    1644     fEfl |= g_afParity[Result.s.Lo & 0xff]; \
    1645     if (Result.s.Hi != 0) \
    1646         fEfl |= X86_EFL_CF | X86_EFL_OF; \
     1640    /* Calc EFLAGS: */ \
     1641    uint32_t fEfl = *pfEFlags; \
     1642    if (a_fIntelFlags) \
     1643    { /* Intel: 6700K and 10980XE behavior */ \
     1644        fEfl &= ~(X86_EFL_SF | X86_EFL_CF | X86_EFL_OF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_PF); \
     1645        if (Result.s.Lo & RT_BIT_64(a_cBitsWidth - 1)) \
     1646            fEfl |= X86_EFL_SF; \
     1647        fEfl |= g_afParity[Result.s.Lo & 0xff]; \
     1648        if (Result.s.Hi != 0) \
     1649            fEfl |= X86_EFL_CF | X86_EFL_OF; \
     1650    } \
     1651    else \
     1652    { /* AMD: 3990X */ \
     1653        if (Result.s.Hi != 0) \
     1654            fEfl |= X86_EFL_CF | X86_EFL_OF; \
     1655        else \
     1656            fEfl &= ~(X86_EFL_CF | X86_EFL_OF); \
     1657    } \
    16471658    *pfEFlags = fEfl; \
    16481659    return 0; \
    16491660} \
    1650 IEM_DECL_IMPL_DEF(int, iemAImpl_mul_u ## a_cBitsWidth ## _intel, a_Args) \
    1651 { \
    1652     return iemAImpl_mul_u ## a_cBitsWidth a_CallArgs; \
    1653 } \
    1654 IEM_DECL_IMPL_DEF(int, iemAImpl_mul_u ## a_cBitsWidth ## _amd, a_Args) \
    1655 { \
    1656     RTUINT ## a_cBitsWidth2x ## U Result; \
    1657     a_fnMul(Result, a_fnLoadF1(), uFactor, a_cBitsWidth2x); \
    1658     a_fnStore(Result); \
    1659     \
    1660     /* MUL EFLAGS according to Skylake (similar to IMUL). */ \
    1661     uint32_t fEfl = *pfEFlags & ~(X86_EFL_SF | X86_EFL_CF | X86_EFL_OF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_PF); \
    1662     if (Result.s.Lo & RT_BIT_64(a_cBitsWidth - 1)) \
    1663         fEfl |= X86_EFL_SF; \
    1664     fEfl |= g_afParity[Result.s.Lo & 0xff]; /* (Skylake behaviour) */ \
    1665     if (Result.s.Hi != 0) \
    1666         fEfl |= X86_EFL_CF | X86_EFL_OF; \
    1667     *pfEFlags = fEfl; \
    1668     return 0; \
    1669 }
     1661
     1662# define EMIT_MUL(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnMul) \
     1663    EMIT_MUL_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnMul, RT_NOTHING, 1) \
     1664    EMIT_MUL_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnMul, _intel,     1) \
     1665    EMIT_MUL_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnMul, _amd,       0) \
    16701666
    16711667EMIT_MUL(64, 128, (uint64_t *puA, uint64_t *puD, uint64_t uFactor, uint32_t *pfEFlags), (puA, puD, uFactor, pfEFlags),
     
    16891685 * as per the lower half of the result.
    16901686 */
    1691 # define EMIT_IMUL(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnNeg, a_fnMul) \
    1692 IEM_DECL_IMPL_DEF(int, iemAImpl_imul_u ## a_cBitsWidth,a_Args) \
     1687# define EMIT_IMUL_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnNeg, a_fnMul, \
     1688                         a_Suffix, a_fIntelFlags) \
     1689IEM_DECL_IMPL_DEF(int, RT_CONCAT3(iemAImpl_imul_u,a_cBitsWidth,a_Suffix),a_Args) \
    16931690{ \
    16941691    RTUINT ## a_cBitsWidth2x ## U Result; \
     
    17341731    a_fnStore(Result); \
    17351732    \
    1736     fEfl &= ~(X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_PF); \
    1737     if (Result.s.Lo & RT_BIT_64(a_cBitsWidth - 1)) \
    1738         fEfl |= X86_EFL_SF;  \
    1739     fEfl |= g_afParity[Result.s.Lo & 0xff]; \
     1733    if (a_fIntelFlags) \
     1734    { \
     1735        fEfl &= ~(X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_PF); \
     1736        if (Result.s.Lo & RT_BIT_64(a_cBitsWidth - 1)) \
     1737            fEfl |= X86_EFL_SF;  \
     1738        fEfl |= g_afParity[Result.s.Lo & 0xff]; \
     1739    } \
    17401740    *pfEFlags = fEfl; \
    17411741    return 0; \
    1742 } \
    1743 \
    1744 IEM_DECL_IMPL_DEF(int, iemAImpl_imul_u ## a_cBitsWidth ## _intel,a_Args) \
    1745 { \
    1746     return iemAImpl_imul_u ## a_cBitsWidth a_CallArgs; \
    1747 } \
    1748 \
    1749 IEM_DECL_IMPL_DEF(int, iemAImpl_imul_u ## a_cBitsWidth ## _amd,a_Args) \
    1750 { \
    1751     RTUINT ## a_cBitsWidth2x ## U Result; \
    1752     /* The SF, ZF, AF and PF flags are "undefined". AMD (3990x) leaves these \
    1753        flags as is - at least for the two op version. Whereas Intel skylake \
    1754        always clear AF and ZF and calculates SF and PF as per the lower half \
    1755        of the result. */ \
    1756     uint32_t fEfl = *pfEFlags & ~(X86_EFL_CF | X86_EFL_OF); \
    1757     \
    1758     uint ## a_cBitsWidth ## _t const uFactor1 = a_fnLoadF1(); \
    1759     if (!(uFactor1 & RT_BIT_64(a_cBitsWidth - 1))) \
    1760     { \
    1761         if (!(uFactor2 & RT_BIT_64(a_cBitsWidth - 1))) \
    1762         { \
    1763             a_fnMul(Result, uFactor1, uFactor2, a_cBitsWidth2x); \
    1764             if (Result.s.Hi != 0 || Result.s.Lo >= RT_BIT_64(a_cBitsWidth - 1)) \
    1765                 fEfl |= X86_EFL_CF | X86_EFL_OF; \
    1766         } \
    1767         else \
    1768         { \
    1769             uint ## a_cBitsWidth ## _t const uPositiveFactor2 = UINT ## a_cBitsWidth ## _C(0) - uFactor2; \
    1770             a_fnMul(Result, uFactor1, uPositiveFactor2, a_cBitsWidth2x); \
    1771             if (Result.s.Hi != 0 || Result.s.Lo > RT_BIT_64(a_cBitsWidth - 1)) \
    1772                 fEfl |= X86_EFL_CF | X86_EFL_OF; \
    1773             a_fnNeg(Result, a_cBitsWidth2x); \
    1774         } \
    1775     } \
    1776     else \
    1777     { \
    1778         if (!(uFactor2 & RT_BIT_64(a_cBitsWidth - 1))) \
    1779         { \
    1780             uint ## a_cBitsWidth ## _t const uPositiveFactor1 = UINT ## a_cBitsWidth ## _C(0) - uFactor1; \
    1781             a_fnMul(Result, uPositiveFactor1, uFactor2, a_cBitsWidth2x); \
    1782             if (Result.s.Hi != 0 || Result.s.Lo > RT_BIT_64(a_cBitsWidth - 1)) \
    1783                 fEfl |= X86_EFL_CF | X86_EFL_OF; \
    1784             a_fnNeg(Result, a_cBitsWidth2x); \
    1785         } \
    1786         else \
    1787         { \
    1788             uint ## a_cBitsWidth ## _t const uPositiveFactor1 = UINT ## a_cBitsWidth ## _C(0) - uFactor1; \
    1789             uint ## a_cBitsWidth ## _t const uPositiveFactor2 = UINT ## a_cBitsWidth ## _C(0) - uFactor2; \
    1790             a_fnMul(Result, uPositiveFactor1, uPositiveFactor2, a_cBitsWidth2x); \
    1791             if (Result.s.Hi != 0 || Result.s.Lo >= RT_BIT_64(a_cBitsWidth - 1)) \
    1792                 fEfl |= X86_EFL_CF | X86_EFL_OF; \
    1793         } \
    1794     } \
    1795     a_fnStore(Result); \
    1796     *pfEFlags = fEfl; \
    1797     return 0; \
    1798 }
     1742}
     1743# define EMIT_IMUL(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnNeg, a_fnMul) \
     1744    EMIT_IMUL_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnNeg, a_fnMul, RT_NOTHING, 1) \
     1745    EMIT_IMUL_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnNeg, a_fnMul, _intel,     1) \
     1746    EMIT_IMUL_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoadF1, a_fnStore, a_fnNeg, a_fnMul, _amd,       0)
     1747
    17991748EMIT_IMUL(64, 128, (uint64_t *puA, uint64_t *puD, uint64_t uFactor2, uint32_t *pfEFlags), (puA, puD, uFactor2, pfEFlags),
    18001749          MUL_LOAD_F1, MUL_STORE, MULDIV_NEG_U128, MULDIV_MUL_U128)
     
    18421791 * DIV
    18431792 */
    1844 # define EMIT_DIV(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnDivRem) \
    1845 IEM_DECL_IMPL_DEF(int, iemAImpl_div_u ## a_cBitsWidth,a_Args) \
     1793# define EMIT_DIV_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnDivRem, \
     1794                        a_Suffix, a_fIntelFlags) \
     1795IEM_DECL_IMPL_DEF(int, RT_CONCAT3(iemAImpl_div_u,a_cBitsWidth,a_Suffix),a_Args) \
    18461796{ \
    1847     /* Note! Skylake leaves all flags alone. */ \
    1848     RT_NOREF_PV(pfEFlags); \
    1849     \
    18501797    RTUINT ## a_cBitsWidth2x ## U Dividend; \
    18511798    a_fnLoad(Dividend); \
     
    18561803        a_fnDivRem(Quotient, Remainder, Dividend, uDivisor); \
    18571804        a_fnStore(Quotient.s.Lo, Remainder.s.Lo); \
    1858         /** @todo research the undefined DIV flags. */ \
     1805        \
     1806        /* Calc EFLAGS: Intel 6700K and 10980XE leaves them alone.  AMD 3990X sets AF and clears PF, ZF and SF. */ \
     1807        if (!a_fIntelFlags) \
     1808            *pfEFlags = (*pfEFlags & ~(X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF)) | X86_EFL_AF; \
    18591809        return 0; \
    18601810    } \
    18611811    /* #DE */ \
    18621812    return -1; \
    1863 } \
    1864 \
    1865 IEM_DECL_IMPL_DEF(int, iemAImpl_div_u ## a_cBitsWidth ## _intel,a_Args) \
    1866 { \
    1867     return iemAImpl_div_u ## a_cBitsWidth a_CallArgs; \
    1868 } \
    1869 \
    1870 IEM_DECL_IMPL_DEF(int, iemAImpl_div_u ## a_cBitsWidth ## _amd,a_Args) \
    1871 { \
    1872     /* Note! Skylake leaves all flags alone. */ \
    1873     RT_NOREF_PV(pfEFlags); \
    1874     \
    1875     RTUINT ## a_cBitsWidth2x ## U Dividend; \
    1876     a_fnLoad(Dividend); \
    1877     if (   uDivisor != 0 \
    1878         && Dividend.s.Hi < uDivisor) \
    1879     { \
    1880         RTUINT ## a_cBitsWidth2x ## U Remainder, Quotient; \
    1881         a_fnDivRem(Quotient, Remainder, Dividend, uDivisor); \
    1882         a_fnStore(Quotient.s.Lo, Remainder.s.Lo); \
    1883         /** @todo research the undefined DIV flags. */ \
    1884         return 0; \
    1885     } \
    1886     /* #DE */ \
    1887     return -1; \
    1888 }
     1813}
     1814# define EMIT_DIV(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnDivRem) \
     1815    EMIT_DIV_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnDivRem, RT_NOTHING, 1) \
     1816    EMIT_DIV_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnDivRem, _intel,     1) \
     1817    EMIT_DIV_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnDivRem, _amd,       0)
     1818
    18891819EMIT_DIV(64,128,(uint64_t *puA, uint64_t *puD, uint64_t uDivisor, uint32_t *pfEFlags), (puA, puD, uDivisor, pfEFlags),
    18901820         DIV_LOAD, DIV_STORE, MULDIV_MODDIV_U128)
     
    19011831/*
    19021832 * IDIV
    1903  */
    1904 # define EMIT_IDIV(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnNeg, a_fnDivRem) \
    1905 IEM_DECL_IMPL_DEF(int, iemAImpl_idiv_u ## a_cBitsWidth,a_Args) \
     1833 *
     1834 * EFLAGS are ignored and left as-is by Intel 6700K and 10980XE.  AMD 3990X will
     1835 * set AF and clear PF, ZF and SF just like it does for DIV.
     1836 *
     1837 */
     1838# define EMIT_IDIV_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnNeg, a_fnDivRem, \
     1839                         a_Suffix, a_fIntelFlags) \
     1840IEM_DECL_IMPL_DEF(int, RT_CONCAT3(iemAImpl_idiv_u,a_cBitsWidth,a_Suffix),a_Args) \
    19061841{ \
    19071842    /* Note! Skylake leaves all flags alone. */ \
    1908     RT_NOREF_PV(pfEFlags); \
    19091843    \
    19101844    /** @todo overflow checks */ \
     
    19401874                { \
    19411875                    a_fnStore(Quotient.s.Lo, Remainder.s.Lo); \
     1876                    if (!a_fIntelFlags) \
     1877                        *pfEFlags = (*pfEFlags & ~(X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF)) | X86_EFL_AF; \
    19421878                    return 0; \
    19431879                } \
     
    19491885                { \
    19501886                    a_fnStore(UINT ## a_cBitsWidth ## _C(0) - Quotient.s.Lo, UINT ## a_cBitsWidth ## _C(0) - Remainder.s.Lo); \
     1887                    if (!a_fIntelFlags) \
     1888                        *pfEFlags = (*pfEFlags & ~(X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF)) | X86_EFL_AF; \
    19511889                    return 0; \
    19521890                } \
     
    19611899                { \
    19621900                    a_fnStore(UINT ## a_cBitsWidth ## _C(0) - Quotient.s.Lo, Remainder.s.Lo); \
     1901                    if (!a_fIntelFlags) \
     1902                        *pfEFlags = (*pfEFlags & ~(X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF)) | X86_EFL_AF; \
    19631903                    return 0; \
    19641904                } \
     
    19701910                { \
    19711911                    a_fnStore(Quotient.s.Lo, UINT ## a_cBitsWidth ## _C(0) - Remainder.s.Lo); \
     1912                    if (!a_fIntelFlags) \
     1913                        *pfEFlags = (*pfEFlags & ~(X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF)) | X86_EFL_AF; \
    19721914                    return 0; \
    19731915                } \
     
    19771919    /* #DE */ \
    19781920    return -1; \
    1979 } \
    1980 \
    1981 IEM_DECL_IMPL_DEF(int, iemAImpl_idiv_u ## a_cBitsWidth ## _intel,a_Args) \
    1982 { \
    1983     return iemAImpl_idiv_u ## a_cBitsWidth a_CallArgs; \
    1984 } \
    1985 \
    1986 IEM_DECL_IMPL_DEF(int, iemAImpl_idiv_u ## a_cBitsWidth ## _amd,a_Args) \
    1987 { \
    1988     /* Note! Skylake leaves all flags alone. */ \
    1989     RT_NOREF_PV(pfEFlags); \
    1990     \
    1991     /** @todo overflow checks */ \
    1992     if (uDivisor != 0) \
    1993     { \
    1994         /* \
    1995          * Convert to unsigned division. \
    1996          */ \
    1997         RTUINT ## a_cBitsWidth2x ## U Dividend; \
    1998         a_fnLoad(Dividend); \
    1999         bool const fSignedDividend = RT_BOOL(Dividend.s.Hi & RT_BIT_64(a_cBitsWidth - 1)); \
    2000         if (fSignedDividend) \
    2001             a_fnNeg(Dividend, a_cBitsWidth2x); \
    2002         \
    2003         uint ## a_cBitsWidth ## _t uDivisorPositive; \
    2004         if (!(uDivisor & RT_BIT_64(a_cBitsWidth - 1))) \
    2005             uDivisorPositive = uDivisor; \
    2006         else \
    2007             uDivisorPositive = UINT ## a_cBitsWidth ## _C(0) - uDivisor; \
    2008         \
    2009         RTUINT ## a_cBitsWidth2x ## U Remainder, Quotient; \
    2010         a_fnDivRem(Quotient, Remainder, Dividend, uDivisorPositive); \
    2011         \
    2012         /* \
    2013          * Setup the result, checking for overflows. \
    2014          */ \
    2015         if (!(uDivisor & RT_BIT_64(a_cBitsWidth - 1))) \
    2016         { \
    2017             if (!fSignedDividend) \
    2018             { \
    2019                 /* Positive divisor, positive dividend => result positive. */ \
    2020                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint ## a_cBitsWidth ## _t)INT ## a_cBitsWidth ## _MAX) \
    2021                 { \
    2022                     a_fnStore(Quotient.s.Lo, Remainder.s.Lo); \
    2023                     return 0; \
    2024                 } \
    2025             } \
    2026             else \
    2027             { \
    2028                 /* Positive divisor, negative dividend => result negative. */ \
    2029                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= RT_BIT_64(a_cBitsWidth - 1)) \
    2030                 { \
    2031                     a_fnStore(UINT ## a_cBitsWidth ## _C(0) - Quotient.s.Lo, UINT ## a_cBitsWidth ## _C(0) - Remainder.s.Lo); \
    2032                     return 0; \
    2033                 } \
    2034             } \
    2035         } \
    2036         else \
    2037         { \
    2038             if (!fSignedDividend) \
    2039             { \
    2040                 /* Negative divisor, positive dividend => negative quotient, positive remainder. */ \
    2041                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= RT_BIT_64(a_cBitsWidth - 1)) \
    2042                 { \
    2043                     a_fnStore(UINT ## a_cBitsWidth ## _C(0) - Quotient.s.Lo, Remainder.s.Lo); \
    2044                     return 0; \
    2045                 } \
    2046             } \
    2047             else \
    2048             { \
    2049                 /* Negative divisor, negative dividend => positive quotient, negative remainder. */ \
    2050                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint ## a_cBitsWidth ## _t)INT ## a_cBitsWidth ## _MAX) \
    2051                 { \
    2052                     a_fnStore(Quotient.s.Lo, UINT ## a_cBitsWidth ## _C(0) - Remainder.s.Lo); \
    2053                     return 0; \
    2054                 } \
    2055             } \
    2056         } \
    2057     } \
    2058     /* #DE */ \
    2059     return -1; \
    2060 }
     1921}
     1922# define EMIT_IDIV(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnNeg, a_fnDivRem) \
     1923    EMIT_IDIV_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnNeg, a_fnDivRem, RT_NOTHING, 1) \
     1924    EMIT_IDIV_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnNeg, a_fnDivRem, _intel,     1) \
     1925    EMIT_IDIV_INNER(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_CallArgs, a_fnLoad, a_fnStore, a_fnNeg, a_fnDivRem, _amd,       0)
    20611926
    20621927EMIT_IDIV(64,128,(uint64_t *puA, uint64_t *puD, uint64_t uDivisor, uint32_t *pfEFlags), (puA, puD, uDivisor, pfEFlags),
  • trunk/src/VBox/VMM/testcase/tstIEMAImpl.cpp

    r94169 r94170  
    15561556                            X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF),
    15571557    ENTRY_INTEL_EX(imul_u8, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF, 0),
    1558     ENTRY_AMD_EX(div_u8,    X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF,
    1559                             X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF),
     1558    ENTRY_AMD_EX(div_u8,    X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF, 0),
    15601559    ENTRY_INTEL_EX(div_u8,  X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF, 0),
    1561     ENTRY_AMD_EX(idiv_u8,   X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF,
    1562                             X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF),
     1560    ENTRY_AMD_EX(idiv_u8,   X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF, 0),
    15631561    ENTRY_INTEL_EX(idiv_u8, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF, 0),
    15641562};
     
    15941592    for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aMulDivU8); iFn++)
    15951593    {
    1596         if (   g_aMulDivU8[iFn].idxCpuEflFlavour != IEMTARGETCPU_EFL_BEHAVIOR_NATIVE
    1597             && g_aMulDivU8[iFn].idxCpuEflFlavour != g_idxCpuEflFlavour)
    1598             continue;
    1599 
    16001594        RTTestSub(g_hTest, g_aMulDivU8[iFn].pszName);
    16011595        MULDIVU8_TEST_T const * const paTests = g_aMulDivU8[iFn].paTests;
    16021596        uint32_t const                cTests  = g_aMulDivU8[iFn].cTests;
    16031597        uint32_t const                fEflIgn = g_aMulDivU8[iFn].uExtra;
    1604         for (uint32_t iTest = 0; iTest < cTests; iTest++ )
     1598        PFNIEMAIMPLMULDIVU8           pfn     = g_aMulDivU8[iFn].pfn;
     1599        uint32_t const cVars = 1 + (g_aMulDivU8[iFn].idxCpuEflFlavour == g_idxCpuEflFlavour && g_aMulDivU8[iFn].pfnNative);
     1600        for (uint32_t iVar = 0; iVar < cVars; iVar++)
    16051601        {
    1606             uint32_t fEfl  = paTests[iTest].fEflIn;
    1607             uint16_t uDst  = paTests[iTest].uDstIn;
    1608             int      rc    = g_aMulDivU8[iFn].pfn(&uDst, paTests[iTest].uSrcIn, &fEfl);
    1609             if (   uDst != paTests[iTest].uDstOut
    1610                 || (fEfl | fEflIgn) != (paTests[iTest].fEflOut | fEflIgn)
    1611                 || rc != paTests[iTest].rc)
    1612                 RTTestFailed(g_hTest, "#%02u: efl=%#08x dst=%#06RX16 src=%#04RX8\n"
    1613                                       "  -> efl=%#08x dst=%#06RX16 rc=%d\n"
    1614                                       "expected %#08x     %#06RX16    %d%s\n",
    1615                              iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uSrcIn,
    1616                              fEfl, uDst, rc, paTests[iTest].fEflOut, paTests[iTest].uDstOut, paTests[iTest].rc,
    1617                              EFlagsDiff(fEfl | fEflIgn, paTests[iTest].fEflOut | fEflIgn));
    1618             else
     1602            for (uint32_t iTest = 0; iTest < cTests; iTest++ )
    16191603            {
    1620                  *g_pu16  = paTests[iTest].uDstIn;
    1621                  *g_pfEfl = paTests[iTest].fEflIn;
    1622                  rc = g_aMulDivU8[iFn].pfn(g_pu16, paTests[iTest].uSrcIn, g_pfEfl);
    1623                  RTTEST_CHECK(g_hTest, *g_pu16  == paTests[iTest].uDstOut);
    1624                  RTTEST_CHECK(g_hTest, (*g_pfEfl | fEflIgn) == (paTests[iTest].fEflOut | fEflIgn));
    1625                  RTTEST_CHECK(g_hTest, rc  == paTests[iTest].rc);
     1604                uint32_t fEfl  = paTests[iTest].fEflIn;
     1605                uint16_t uDst  = paTests[iTest].uDstIn;
     1606                int      rc    = g_aMulDivU8[iFn].pfn(&uDst, paTests[iTest].uSrcIn, &fEfl);
     1607                if (   uDst != paTests[iTest].uDstOut
     1608                    || (fEfl | fEflIgn) != (paTests[iTest].fEflOut | fEflIgn)
     1609                    || rc != paTests[iTest].rc)
     1610                    RTTestFailed(g_hTest, "#%02u%s: efl=%#08x dst=%#06RX16 src=%#04RX8\n"
     1611                                          "  %s-> efl=%#08x dst=%#06RX16 rc=%d\n"
     1612                                          "%sexpected %#08x     %#06RX16    %d%s\n",
     1613                                 iTest, iVar ? "/n" : "", paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uSrcIn,
     1614                                 iVar ? "  " : "", fEfl, uDst, rc,
     1615                                 iVar ? "  " : "", paTests[iTest].fEflOut, paTests[iTest].uDstOut, paTests[iTest].rc,
     1616                                 EFlagsDiff(fEfl | fEflIgn, paTests[iTest].fEflOut | fEflIgn));
     1617                else
     1618                {
     1619                     *g_pu16  = paTests[iTest].uDstIn;
     1620                     *g_pfEfl = paTests[iTest].fEflIn;
     1621                     rc = g_aMulDivU8[iFn].pfn(g_pu16, paTests[iTest].uSrcIn, g_pfEfl);
     1622                     RTTEST_CHECK(g_hTest, *g_pu16  == paTests[iTest].uDstOut);
     1623                     RTTEST_CHECK(g_hTest, (*g_pfEfl | fEflIgn) == (paTests[iTest].fEflOut | fEflIgn));
     1624                     RTTEST_CHECK(g_hTest, rc  == paTests[iTest].rc);
     1625                }
    16261626            }
     1627            pfn = g_aMulDivU8[iFn].pfnNative;
    16271628        }
    16281629    }
     
    16721673} a_aSubTests [] = \
    16731674{ \
    1674     ENTRY_AMD_EX(mul_u ## a_cBits,    X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF, \
    1675                                       X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF /** @todo check out AMD flags */ ), \
     1675    ENTRY_AMD_EX(mul_u ## a_cBits,    X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF, 0), \
    16761676    ENTRY_INTEL_EX(mul_u ## a_cBits,  X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF, 0), \
    1677     ENTRY_AMD_EX(imul_u ## a_cBits,   X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF, \
    1678                                       X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), \
     1677    ENTRY_AMD_EX(imul_u ## a_cBits,   X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF, 0), \
    16791678    ENTRY_INTEL_EX(imul_u ## a_cBits, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF, 0), \
    1680     ENTRY_AMD_EX(div_u ## a_cBits,    X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF,  \
    1681                                       X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF), \
     1679    ENTRY_AMD_EX(div_u ## a_cBits,    X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF, 0), \
    16821680    ENTRY_INTEL_EX(div_u ## a_cBits,  X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF, 0), \
    1683     ENTRY_AMD_EX(idiv_u ## a_cBits,   X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF, \
    1684                                       X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF), \
     1681    ENTRY_AMD_EX(idiv_u ## a_cBits,   X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF, 0), \
    16851682    ENTRY_INTEL_EX(idiv_u ## a_cBits, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF, 0), \
    16861683}; \
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