VirtualBox

Changeset 93879 in vbox


Ignore:
Timestamp:
Feb 21, 2022 10:28:27 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
150097
Message:

VMM/IEM: Added CMPXCHG testcase and corrected flag handling in C implementation. bugref:9898

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

Legend:

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

    r93878 r93879  
    13871387IEM_DECL_IMPL_DEF(void, iemAImpl_cmpxchg_u8_locked, (uint8_t  *pu8Dst,  uint8_t  *puAl,  uint8_t  uSrcReg, uint32_t *pEFlags))
    13881388{
    1389     uint8_t const uOld = *puAl;
     1389    uint8_t uOld = *puAl;
    13901390    if (ASMAtomicCmpXchgExU8(pu8Dst, uSrcReg, uOld, puAl))
    1391     {
    13921391        Assert(*puAl == uOld);
    1393         *pEFlags |= X86_EFL_ZF;
    1394     }
    1395     else
    1396         *pEFlags &= ~X86_EFL_ZF;
     1392    iemAImpl_cmp_u8(&uOld, *puAl, pEFlags);
    13971393}
    13981394
     
    14001396IEM_DECL_IMPL_DEF(void, iemAImpl_cmpxchg_u16_locked,(uint16_t *pu16Dst, uint16_t *puAx,  uint16_t uSrcReg, uint32_t *pEFlags))
    14011397{
    1402     uint16_t const uOld = *puAx;
     1398    uint16_t uOld = *puAx;
    14031399    if (ASMAtomicCmpXchgExU16(pu16Dst, uSrcReg, uOld, puAx))
    1404     {
    14051400        Assert(*puAx == uOld);
    1406         *pEFlags |= X86_EFL_ZF;
    1407     }
    1408     else
    1409         *pEFlags &= ~X86_EFL_ZF;
     1401    iemAImpl_cmp_u16(&uOld, *puAx, pEFlags);
    14101402}
    14111403
     
    14131405IEM_DECL_IMPL_DEF(void, iemAImpl_cmpxchg_u32_locked,(uint32_t *pu32Dst, uint32_t *puEax, uint32_t uSrcReg, uint32_t *pEFlags))
    14141406{
    1415     uint32_t const uOld = *puEax;
     1407    uint32_t uOld = *puEax;
    14161408    if (ASMAtomicCmpXchgExU32(pu32Dst, uSrcReg, uOld, puEax))
    1417     {
    14181409        Assert(*puEax == uOld);
    1419         *pEFlags |= X86_EFL_ZF;
    1420     }
    1421     else
    1422         *pEFlags &= ~X86_EFL_ZF;
     1410    iemAImpl_cmp_u32(&uOld, *puEax, pEFlags);
    14231411}
    14241412
     
    14331421    uint64_t const uSrcReg = *puSrcReg;
    14341422# endif
    1435     uint64_t const uOld = *puRax;
     1423    uint64_t uOld = *puRax;
    14361424    if (ASMAtomicCmpXchgExU64(pu64Dst, uSrcReg, uOld, puRax))
    1437     {
    14381425        Assert(*puRax == uOld);
    1439         *pEFlags |= X86_EFL_ZF;
    1440     }
    1441     else
    1442         *pEFlags &= ~X86_EFL_ZF;
     1426    iemAImpl_cmp_u64(&uOld, *puRax, pEFlags);
    14431427}
    14441428
  • trunk/src/VBox/VMM/testcase/tstIEMAImpl.cpp

    r93877 r93879  
    746746{
    747747    RTTestSub(g_hTest, "xadd");
    748     typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU8, (uint8_t  *pu8Mem,  uint8_t  *pu8Reg,  uint32_t *pEFlags));
    749     typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU16,(uint16_t *pu16Mem, uint16_t *pu16Reg, uint32_t *pEFlags));
    750     typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU32,(uint32_t *pu32Mem, uint32_t *pu32Reg, uint32_t *pEFlags));
    751     typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU64,(uint64_t *pu64Mem, uint64_t *pu64Reg, uint32_t *pEFlags));
    752 
    753 #define TEST_XADD(a_cBits, a_Type, a_Fmt) do {\
     748#define TEST_XADD(a_cBits, a_Type, a_Fmt) do { \
     749        typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU ## a_cBits, (a_Type *, a_Type *, uint32_t *)); \
    754750        static struct \
    755751        { \
     
    793789
    794790/*
     791 * CMPXCHG
     792 */
     793
     794static void CmpXchgTest(void)
     795{
     796    RTTestSub(g_hTest, "cmpxchg");
     797#define TEST_CMPXCHG(a_cBits, a_Type, a_Fmt) do {\
     798        typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLCMPXCHGU ## a_cBits, (a_Type *, a_Type *, a_Type, uint32_t *)); \
     799        static struct \
     800        { \
     801            const char                         *pszName; \
     802            FNIEMAIMPLCMPXCHGU ## a_cBits      *pfn; \
     803            PFNIEMAIMPLBINU ## a_cBits          pfnSub; \
     804            BINU ## a_cBits ## _TEST_T const   *paTests; \
     805            uint32_t                            cTests; \
     806        } const s_aFuncs[] = \
     807        { \
     808            { "cmpxchg_u" # a_cBits,           iemAImpl_cmpxchg_u ## a_cBits, iemAImpl_sub_u ## a_cBits, \
     809              g_aTests_cmp_u ## a_cBits, RT_ELEMENTS(g_aTests_cmp_u ## a_cBits) }, \
     810            { "cmpxchg_u" # a_cBits "_locked", iemAImpl_cmpxchg_u ## a_cBits ## _locked, iemAImpl_sub_u ## a_cBits, \
     811              g_aTests_cmp_u ## a_cBits, RT_ELEMENTS(g_aTests_cmp_u ## a_cBits) }, \
     812        }; \
     813        for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++) \
     814        { \
     815            BINU ## a_cBits ## _TEST_T const * const paTests = s_aFuncs[iFn].paTests; \
     816            uint32_t const                           cTests  = s_aFuncs[iFn].cTests; \
     817            for (uint32_t iTest = 0; iTest < cTests; iTest++) \
     818            { \
     819                /* as is (99% likely to be negative). */ \
     820                uint32_t      fEfl    = paTests[iTest].fEflIn; \
     821                a_Type const  uNew    = paTests[iTest].uSrcIn + 0x42; \
     822                a_Type        uA      = paTests[iTest].uDstIn; \
     823                *g_pu ## a_cBits      = paTests[iTest].uSrcIn; \
     824                a_Type const  uExpect = uA != paTests[iTest].uSrcIn ? paTests[iTest].uSrcIn : uNew; \
     825                s_aFuncs[iFn].pfn(g_pu ## a_cBits, &uA, uNew, &fEfl); \
     826                if (   fEfl             != paTests[iTest].fEflOut \
     827                    || *g_pu ## a_cBits != uExpect \
     828                    || uA               != paTests[iTest].uSrcIn) \
     829                    RTTestFailed(g_hTest, "%s/#%ua: efl=%#08x dst=" a_Fmt " cmp=" a_Fmt " new=" a_Fmt " -> efl=%#08x dst=" a_Fmt " old=" a_Fmt ", expected %#08x, " a_Fmt ", " a_Fmt "%s\n", \
     830                                 s_aFuncs[iFn].pszName, iTest, paTests[iTest].fEflIn, paTests[iTest].uSrcIn, paTests[iTest].uDstIn, \
     831                                 uNew, fEfl, *g_pu ## a_cBits, uA, paTests[iTest].fEflOut, uExpect, paTests[iTest].uSrcIn, \
     832                                 EFlagsDiff(fEfl, paTests[iTest].fEflOut)); \
     833                /* positive */ \
     834                uint32_t fEflExpect = paTests[iTest].fEflIn; \
     835                uA                  = paTests[iTest].uDstIn; \
     836                s_aFuncs[iFn].pfnSub(&uA, uA, &fEflExpect); \
     837                fEfl                = paTests[iTest].fEflIn; \
     838                uA                  = paTests[iTest].uDstIn; \
     839                *g_pu ## a_cBits    = uA; \
     840                s_aFuncs[iFn].pfn(g_pu ## a_cBits, &uA, uNew, &fEfl); \
     841                if (   fEfl             != fEflExpect \
     842                    || *g_pu ## a_cBits != uNew \
     843                    || uA               != paTests[iTest].uDstIn) \
     844                    RTTestFailed(g_hTest, "%s/#%ua: efl=%#08x dst=" a_Fmt " cmp=" a_Fmt " new=" a_Fmt " -> efl=%#08x dst=" a_Fmt " old=" a_Fmt ", expected %#08x, " a_Fmt ", " a_Fmt "%s\n", \
     845                                 s_aFuncs[iFn].pszName, iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uDstIn, \
     846                                 uNew, fEfl, *g_pu ## a_cBits, uA, fEflExpect, uNew, paTests[iTest].uDstIn, \
     847                                 EFlagsDiff(fEfl, fEflExpect)); \
     848            } \
     849        } \
     850    } while(0)
     851    TEST_CMPXCHG(8, uint8_t, "%#04RX8");
     852    TEST_CMPXCHG(16, uint16_t, "%#06x");
     853    TEST_CMPXCHG(32, uint32_t, "%#010RX32");
     854#if ARCH_BITS != 32 /* calling convension issue, skipping as it's an unsupported host  */
     855    TEST_CMPXCHG(64, uint64_t, "%#010RX64");
     856#endif
     857}
     858
     859#if 0
     860static void CmpXchgTest(void)
     861{
     862    RTTestSub(g_hTest, "cmpxchg");
     863#define TEST_CMPXCHG(a_cBits, a_Type, a_Fmt) do {\
     864        typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLCMPXCHGU ## a_cBits, (a_Type *, a_Type *, a_Type, uint32_t *)); \
     865        static struct \
     866        { \
     867            const char                         *pszName; \
     868            FNIEMAIMPLCMPXCHGU ## a_cBits      *pfn; \
     869        } const s_aFuncs[] = \
     870        { \
     871            { "cmpxchg_u" # a_cBits,           iemAImpl_cmpxchg_u ## a_cBits  }, \
     872            { "cmpxchg_u" # a_cBits "_locked", iemAImpl_cmpxchg_u ## a_cBits ## _locked }, \
     873        }; \
     874        for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++) \
     875        { \
     876            for (uint32_t iTest = 0; iTest < 4; iTest += 2) \
     877            { \
     878                a_Type const uOldValue = RandU ## a_cBits(); \
     879                a_Type const uNewValue = RandU ## a_cBits(); \
     880                /* positive test. */ \
     881                *g_pu ## a_cBits = uOldValue; \
     882                a_Type   uA      = uOldValue; \
     883                uint32_t fEflIn  = RandEFlags(); \
     884                uint32_t fEfl    = fEflIn; \
     885                s_aFuncs[iFn].pfn(g_pu ## a_cBits, &uA, uNewValue, &fEfl); \
     886                if (   fEfl != (fEflIn | X86_EFL_ZF) \
     887                    || *g_pu ## a_cBits != uNewValue \
     888                    || uA != uOldValue) \
     889                    RTTestFailed(g_hTest, "%s/#%u: efl=%#08x dst=" a_Fmt " cmp=" a_Fmt " new=" a_Fmt " -> efl=%#08x dst=" a_Fmt " old=" a_Fmt ", expected %#08x, " a_Fmt ", " a_Fmt "%s\n", \
     890                                 s_aFuncs[iFn].pszName, iTest, fEflIn, uOldValue, uOldValue, uNewValue, \
     891                                 fEfl, *g_pu ## a_cBits, uA, \
     892                                 (fEflIn | X86_EFL_ZF), uNewValue, uOldValue, EFlagsDiff(fEfl, fEflIn | X86_EFL_ZF)); \
     893                /* negative */ \
     894                a_Type const uExpect = ~uOldValue; \
     895                *g_pu ## a_cBits = uExpect; \
     896                uA   = uOldValue; \
     897                fEfl = fEflIn = RandEFlags(); \
     898                s_aFuncs[iFn].pfn(g_pu ## a_cBits, &uA, uNewValue, &fEfl); \
     899                if (   fEfl != (fEflIn & ~X86_EFL_ZF) \
     900                    || *g_pu ## a_cBits != uExpect \
     901                    || uA != uExpect) \
     902                    RTTestFailed(g_hTest, "%s/#%u: efl=%#08x dst=" a_Fmt " cmp=" a_Fmt " new=" a_Fmt " -> efl=%#08x dst=" a_Fmt " old=" a_Fmt ", expected %#08x, " a_Fmt ", " a_Fmt "%s\n", \
     903                                 s_aFuncs[iFn].pszName, iTest + 1, fEflIn, uExpect, uOldValue, uNewValue, \
     904                                 fEfl, *g_pu ## a_cBits, uA, \
     905                                 (fEflIn & ~X86_EFL_ZF), uExpect, uExpect, EFlagsDiff(fEfl, fEflIn & ~X86_EFL_ZF)); \
     906            } \
     907        } \
     908    } while(0)
     909    TEST_CMPXCHG(8, uint8_t, "%#04RX8");
     910#if 0
     911    TEST_CMPXCHG(16, uint16_t, "%#06x");
     912    TEST_CMPXCHG(32, uint32_t, "%#010RX32");
     913#if ARCH_BITS != 32 /* calling convension issue, skipping as it's an unsupported host  */
     914    TEST_CMPXCHG(64, uint64_t, "%#010RX64");
     915#endif
     916#endif
     917}
     918#endif
     919
     920
     921/*
    795922 * Random helpers.
    796923 */
     
    8981025            XchgTest();
    8991026            XaddTest();
     1027            CmpXchgTest();
    9001028        }
    9011029        return RTTestSummaryAndDestroy(g_hTest);
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