VirtualBox

Changeset 93880 in vbox for trunk


Ignore:
Timestamp:
Feb 22, 2022 9:09:02 AM (3 years ago)
Author:
vboxsync
Message:

VMM/IEM: Tests for CMPXCHG8B and 16B C implementations. bugref:9898

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/testcase/tstIEMAImpl.cpp

    r93879 r93880  
    140140*   Internal Functions                                                                                                           *
    141141*********************************************************************************************************************************/
    142 static uint32_t RandEFlags(void);
    143 static uint8_t  RandU8(void);
    144 static uint16_t RandU16(void);
    145 static uint32_t RandU32(void);
    146 static uint64_t RandU64(void);
     142static uint32_t     RandEFlags(void);
     143static uint8_t      RandU8(void);
     144static uint16_t     RandU16(void);
     145static uint32_t     RandU32(void);
     146static uint64_t     RandU64(void);
     147static RTUINT128U   RandU128(void);
    147148
    148149
     
    745746static void XaddTest(void)
    746747{
    747     RTTestSub(g_hTest, "xadd");
    748748#define TEST_XADD(a_cBits, a_Type, a_Fmt) do { \
    749749        typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU ## a_cBits, (a_Type *, a_Type *, uint32_t *)); \
     
    763763        for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++) \
    764764        { \
     765            RTTestSub(g_hTest, s_aFuncs[iFn].pszName); \
    765766            BINU ## a_cBits ## _TEST_T const * const paTests = s_aFuncs[iFn].paTests; \
    766767            uint32_t const                           cTests  = s_aFuncs[iFn].cTests; \
     
    794795static void CmpXchgTest(void)
    795796{
    796     RTTestSub(g_hTest, "cmpxchg");
    797797#define TEST_CMPXCHG(a_cBits, a_Type, a_Fmt) do {\
    798798        typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLCMPXCHGU ## a_cBits, (a_Type *, a_Type *, a_Type, uint32_t *)); \
     
    813813        for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++) \
    814814        { \
     815            RTTestSub(g_hTest, s_aFuncs[iFn].pszName); \
    815816            BINU ## a_cBits ## _TEST_T const * const paTests = s_aFuncs[iFn].paTests; \
    816817            uint32_t const                           cTests  = s_aFuncs[iFn].cTests; \
     
    857858}
    858859
    859 #if 0
    860 static 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");
     860static void CmpXchg8bTest(void)
     861{
     862    typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLCMPXCHG8B,(uint64_t *, PRTUINT64U, PRTUINT64U, uint32_t *));
     863    static struct
     864    {
     865        const char           *pszName;
     866        FNIEMAIMPLCMPXCHG8B  *pfn;
     867    } const s_aFuncs[] =
     868    {
     869        { "cmpxchg8b",        iemAImpl_cmpxchg8b },
     870        { "cmpxchg8b_locked", iemAImpl_cmpxchg8b_locked },
     871    };
     872    for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++)
     873    {
     874        RTTestSub(g_hTest, s_aFuncs[iFn].pszName);
     875        for (uint32_t iTest = 0; iTest < 4; iTest += 2)
     876        {
     877            uint64_t const uOldValue = RandU64();
     878            uint64_t const uNewValue = RandU64();
     879
     880            /* positive test. */
     881            RTUINT64U uA, uB;
     882            uB.u             = uNewValue;
     883            uA.u             = uOldValue;
     884            *g_pu64          = uOldValue;
     885            uint32_t fEflIn  = RandEFlags();
     886            uint32_t fEfl    = fEflIn;
     887            s_aFuncs[iFn].pfn(g_pu64, &uA, &uB, &fEfl);
     888            if (   fEfl    != (fEflIn | X86_EFL_ZF)
     889                || *g_pu64 != uNewValue
     890                || uA.u    != uOldValue)
     891                RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#018RX64 cmp=%#018RX64 new=%#018RX64\n -> efl=%#08x dst=%#018RX64 old=%#018RX64,\n wanted %#08x,    %#018RX64,    %#018RX64%s\n",
     892                             iTest, fEflIn, uOldValue, uOldValue, uNewValue,
     893                             fEfl, *g_pu64, uA.u,
     894                             (fEflIn | X86_EFL_ZF), uNewValue, uOldValue, EFlagsDiff(fEfl, fEflIn | X86_EFL_ZF));
     895            RTTEST_CHECK(g_hTest, uB.u == uNewValue);
     896
     897            /* negative */
     898            uint64_t const uExpect = ~uOldValue;
     899            *g_pu64 = uExpect;
     900            uA.u = uOldValue;
     901            uB.u = uNewValue;
     902            fEfl = fEflIn = RandEFlags();
     903            s_aFuncs[iFn].pfn(g_pu64, &uA, &uB, &fEfl);
     904            if (   fEfl    != (fEflIn & ~X86_EFL_ZF)
     905                || *g_pu64 != uExpect
     906                || uA.u    != uExpect)
     907                RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#018RX64 cmp=%#018RX64 new=%#018RX64\n -> efl=%#08x dst=%#018RX64 old=%#018RX64,\n wanted %#08x,    %#018RX64,    %#018RX64%s\n",
     908                             iTest + 1, fEflIn, uExpect, uOldValue, uNewValue,
     909                             fEfl, *g_pu64, uA.u,
     910                             (fEflIn & ~X86_EFL_ZF), uExpect, uExpect, EFlagsDiff(fEfl, fEflIn & ~X86_EFL_ZF));
     911            RTTEST_CHECK(g_hTest, uB.u == uNewValue);
     912        }
     913    }
     914}
     915
     916static void CmpXchg16bTest(void)
     917{
     918    typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLCMPXCHG16B,(PRTUINT128U, PRTUINT128U, PRTUINT128U, uint32_t *));
     919    static struct
     920    {
     921        const char           *pszName;
     922        FNIEMAIMPLCMPXCHG16B *pfn;
     923    } const s_aFuncs[] =
     924    {
     925        { "cmpxchg16b",          iemAImpl_cmpxchg16b },
     926        { "cmpxchg16b_locked",   iemAImpl_cmpxchg16b_locked },
     927#if !defined(RT_ARCH_ARM64)
     928        { "cmpxchg16b_fallback", iemAImpl_cmpxchg16b_fallback },
    915929#endif
     930    };
     931    for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++)
     932    {
     933#if !defined(IEM_WITHOUT_ASSEMBLY) && defined(RT_ARCH_AMD64)
     934        if (!(ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_CX16))
     935            continue;
    916936#endif
    917 }
    918 #endif
     937        RTTestSub(g_hTest, s_aFuncs[iFn].pszName);
     938        for (uint32_t iTest = 0; iTest < 4; iTest += 2)
     939        {
     940            RTUINT128U const uOldValue = RandU128();
     941            RTUINT128U const uNewValue = RandU128();
     942
     943            /* positive test. */
     944            RTUINT128U uA, uB;
     945            uB               = uNewValue;
     946            uA               = uOldValue;
     947            *g_pu128         = uOldValue;
     948            uint32_t fEflIn  = RandEFlags();
     949            uint32_t fEfl    = fEflIn;
     950            s_aFuncs[iFn].pfn(g_pu128, &uA, &uB, &fEfl);
     951            if (   fEfl    != (fEflIn | X86_EFL_ZF)
     952                || g_pu128->s.Lo != uNewValue.s.Lo
     953                || g_pu128->s.Hi != uNewValue.s.Hi
     954                || uA.s.Lo       != uOldValue.s.Lo
     955                || uA.s.Hi       != uOldValue.s.Hi)
     956                RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#018RX64'%016RX64 cmp=%#018RX64'%016RX64 new=%#018RX64'%016RX64\n"
     957                                      " -> efl=%#08x dst=%#018RX64'%016RX64 old=%#018RX64'%016RX64,\n"
     958                                      " wanted %#08x,    %#018RX64'%016RX64,    %#018RX64'%016RX64%s\n",
     959                             iTest, fEflIn, uOldValue.s.Hi, uOldValue.s.Lo, uOldValue.s.Hi, uOldValue.s.Lo, uNewValue.s.Hi, uNewValue.s.Lo,
     960                             fEfl, g_pu128->s.Hi, g_pu128->s.Lo, uA.s.Hi, uA.s.Lo,
     961                             (fEflIn | X86_EFL_ZF), uNewValue.s.Hi, uNewValue.s.Lo, uOldValue.s.Hi, uOldValue.s.Lo,
     962                             EFlagsDiff(fEfl, fEflIn | X86_EFL_ZF));
     963            RTTEST_CHECK(g_hTest, uB.s.Lo == uNewValue.s.Lo && uB.s.Hi == uNewValue.s.Hi);
     964
     965            /* negative */
     966            RTUINT128U const uExpect = RTUINT128_INIT(~uOldValue.s.Hi, ~uOldValue.s.Lo);
     967            *g_pu128 = uExpect;
     968            uA       = uOldValue;
     969            uB       = uNewValue;
     970            fEfl = fEflIn = RandEFlags();
     971            s_aFuncs[iFn].pfn(g_pu128, &uA, &uB, &fEfl);
     972            if (   fEfl          != (fEflIn & ~X86_EFL_ZF)
     973                || g_pu128->s.Lo != uExpect.s.Lo
     974                || g_pu128->s.Hi != uExpect.s.Hi
     975                || uA.s.Lo       != uExpect.s.Lo
     976                || uA.s.Hi       != uExpect.s.Hi)
     977                RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#018RX64'%016RX64 cmp=%#018RX64'%016RX64 new=%#018RX64'%016RX64\n"
     978                                      " -> efl=%#08x dst=%#018RX64'%016RX64 old=%#018RX64'%016RX64,\n"
     979                                      " wanted %#08x,    %#018RX64'%016RX64,    %#018RX64'%016RX64%s\n",
     980                             iTest + 1, fEflIn, uExpect.s.Hi, uExpect.s.Lo, uOldValue.s.Hi, uOldValue.s.Lo, uNewValue.s.Hi, uNewValue.s.Lo,
     981                             fEfl, g_pu128->s.Hi, g_pu128->s.Lo, uA.s.Hi, uA.s.Lo,
     982                             (fEflIn & ~X86_EFL_ZF), uExpect.s.Hi, uExpect.s.Lo, uExpect.s.Hi, uExpect.s.Lo,
     983                             EFlagsDiff(fEfl, fEflIn & ~X86_EFL_ZF));
     984            RTTEST_CHECK(g_hTest, uB.s.Lo == uNewValue.s.Lo && uB.s.Hi == uNewValue.s.Hi);
     985        }
     986    }
     987}
    919988
    920989
     
    9501019{
    9511020    return RTRandU64();
     1021}
     1022
     1023
     1024static RTUINT128U RandU128(void)
     1025{
     1026    RTUINT128U Ret;
     1027    Ret.s.Hi = RTRandU64();
     1028    Ret.s.Lo = RTRandU64();
     1029    return Ret;
    9521030}
    9531031
     
    10021080    {
    10031081        /* Allocate guarded memory for use in the tests. */
    1004 #define ALLOC_GUARDED_VAR(a_uVar) do { \
    1005             rc = RTTestGuardedAlloc(g_hTest, sizeof(a_uVar), sizeof(a_uVar), false /*fHead*/, (void **)&a_uVar); \
    1006             if (RT_FAILURE(rc)) RTTestFailed(g_hTest, "Failed to allocate guarded mem: " #a_uVar); \
     1082#define ALLOC_GUARDED_VAR(a_puVar) do { \
     1083            rc = RTTestGuardedAlloc(g_hTest, sizeof(*a_puVar), sizeof(*a_puVar), false /*fHead*/, (void **)&a_puVar); \
     1084            if (RT_FAILURE(rc)) RTTestFailed(g_hTest, "Failed to allocate guarded mem: " #a_puVar); \
    10071085        } while (0)
    10081086        ALLOC_GUARDED_VAR(g_pu8);
     
    10261104            XaddTest();
    10271105            CmpXchgTest();
     1106            CmpXchg8bTest();
     1107            CmpXchg16bTest();
    10281108        }
    10291109        return RTTestSummaryAndDestroy(g_hTest);
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