VirtualBox

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


Ignore:
Timestamp:
Feb 22, 2022 3:46:53 PM (3 years ago)
Author:
vboxsync
Message:

VMM/IEM: Corrected MUL, IMUL, DIV and IDIV instruction helpers (C versions); added tests for them. bugref:9898

File:
1 edited

Legend:

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

    r93887 r93888  
    15671567
    15681568# define DIV_STORE(a_Quotient, a_uReminder)    *puA  = (a_Quotient),    *puD = (a_uReminder)
    1569 # define DIV_STORE_U8(a_Quotient, a_uReminder) *puAX = (a_Quotient) | ((uint16_t)(a_uReminder) << 8)
     1569# define DIV_STORE_U8(a_Quotient, a_uReminder) *puAX = (uint8_t)(a_Quotient) | ((uint16_t)(a_uReminder) << 8)
    15701570
    15711571# define MUL_LOAD_F1()                         *puA
     
    16031603    \
    16041604    /* MUL EFLAGS according to Skylake (similar to IMUL). */ \
    1605     *pfEFlags &= ~(X86_EFL_SF | X86_EFL_CF | X86_EFL_OF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_PF); \
     1605    uint32_t fEfl = *pfEFlags & ~(X86_EFL_SF | X86_EFL_CF | X86_EFL_OF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_PF); \
    16061606    if (Result.s.Lo & RT_BIT_64(a_cBitsWidth - 1)) \
    1607         *pfEFlags |= X86_EFL_SF; \
    1608     *pfEFlags |= g_afParity[Result.s.Lo & 0xff]; /* (Skylake behaviour) */ \
     1607        fEfl |= X86_EFL_SF; \
     1608    fEfl |= g_afParity[Result.s.Lo & 0xff]; /* (Skylake behaviour) */ \
    16091609    if (Result.s.Hi != 0) \
    1610         *pfEFlags |= X86_EFL_CF | X86_EFL_OF; \
     1610        fEfl |= X86_EFL_CF | X86_EFL_OF; \
     1611    *pfEFlags = fEfl; \
    16111612    return 0; \
    16121613}
     
    16271628    RTUINT ## a_cBitsWidth2x ## U Result; \
    16281629    /* The SF, ZF, AF and PF flags are "undefined". AMD (3990x) leaves these \
    1629        flags as is. Whereas Intel skylake always clear AF and ZF and calculates \
    1630        SF and PF as per the lower half of the result. */ \
     1630       flags as is - at least for the two op version. Whereas Intel skylake \
     1631       always clear AF and ZF and calculates SF and PF as per the lower half \
     1632       of the result. */ \
    16311633    uint32_t fEfl = *pfEFlags & ~(X86_EFL_CF | X86_EFL_OF); \
    16321634    \
     
    16421644        else \
    16431645        { \
    1644             a_fnMul(Result, uFactor1, UINT ## a_cBitsWidth ## _C(0) - uFactor2, a_cBitsWidth2x); \
     1646            uint ## a_cBitsWidth ## _t const uPositiveFactor2 = UINT ## a_cBitsWidth ## _C(0) - uFactor2; \
     1647            a_fnMul(Result, uFactor1, uPositiveFactor2, a_cBitsWidth2x); \
    16451648            if (Result.s.Hi != 0 || Result.s.Lo > RT_BIT_64(a_cBitsWidth - 1)) \
    16461649                fEfl |= X86_EFL_CF | X86_EFL_OF; \
     
    16521655        if (!(uFactor2 & RT_BIT_64(a_cBitsWidth - 1))) \
    16531656        { \
    1654             a_fnMul(Result, UINT ## a_cBitsWidth ## _C(0) - uFactor1, uFactor2, a_cBitsWidth2x); \
     1657            uint ## a_cBitsWidth ## _t const uPositiveFactor1 = UINT ## a_cBitsWidth ## _C(0) - uFactor1; \
     1658            a_fnMul(Result, uPositiveFactor1, uFactor2, a_cBitsWidth2x); \
    16551659            if (Result.s.Hi != 0 || Result.s.Lo > RT_BIT_64(a_cBitsWidth - 1)) \
    16561660                fEfl |= X86_EFL_CF | X86_EFL_OF; \
     
    16591663        else \
    16601664        { \
    1661             /*a_fnMul(Result, UINT ## a_cBitsWidth ## _C(0) - uFactor1, UINT ## a_cBitsWidth ## _C(0) - uFactor2, a_cBitsWidth2x);*/ \
    1662             a_fnMul(Result, uFactor1, uFactor2, a_cBitsWidth2x); \
     1665            uint ## a_cBitsWidth ## _t const uPositiveFactor1 = UINT ## a_cBitsWidth ## _C(0) - uFactor1; \
     1666            uint ## a_cBitsWidth ## _t const uPositiveFactor2 = UINT ## a_cBitsWidth ## _C(0) - uFactor2; \
     1667            a_fnMul(Result, uPositiveFactor1, uPositiveFactor2, a_cBitsWidth2x); \
    16631668            if (Result.s.Hi != 0 || Result.s.Lo >= RT_BIT_64(a_cBitsWidth - 1)) \
    16641669                fEfl |= X86_EFL_CF | X86_EFL_OF; \
     
    17231728    { \
    17241729        RTUINT ## a_cBitsWidth2x ## U Remainder, Quotient; \
    1725         a_fnDivRem(Remainder, Quotient, Dividend, uDivisor); \
     1730        a_fnDivRem(Quotient, Remainder, Dividend, uDivisor); \
    17261731        a_fnStore(Quotient.s.Lo, Remainder.s.Lo); \
    17271732        /** @todo research the undefined DIV flags. */ \
     
    17561761        RTUINT ## a_cBitsWidth2x ## U Dividend; \
    17571762        a_fnLoad(Dividend); \
    1758         if ((int ## a_cBitsWidth ## _t)Dividend.s.Hi < 0) \
     1763        bool const fSignedDividend = RT_BOOL(Dividend.s.Hi & RT_BIT_64(a_cBitsWidth - 1)); \
     1764        if (fSignedDividend) \
    17591765            a_fnNeg(Dividend, a_cBitsWidth2x); \
    17601766        \
    17611767        uint ## a_cBitsWidth ## _t uDivisorPositive; \
    1762         if ((int ## a_cBitsWidth ## _t)uDivisor >= 0) \
     1768        if (!(uDivisor & RT_BIT_64(a_cBitsWidth - 1))) \
    17631769            uDivisorPositive = uDivisor; \
    17641770        else \
     
    17661772        \
    17671773        RTUINT ## a_cBitsWidth2x ## U Remainder, Quotient; \
    1768         a_fnDivRem(Remainder, Quotient, Dividend, uDivisorPositive); \
     1774        a_fnDivRem(Quotient, Remainder, Dividend, uDivisorPositive); \
    17691775        \
    17701776        /* \
    17711777         * Setup the result, checking for overflows. \
    17721778         */ \
    1773         if ((int ## a_cBitsWidth ## _t)uDivisor >= 0) \
     1779        if (!(uDivisor & RT_BIT_64(a_cBitsWidth - 1))) \
    17741780        { \
    1775             if ((int ## a_cBitsWidth ## _t)Dividend.s.Hi >= 0) \
     1781            if (!fSignedDividend) \
    17761782            { \
    17771783                /* Positive divisor, positive dividend => result positive. */ \
     
    17841790            else \
    17851791            { \
    1786                 /* Positive divisor, positive dividend => result negative. */ \
     1792                /* Positive divisor, negative dividend => result negative. */ \
    17871793                if (Quotient.s.Hi == 0 && Quotient.s.Lo <= RT_BIT_64(a_cBitsWidth - 1)) \
    17881794                { \
     
    17941800        else \
    17951801        { \
    1796             if ((int ## a_cBitsWidth ## _t)Dividend.s.Hi >= 0) \
     1802            if (!fSignedDividend) \
    17971803            { \
    17981804                /* Negative divisor, positive dividend => negative quotient, positive remainder. */ \
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