VirtualBox

Changeset 93850 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Feb 19, 2022 1:11:56 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
150065
Message:

VMM/IEM: Reduced the code duplication for the DIV and IDIV C workers. bugref:9898

File:
1 edited

Legend:

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

    r93848 r93850  
    18331833
    18341834/*
     1835 * DIV and IDIV helpers.
     1836 *
     1837 * - The U64 versions must use 128-bit intermediates, so we need to abstract the
     1838 *   division step so we can select between using C operators and RTUInt128DivRem.
     1839 *
     1840 * - The U8 versions work on AX and returns output in AL + AH instead of xDX:xAX
     1841 *   and return xAX + xDX, so we need load and store wrappers to hide this.
     1842 */
     1843
     1844DECLINLINE(void) RTUInt128DivRemByU64(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pDividend, uint64_t u64Divisor)
     1845{
     1846# ifdef __GNUC__ /* GCC maybe really annoying in function. */
     1847    pQuotient->s.Lo = 0;
     1848    pQuotient->s.Hi = 0;
     1849# endif
     1850    RTUINT128U Divisor;
     1851    Divisor.s.Lo = u64Divisor;
     1852    Divisor.s.Hi = 0;
     1853    RTUInt128DivRem(pQuotient, pRemainder, pDividend, &Divisor);
     1854}
     1855
     1856# define DIV_LOAD(a_Dividend)  \
     1857    a_Dividend.s.Lo = *puA, a_Dividend.s.Hi = *puD
     1858# define DIV_LOAD_U8(a_Dividend) \
     1859    a_Dividend.u = *puAX
     1860
     1861# define DIV_STORE(a_Quotient, a_uReminder)    *puA  = (a_Quotient), *puD = (a_uReminder)
     1862# define DIV_STORE_U8(a_Quotient, a_uReminder) *puAX = (a_Quotient) | ((uint16_t)(a_uReminder) << 8)
     1863
     1864# define DIV_NEG(a_Value, a_cBitsWidth2x) \
     1865    (a_Value).u = UINT ## a_cBitsWidth2x ## _C(0) - (a_Value).u
     1866# define DIV_NEG_U128(a_Value, a_cBitsWidth2x) \
     1867    RTUInt128AssignNeg(&(a_Value))
     1868
     1869# define DIV_DO_DIVREM(a_Quotient, a_Remainder, a_Dividend, a_uDivisor) \
     1870    a_Quotient.u = (a_Dividend).u / (a_uDivisor), \
     1871    a_Remainder.u = (a_Dividend).u % (a_uDivisor)
     1872# define DIV_DO_DIVREM_U128(a_Quotient, a_Remainder, a_Dividend, a_uDivisor) \
     1873    RTUInt128DivRemByU64(&a_Quotient, &a_Remainder, &a_Dividend, a_uDivisor)
     1874
     1875
     1876/*
    18351877 * DIV
    18361878 */
    1837 
    1838 IEM_DECL_IMPL_DEF(int, iemAImpl_div_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Divisor, uint32_t *pfEFlags))
    1839 {
    1840     /* Note! Skylake leaves all flags alone. */
    1841     RT_NOREF_PV(pfEFlags);
    1842 
    1843     if (   u64Divisor != 0
    1844         && *pu64RDX < u64Divisor)
    1845     {
    1846         RTUINT128U Dividend;
    1847         Dividend.s.Lo = *pu64RAX;
    1848         Dividend.s.Hi = *pu64RDX;
    1849 
    1850         RTUINT128U Divisor;
    1851         Divisor.s.Lo = u64Divisor;
    1852         Divisor.s.Hi = 0;
    1853 
    1854         RTUINT128U Remainder;
    1855         RTUINT128U Quotient;
    1856 # ifdef __GNUC__ /* GCC maybe really annoying in function. */
    1857         Quotient.s.Lo = 0;
    1858         Quotient.s.Hi = 0;
    1859 # endif
    1860         RTUInt128DivRem(&Quotient, &Remainder, &Dividend, &Divisor);
    1861         Assert(Quotient.s.Hi == 0);
    1862         Assert(Remainder.s.Hi == 0);
    1863 
    1864         *pu64RAX = Quotient.s.Lo;
    1865         *pu64RDX = Remainder.s.Lo;
    1866         /** @todo research the undefined DIV flags. */
    1867         return 0;
    1868 
    1869     }
    1870     /* #DE */
    1871     return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    1872 }
    1873 
    1874 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY)
    1875 
    1876 IEM_DECL_IMPL_DEF(int, iemAImpl_div_u32,(uint32_t *pu32RAX, uint32_t *pu32RDX, uint32_t u32Divisor, uint32_t *pfEFlags))
    1877 {
    1878     /* Note! Skylake leaves all flags alone. */
    1879     RT_NOREF_PV(pfEFlags);
    1880 
    1881     if (   u32Divisor != 0
    1882         && *pu32RDX < u32Divisor)
    1883     {
    1884         RTUINT64U Dividend;
    1885         Dividend.s.Lo = *pu32RAX;
    1886         Dividend.s.Hi = *pu32RDX;
    1887 
    1888         RTUINT64U Remainder;
    1889         RTUINT64U Quotient;
    1890         Quotient.u  = Dividend.u / u32Divisor;
    1891         Remainder.u = Dividend.u % u32Divisor;
    1892 
    1893         *pu32RAX = Quotient.s.Lo;
    1894         *pu32RDX = Remainder.s.Lo;
    1895         /** @todo research the undefined DIV flags. */
    1896         return 0;
    1897 
    1898     }
    1899     /* #DE */
    1900     return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    1901 }
    1902 
    1903 
    1904 IEM_DECL_IMPL_DEF(int, iemAImpl_div_u16,(uint16_t *pu16RAX, uint16_t *pu16RDX, uint16_t u16Divisor, uint32_t *pfEFlags))
    1905 {
    1906     /* Note! Skylake leaves all flags alone. */
    1907     RT_NOREF_PV(pfEFlags);
    1908 
    1909     if (   u16Divisor != 0
    1910         && *pu16RDX < u16Divisor)
    1911     {
    1912         RTUINT32U Dividend;
    1913         Dividend.s.Lo = *pu16RAX;
    1914         Dividend.s.Hi = *pu16RDX;
    1915 
    1916         RTUINT32U Remainder;
    1917         RTUINT32U Quotient;
    1918         Quotient.u  = Dividend.u / u16Divisor;
    1919         Remainder.u = Dividend.u % u16Divisor;
    1920 
    1921         *pu16RAX = Quotient.s.Lo;
    1922         *pu16RDX = Remainder.s.Lo;
    1923         /** @todo research the undefined DIV flags. */
    1924         return 0;
    1925 
    1926     }
    1927     /* #DE */
    1928     return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    1929 }
    1930 
    1931 
    1932 IEM_DECL_IMPL_DEF(int, iemAImpl_div_u8,(uint8_t *pu8RAX, uint8_t *pu8RDX, uint8_t u8Divisor, uint32_t *pfEFlags))
    1933 {
    1934     /* Note! Skylake leaves all flags alone. */
    1935     RT_NOREF_PV(pfEFlags);
    1936 
    1937     if (   u8Divisor != 0
    1938         && *pu8RDX < u8Divisor)
    1939     {
    1940         RTUINT16U Dividend;
    1941         Dividend.s.Lo = *pu8RAX;
    1942         Dividend.s.Hi = *pu8RDX;
    1943 
    1944         RTUINT16U Remainder;
    1945         RTUINT16U Quotient;
    1946         Quotient.u  = Dividend.u / u8Divisor;
    1947         Remainder.u = Dividend.u % u8Divisor;
    1948 
    1949         *pu8RAX = Quotient.s.Lo;
    1950         *pu8RDX = Remainder.s.Lo;
    1951         /** @todo research the undefined DIV flags. */
    1952         return 0;
    1953 
    1954     }
    1955     /* #DE */
    1956     return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    1957 }
    1958 
     1879# define EMIT_DIV(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_fnLoad, a_fnStore, a_fnDivRem) \
     1880IEM_DECL_IMPL_DEF(int, iemAImpl_div_u ## a_cBitsWidth,a_Args) \
     1881{ \
     1882    /* Note! Skylake leaves all flags alone. */ \
     1883    RT_NOREF_PV(pfEFlags); \
     1884    \
     1885    RTUINT ## a_cBitsWidth2x ## U Dividend; \
     1886    a_fnLoad(Dividend); \
     1887    if (   uDivisor != 0 \
     1888        && Dividend.s.Hi < uDivisor) \
     1889    { \
     1890        RTUINT ## a_cBitsWidth2x ## U Remainder, Quotient; \
     1891        a_fnDivRem(Remainder, Quotient, Dividend, uDivisor); \
     1892        a_fnStore(Quotient.s.Lo, Remainder.s.Lo); \
     1893        /** @todo research the undefined DIV flags. */ \
     1894        return 0; \
     1895    } \
     1896    /* #DE */ \
     1897    return -1; \
     1898}
     1899EMIT_DIV(64,128,(uint64_t *puA, uint64_t *puD, uint64_t uDivisor, uint32_t *pfEFlags), DIV_LOAD, DIV_STORE, DIV_DO_DIVREM_U128);
     1900# if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY)
     1901EMIT_DIV(32,64, (uint32_t *puA, uint32_t *puD, uint32_t uDivisor, uint32_t *pfEFlags), DIV_LOAD, DIV_STORE, DIV_DO_DIVREM);
     1902EMIT_DIV(16,32, (uint16_t *puA, uint16_t *puD, uint16_t uDivisor, uint32_t *pfEFlags), DIV_LOAD, DIV_STORE, DIV_DO_DIVREM);
     1903EMIT_DIV(8,16,  (uint16_t *puAX, uint8_t uDivisor, uint32_t *pfEFlags), DIV_LOAD_U8, DIV_STORE_U8, DIV_DO_DIVREM);
    19591904# endif /* !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) */
    19601905
     
    19631908 * IDIV
    19641909 */
    1965 
    1966 IEM_DECL_IMPL_DEF(int, iemAImpl_idiv_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Divisor, uint32_t *pfEFlags))
    1967 {
    1968     /* Note! Skylake leaves all flags alone. */
    1969     RT_NOREF_PV(pfEFlags);
    1970 
    1971     /** @todo overflow checks   */
    1972     if (u64Divisor != 0)
    1973     {
    1974         /*
    1975          * Convert to unsigned division.
    1976          */
    1977         RTUINT128U Dividend;
    1978         Dividend.s.Lo = *pu64RAX;
    1979         Dividend.s.Hi = *pu64RDX;
    1980         if ((int64_t)*pu64RDX < 0)
    1981             RTUInt128AssignNeg(&Dividend);
    1982 
    1983         RTUINT128U Divisor;
    1984         Divisor.s.Hi = 0;
    1985         if ((int64_t)u64Divisor >= 0)
    1986             Divisor.s.Lo = u64Divisor;
    1987         else
    1988             Divisor.s.Lo = UINT64_C(0) - u64Divisor;
    1989 
    1990         RTUINT128U Remainder;
    1991         RTUINT128U Quotient;
    1992 # ifdef __GNUC__ /* GCC maybe really annoying. */
    1993         Quotient.s.Lo = 0;
    1994         Quotient.s.Hi = 0;
    1995 # endif
    1996         RTUInt128DivRem(&Quotient, &Remainder, &Dividend, &Divisor);
    1997 
    1998         /*
    1999          * Setup the result, checking for overflows.
    2000          */
    2001         if ((int64_t)u64Divisor >= 0)
    2002         {
    2003             if ((int64_t)*pu64RDX >= 0)
    2004             {
    2005                 /* Positive divisor, positive dividend => result positive. */
    2006                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint64_t)INT64_MAX)
    2007                 {
    2008                     *pu64RAX = Quotient.s.Lo;
    2009                     *pu64RDX = Remainder.s.Lo;
    2010                     return 0;
    2011                 }
    2012             }
    2013             else
    2014             {
    2015                 /* Positive divisor, positive dividend => result negative. */
    2016                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= UINT64_C(0x8000000000000000))
    2017                 {
    2018                     *pu64RAX = UINT64_C(0) - Quotient.s.Lo;
    2019                     *pu64RDX = UINT64_C(0) - Remainder.s.Lo;
    2020                     return 0;
    2021                 }
    2022             }
    2023         }
    2024         else
    2025         {
    2026             if ((int64_t)*pu64RDX >= 0)
    2027             {
    2028                 /* Negative divisor, positive dividend => negative quotient, positive remainder. */
    2029                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= UINT64_C(0x8000000000000000))
    2030                 {
    2031                     *pu64RAX = UINT64_C(0) - Quotient.s.Lo;
    2032                     *pu64RDX = Remainder.s.Lo;
    2033                     return 0;
    2034                 }
    2035             }
    2036             else
    2037             {
    2038                 /* Negative divisor, negative dividend => positive quotient, negative remainder. */
    2039                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint64_t)INT64_MAX)
    2040                 {
    2041                     *pu64RAX = Quotient.s.Lo;
    2042                     *pu64RDX = UINT64_C(0) - Remainder.s.Lo;
    2043                     return 0;
    2044                 }
    2045             }
    2046         }
    2047     }
    2048     /* #DE */
    2049     return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    2050 }
    2051 
    2052 # if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY)
    2053 
    2054 IEM_DECL_IMPL_DEF(int, iemAImpl_idiv_u32,(uint32_t *pu32RAX, uint32_t *pu32RDX, uint32_t u32Divisor, uint32_t *pfEFlags))
    2055 {
    2056     /* Note! Skylake leaves all flags alone. */
    2057     RT_NOREF_PV(pfEFlags);
    2058 
    2059     /** @todo overflow checks   */
    2060     if (u32Divisor != 0)
    2061     {
    2062         /*
    2063          * Convert to unsigned division.
    2064          */
    2065         RTUINT64U Dividend;
    2066         Dividend.s.Lo = *pu32RAX;
    2067         Dividend.s.Hi = *pu32RDX;
    2068         if ((int32_t)*pu32RDX < 0)
    2069             Dividend.u = UINT64_C(0) - Dividend.u;
    2070 
    2071         uint32_t u32DivisorPositive;
    2072         if ((int32_t)u32Divisor >= 0)
    2073             u32DivisorPositive = u32Divisor;
    2074         else
    2075             u32DivisorPositive = UINT32_C(0) - u32Divisor;
    2076 
    2077         RTUINT64U Remainder;
    2078         RTUINT64U Quotient;
    2079         Quotient.u  = Dividend.u / u32DivisorPositive;
    2080         Remainder.u = Dividend.u % u32DivisorPositive;
    2081 
    2082         /*
    2083          * Setup the result, checking for overflows.
    2084          */
    2085         if ((int32_t)u32Divisor >= 0)
    2086         {
    2087             if ((int32_t)*pu32RDX >= 0)
    2088             {
    2089                 /* Positive divisor, positive dividend => result positive. */
    2090                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint32_t)INT32_MAX)
    2091                 {
    2092                     *pu32RAX = Quotient.s.Lo;
    2093                     *pu32RDX = Remainder.s.Lo;
    2094                     return 0;
    2095                 }
    2096             }
    2097             else
    2098             {
    2099                 /* Positive divisor, positive dividend => result negative. */
    2100                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= RT_BIT_32(31))
    2101                 {
    2102                     *pu32RAX = UINT32_C(0) - Quotient.s.Lo;
    2103                     *pu32RDX = UINT32_C(0) - Remainder.s.Lo;
    2104                     return 0;
    2105                 }
    2106             }
    2107         }
    2108         else
    2109         {
    2110             if ((int32_t)*pu32RDX >= 0)
    2111             {
    2112                 /* Negative divisor, positive dividend => negative quotient, positive remainder. */
    2113                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= RT_BIT_32(31))
    2114                 {
    2115                     *pu32RAX = UINT32_C(0) - Quotient.s.Lo;
    2116                     *pu32RDX = Remainder.s.Lo;
    2117                     return 0;
    2118                 }
    2119             }
    2120             else
    2121             {
    2122                 /* Negative divisor, negative dividend => positive quotient, negative remainder. */
    2123                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint32_t)INT32_MAX)
    2124                 {
    2125                     *pu32RAX = Quotient.s.Lo;
    2126                     *pu32RDX = UINT32_C(0) - Remainder.s.Lo;
    2127                     return 0;
    2128                 }
    2129             }
    2130         }
    2131     }
    2132     /* #DE */
    2133     return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    2134 }
    2135 
    2136 
    2137 IEM_DECL_IMPL_DEF(int, iemAImpl_idiv_u16,(uint16_t *pu16RAX, uint16_t *pu16RDX, uint16_t u16Divisor, uint32_t *pfEFlags))
    2138 {
    2139     /* Note! Skylake leaves all flags alone. */
    2140     RT_NOREF_PV(pfEFlags);
    2141 
    2142     if (u16Divisor != 0)
    2143     {
    2144         /*
    2145          * Convert to unsigned division.
    2146          */
    2147         RTUINT32U Dividend;
    2148         Dividend.s.Lo = *pu16RAX;
    2149         Dividend.s.Hi = *pu16RDX;
    2150         if ((int16_t)*pu16RDX < 0)
    2151             Dividend.u = UINT32_C(0) - Dividend.u;
    2152 
    2153         uint16_t u16DivisorPositive;
    2154         if ((int16_t)u16Divisor >= 0)
    2155             u16DivisorPositive = u16Divisor;
    2156         else
    2157             u16DivisorPositive = UINT16_C(0) - u16Divisor;
    2158 
    2159         RTUINT32U Remainder;
    2160         RTUINT32U Quotient;
    2161         Quotient.u  = Dividend.u / u16DivisorPositive;
    2162         Remainder.u = Dividend.u % u16DivisorPositive;
    2163 
    2164         /*
    2165          * Setup the result, checking for overflows.
    2166          */
    2167         if ((int16_t)u16Divisor >= 0)
    2168         {
    2169             if ((int16_t)*pu16RDX >= 0)
    2170             {
    2171                 /* Positive divisor, positive dividend => result positive. */
    2172                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint16_t)INT16_MAX)
    2173                 {
    2174                     *pu16RAX = Quotient.s.Lo;
    2175                     *pu16RDX = Remainder.s.Lo;
    2176                     return 0;
    2177                 }
    2178             }
    2179             else
    2180             {
    2181                 /* Positive divisor, positive dividend => result negative. */
    2182                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= RT_BIT_32(15))
    2183                 {
    2184                     *pu16RAX = UINT16_C(0) - Quotient.s.Lo;
    2185                     *pu16RDX = UINT16_C(0) - Remainder.s.Lo;
    2186                     return 0;
    2187                 }
    2188             }
    2189         }
    2190         else
    2191         {
    2192             if ((int16_t)*pu16RDX >= 0)
    2193             {
    2194                 /* Negative divisor, positive dividend => negative quotient, positive remainder. */
    2195                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= RT_BIT_32(15))
    2196                 {
    2197                     *pu16RAX = UINT16_C(0) - Quotient.s.Lo;
    2198                     *pu16RDX = Remainder.s.Lo;
    2199                     return 0;
    2200                 }
    2201             }
    2202             else
    2203             {
    2204                 /* Negative divisor, negative dividend => positive quotient, negative remainder. */
    2205                 if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint16_t)INT16_MAX)
    2206                 {
    2207                     *pu16RAX = Quotient.s.Lo;
    2208                     *pu16RDX = UINT16_C(0) - Remainder.s.Lo;
    2209                     return 0;
    2210                 }
    2211             }
    2212         }
    2213     }
    2214     /* #DE */
    2215     return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    2216 }
    2217 
     1910# define EMIT_IDIV(a_cBitsWidth, a_cBitsWidth2x, a_Args, a_fnLoad, a_fnStore, a_fnNeg, a_fnDivRem) \
     1911IEM_DECL_IMPL_DEF(int, iemAImpl_idiv_u ## a_cBitsWidth,a_Args) \
     1912{ \
     1913    /* Note! Skylake leaves all flags alone. */ \
     1914    RT_NOREF_PV(pfEFlags); \
     1915    \
     1916    /** @todo overflow checks */ \
     1917    if (uDivisor != 0) \
     1918    { \
     1919        /* \
     1920         * Convert to unsigned division. \
     1921         */ \
     1922        RTUINT ## a_cBitsWidth2x ## U Dividend; \
     1923        a_fnLoad(Dividend); \
     1924        if ((int ## a_cBitsWidth ## _t)Dividend.s.Hi < 0) \
     1925            a_fnNeg(Dividend, a_cBitsWidth2x); \
     1926        \
     1927        uint ## a_cBitsWidth ## _t uDivisorPositive; \
     1928        if ((int ## a_cBitsWidth ## _t)uDivisor >= 0) \
     1929            uDivisorPositive = uDivisor; \
     1930        else \
     1931            uDivisorPositive = UINT ## a_cBitsWidth ## _C(0) - uDivisor; \
     1932        \
     1933        RTUINT ## a_cBitsWidth2x ## U Remainder, Quotient; \
     1934        a_fnDivRem(Remainder, Quotient, Dividend, uDivisorPositive); \
     1935        \
     1936        /* \
     1937         * Setup the result, checking for overflows. \
     1938         */ \
     1939        if ((int ## a_cBitsWidth ## _t)uDivisor >= 0) \
     1940        { \
     1941            if ((int ## a_cBitsWidth ## _t)Dividend.s.Hi >= 0) \
     1942            { \
     1943                /* Positive divisor, positive dividend => result positive. */ \
     1944                if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint ## a_cBitsWidth ## _t)INT ## a_cBitsWidth ## _MAX) \
     1945                { \
     1946                    a_fnStore(Quotient.s.Lo, Remainder.s.Lo); \
     1947                    return 0; \
     1948                } \
     1949            } \
     1950            else \
     1951            { \
     1952                /* Positive divisor, positive dividend => result negative. */ \
     1953                if (Quotient.s.Hi == 0 && Quotient.s.Lo <= RT_BIT_64(a_cBitsWidth - 1)) \
     1954                { \
     1955                    a_fnStore(UINT ## a_cBitsWidth ## _C(0) - Quotient.s.Lo, UINT ## a_cBitsWidth ## _C(0) - Remainder.s.Lo); \
     1956                    return 0; \
     1957                } \
     1958            } \
     1959        } \
     1960        else \
     1961        { \
     1962            if ((int ## a_cBitsWidth ## _t)Dividend.s.Hi >= 0) \
     1963            { \
     1964                /* Negative divisor, positive dividend => negative quotient, positive remainder. */ \
     1965                if (Quotient.s.Hi == 0 && Quotient.s.Lo <= RT_BIT_64(a_cBitsWidth - 1)) \
     1966                { \
     1967                    a_fnStore(UINT ## a_cBitsWidth ## _C(0) - Quotient.s.Lo, Remainder.s.Lo); \
     1968                    return 0; \
     1969                } \
     1970            } \
     1971            else \
     1972            { \
     1973                /* Negative divisor, negative dividend => positive quotient, negative remainder. */ \
     1974                if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint ## a_cBitsWidth ## _t)INT ## a_cBitsWidth ## _MAX) \
     1975                { \
     1976                    a_fnStore(Quotient.s.Lo, UINT ## a_cBitsWidth ## _C(0) - Remainder.s.Lo); \
     1977                    return 0; \
     1978                } \
     1979            } \
     1980        } \
     1981    } \
     1982    /* #DE */ \
     1983    return -1; \
     1984}
     1985EMIT_IDIV(64,128,(uint64_t *puA, uint64_t *puD, uint64_t uDivisor, uint32_t *pfEFlags), DIV_LOAD, DIV_STORE, DIV_NEG_U128, DIV_DO_DIVREM_U128)
     1986# if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY)
     1987EMIT_IDIV(32,64,(uint32_t *puA, uint32_t *puD, uint32_t uDivisor, uint32_t *pfEFlags), DIV_LOAD, DIV_STORE, DIV_NEG, DIV_DO_DIVREM)
     1988EMIT_IDIV(16,32,(uint16_t *puA, uint16_t *puD, uint16_t uDivisor, uint32_t *pfEFlags), DIV_LOAD, DIV_STORE, DIV_NEG, DIV_DO_DIVREM)
     1989EMIT_IDIV(8,16,(uint16_t *puAX, uint8_t uDivisor, uint32_t *pfEFlags),           DIV_LOAD_U8, DIV_STORE_U8, DIV_NEG, DIV_DO_DIVREM)
    22181990# endif /* !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) */
    22191991
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