VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTInlineAsm.cpp@ 95074

Last change on this file since 95074 was 95074, checked in by vboxsync, 3 years ago

IPRT/tstRTInlineAsm: Fixed bug in the ASMAtomicCmpXchgPtrVoid tests in tstASMAtomicCmpXchgU32Worker.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 166.6 KB
Line 
1/* $Id: tstRTInlineAsm.cpp 95074 2022-05-24 13:38:17Z vboxsync $ */
2/** @file
3 * IPRT Testcase - inline assembly.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/asm.h>
32#include <iprt/asm-math.h>
33
34/* See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44018. Only gcc version 4.4
35 * is affected. No harm for the VBox code: If the cpuid code compiles, it works
36 * fine. */
37#if defined(__GNUC__) && defined(RT_ARCH_X86) && defined(__PIC__)
38# if __GNUC__ == 4 && __GNUC_MINOR__ == 4
39# define GCC44_32BIT_PIC
40# endif
41#endif
42
43#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
44# include <iprt/asm-amd64-x86.h>
45# include <iprt/x86.h>
46#elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
47# include <iprt/asm-arm.h>
48# include <iprt/time.h>
49#else
50# include <iprt/time.h>
51#endif
52#include <iprt/mem.h>
53#include <iprt/param.h>
54#include <iprt/rand.h>
55#include <iprt/stream.h>
56#include <iprt/string.h>
57#include <iprt/thread.h>
58#include <iprt/test.h>
59#include <iprt/time.h>
60
61
62
63/*********************************************************************************************************************************
64* Defined Constants And Macros *
65*********************************************************************************************************************************/
66#define CHECKVAL(val, expect, fmt) \
67 do \
68 { \
69 if ((val) != (expect)) \
70 { \
71 RTTestFailed(g_hTest, "%s, %d: " #val ": expected " fmt " got " fmt "\n", __FUNCTION__, __LINE__, (expect), (val)); \
72 } \
73 } while (0)
74
75#define CHECKOP(op, expect, fmt, type) \
76 do \
77 { \
78 type val = op; \
79 if (val != (type)(expect)) \
80 { \
81 RTTestFailed(g_hTest, "%s, %d: " #op ": expected " fmt " got " fmt "\n", __FUNCTION__, __LINE__, (type)(expect), val); \
82 } \
83 } while (0)
84
85#define CHECK_OP_AND_VAL(a_Type, a_Fmt, a_pVar, a_Operation, a_ExpectRetVal, a_ExpectVarVal) \
86 do { \
87 CHECKOP(a_Operation, a_ExpectRetVal, a_Fmt, a_Type); \
88 CHECKVAL(*a_pVar, a_ExpectVarVal, a_Fmt); \
89 } while (0)
90
91#define CHECK_OP_AND_VAL_EX(a_TypeRet, a_FmtRet, a_FmtVar, a_pVar, a_Operation, a_ExpectRetVal, a_ExpectVarVal) \
92 do { \
93 CHECKOP(a_Operation, a_ExpectRetVal, a_FmtRet, a_TypeRet); \
94 CHECKVAL(*a_pVar, a_ExpectVarVal, a_FmtVar); \
95 } while (0)
96
97#define CHECK_OP_AND_VAL_EX2(a_TypeRet, a_FmtRet, a_FmtVar, a_pVar, a_uVar2, a_Operation, a_ExpectRetVal, a_ExpectVarVal, a_ExpectVarVal2) \
98 do { \
99 CHECKOP(a_Operation, a_ExpectRetVal, a_FmtRet, a_TypeRet); \
100 CHECKVAL(*a_pVar, a_ExpectVarVal, a_FmtVar); \
101 CHECKVAL(a_uVar2, a_ExpectVarVal2, a_FmtVar); \
102 } while (0)
103
104#define CHECKVAL128(a_pu128Val, a_u64HiExpect, a_u64LoExpect) \
105 do \
106 { \
107 if ((a_pu128Val)->s.Hi != (a_u64HiExpect) || (a_pu128Val)->s.Lo != (a_u64LoExpect)) \
108 RTTestFailed(g_hTest, "%s, %d: " #a_pu128Val ": expected %#RX64'%016RX64 got %#RX64'%016RX64\n", \
109 __FUNCTION__, __LINE__, (a_u64HiExpect), (a_u64LoExpect), (a_pu128Val)->s.Hi, (a_pu128Val)->s.Lo); \
110 } while (0)
111#define CHECKVAL128_C(a_pu128Val, a_u64HiExpect, a_u64LoExpect) \
112 do \
113 { \
114 if ((a_pu128Val)->s.Hi != UINT64_C(a_u64HiExpect) || (a_pu128Val)->s.Lo != UINT64_C(a_u64LoExpect)) \
115 RTTestFailed(g_hTest, "%s, %d: " #a_pu128Val ": expected %#RX64'%016RX64 got %#RX64'%016RX64\n", \
116 __FUNCTION__, __LINE__, UINT64_C(a_u64HiExpect), UINT64_C(a_u64LoExpect), \
117 (a_pu128Val)->s.Hi, (a_pu128Val)->s.Lo); \
118 } while (0)
119#define CHECK_OP_AND_VAL_128(a_TypeRet, a_FmtRet, a_pu128Val, a_Operation, a_ExpectRetVal, a_u64HiExpect, a_u64LoExpect) \
120 do { \
121 CHECKOP(a_Operation, a_ExpectRetVal, a_FmtRet, a_TypeRet); \
122 CHECKVAL128(a_pu128Val, a_u64HiExpect, a_u64LoExpect); \
123 } while (0)
124#define CHECK_OP_AND_VAL_128_C(a_TypeRet, a_FmtRet, a_pu128Val, a_Operation, a_ExpectRetVal, a_u64HiExpect, a_u64LoExpect) \
125 do { \
126 CHECKOP(a_Operation, a_ExpectRetVal, a_FmtRet, a_TypeRet); \
127 CHECKVAL128_C(a_pu128Val, a_u64HiExpect, a_u64LoExpect); \
128 } while (0)
129
130/**
131 * Calls a worker function with different worker variable storage types.
132 */
133#define DO_SIMPLE_TEST_NO_SUB_NO_STACK(a_WorkerFunction, type) \
134 do \
135 { \
136 type *pVar = (type *)RTTestGuardedAllocHead(g_hTest, sizeof(type)); \
137 RTTEST_CHECK_BREAK(g_hTest, pVar); \
138 a_WorkerFunction(pVar); \
139 RTTestGuardedFree(g_hTest, pVar); \
140 \
141 pVar = (type *)RTTestGuardedAllocTail(g_hTest, sizeof(type)); \
142 RTTEST_CHECK_BREAK(g_hTest, pVar); \
143 a_WorkerFunction(pVar); \
144 RTTestGuardedFree(g_hTest, pVar); \
145 } while (0)
146
147
148/**
149 * Calls a worker function with different worker variable storage types.
150 */
151#define DO_SIMPLE_TEST_NO_SUB(a_WorkerFunction, type) \
152 do \
153 { \
154 type StackVar; \
155 a_WorkerFunction(&StackVar); \
156 DO_SIMPLE_TEST_NO_SUB_NO_STACK(a_WorkerFunction, type); \
157 } while (0)
158
159/**
160 * Calls a worker function with different worker variable storage types.
161 */
162#define DO_SIMPLE_TEST(name, type) \
163 do \
164 { \
165 RTTestISub(#name); \
166 DO_SIMPLE_TEST_NO_SUB(tst ## name ## Worker, type); \
167 } while (0)
168
169
170/*********************************************************************************************************************************
171* Global Variables *
172*********************************************************************************************************************************/
173/** The test instance. */
174static RTTEST g_hTest;
175
176
177
178#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
179
180const char *getCacheAss(unsigned u)
181{
182 if (u == 0)
183 return "res0 ";
184 if (u == 1)
185 return "direct";
186 if (u >= 256)
187 return "???";
188
189 char *pszRet = NULL;
190 RTStrAPrintf(&pszRet, "%d way", u);
191 RTMEM_WILL_LEAK(pszRet);
192 return pszRet;
193}
194
195
196const char *getL2CacheAss(unsigned u)
197{
198 switch (u)
199 {
200 case 0: return "off ";
201 case 1: return "direct";
202 case 2: return "2 way ";
203 case 3: return "res3 ";
204 case 4: return "4 way ";
205 case 5: return "res5 ";
206 case 6: return "8 way ";
207 case 7: return "res7 ";
208 case 8: return "16 way";
209 case 9: return "res9 ";
210 case 10: return "res10 ";
211 case 11: return "res11 ";
212 case 12: return "res12 ";
213 case 13: return "res13 ";
214 case 14: return "res14 ";
215 case 15: return "fully ";
216 default:
217 return "????";
218 }
219}
220
221
222/**
223 * Test and dump all possible info from the CPUID instruction.
224 *
225 * @remark Bits shared with the libc cpuid.c program. This all written by me, so no worries.
226 * @todo transform the dumping into a generic runtime function. We'll need it for logging!
227 */
228void tstASMCpuId(void)
229{
230 RTTestISub("ASMCpuId");
231
232 unsigned iBit;
233 struct
234 {
235 uint32_t uEBX, uEAX, uEDX, uECX;
236 } s;
237 if (!ASMHasCpuId())
238 {
239 RTTestIPrintf(RTTESTLVL_ALWAYS, "warning! CPU doesn't support CPUID\n");
240 return;
241 }
242
243 /*
244 * Try the 0 function and use that for checking the ASMCpuId_* variants.
245 */
246 ASMCpuId(0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
247
248 uint32_t u32;
249
250 u32 = ASMCpuId_EAX(0);
251 CHECKVAL(u32, s.uEAX, "%x");
252 u32 = ASMCpuId_EBX(0);
253 CHECKVAL(u32, s.uEBX, "%x");
254 u32 = ASMCpuId_ECX(0);
255 CHECKVAL(u32, s.uECX, "%x");
256 u32 = ASMCpuId_EDX(0);
257 CHECKVAL(u32, s.uEDX, "%x");
258
259 uint32_t uECX2 = s.uECX - 1;
260 uint32_t uEDX2 = s.uEDX - 1;
261 ASMCpuId_ECX_EDX(0, &uECX2, &uEDX2);
262 CHECKVAL(uECX2, s.uECX, "%x");
263 CHECKVAL(uEDX2, s.uEDX, "%x");
264
265 uint32_t uEAX2 = s.uEAX - 1;
266 uint32_t uEBX2 = s.uEBX - 1;
267 uECX2 = s.uECX - 1;
268 uEDX2 = s.uEDX - 1;
269 ASMCpuIdExSlow(0, 0, 0, 0, &uEAX2, &uEBX2, &uECX2, &uEDX2);
270 CHECKVAL(uEAX2, s.uEAX, "%x");
271 CHECKVAL(uEBX2, s.uEBX, "%x");
272 CHECKVAL(uECX2, s.uECX, "%x");
273 CHECKVAL(uEDX2, s.uEDX, "%x");
274
275 /*
276 * Check the extended APIC stuff.
277 */
278 uint32_t idExtApic;
279 if (ASMCpuId_EAX(0) >= 0xb)
280 {
281 uint8_t idApic = ASMGetApicId();
282 do
283 {
284 uEAX2 = uEBX2 = uECX2 = uEDX2 = UINT32_C(0x50486744);
285 ASMCpuIdExSlow(0xb, 0, 0, 0, &uEAX2, &uEBX2, &uECX2, &uEDX2);
286 idExtApic = ASMGetApicIdExt0B();
287 } while (ASMGetApicId() != idApic);
288
289 CHECKVAL(uEDX2, idExtApic, "%x");
290 if (idApic != (uint8_t)idExtApic && uECX2 != 0)
291 RTTestIFailed("ASMGetApicIdExt0B() -> %#x vs ASMGetApicId() -> %#x", idExtApic, idApic);
292 }
293 if (ASMCpuId_EAX(UINT32_C(0x80000000)) >= UINT32_C(0x8000001E))
294 {
295 uint8_t idApic = ASMGetApicId();
296 do
297 {
298 uEAX2 = uEBX2 = uECX2 = uEDX2 = UINT32_C(0x50486744);
299 ASMCpuIdExSlow(0x8000001e, 0, 0, 0, &uEAX2, &uEBX2, &uECX2, &uEDX2);
300 idExtApic = ASMGetApicIdExt8000001E();
301 } while (ASMGetApicId() != idApic);
302 CHECKVAL(uEAX2, idExtApic, "%x");
303 if (idApic != (uint8_t)idExtApic)
304 RTTestIFailed("ASMGetApicIdExt8000001E() -> %#x vs ASMGetApicId() -> %#x", idExtApic, idApic);
305 }
306
307 /*
308 * Done testing, dump the information.
309 */
310 RTTestIPrintf(RTTESTLVL_ALWAYS, "CPUID Dump\n");
311 ASMCpuId(0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
312 const uint32_t cFunctions = s.uEAX;
313
314 /* raw dump */
315 RTTestIPrintf(RTTESTLVL_ALWAYS,
316 "\n"
317 " RAW Standard CPUIDs\n"
318 "Function eax ebx ecx edx\n");
319 for (unsigned iStd = 0; iStd <= cFunctions + 3; iStd++)
320 {
321 ASMCpuId_Idx_ECX(iStd, 0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
322 RTTestIPrintf(RTTESTLVL_ALWAYS, "%08x %08x %08x %08x %08x%s\n",
323 iStd, s.uEAX, s.uEBX, s.uECX, s.uEDX, iStd <= cFunctions ? "" : "*");
324
325 /* Some leafs output depend on the initial value of ECX.
326 * The same seems to apply to invalid standard functions */
327 if (iStd > cFunctions)
328 continue;
329 if (iStd == 0x04) /* Deterministic Cache Parameters Leaf */
330 for (uint32_t uECX = 1; s.uEAX & 0x1f; uECX++)
331 {
332 ASMCpuId_Idx_ECX(iStd, uECX, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
333 RTTestIPrintf(RTTESTLVL_ALWAYS, " [%02x] %08x %08x %08x %08x\n", uECX, s.uEAX, s.uEBX, s.uECX, s.uEDX);
334 RTTESTI_CHECK_BREAK(uECX < 128);
335 }
336 else if (iStd == 0x07) /* Structured Extended Feature Flags */
337 {
338 uint32_t uMax = s.uEAX;
339 for (uint32_t uECX = 1; uECX < uMax; uECX++)
340 {
341 ASMCpuId_Idx_ECX(iStd, uECX, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
342 RTTestIPrintf(RTTESTLVL_ALWAYS, " [%02x] %08x %08x %08x %08x\n", uECX, s.uEAX, s.uEBX, s.uECX, s.uEDX);
343 RTTESTI_CHECK_BREAK(uECX < 128);
344 }
345 }
346 else if (iStd == 0x0b) /* Extended Topology Enumeration Leafs */
347 for (uint32_t uECX = 1; (s.uEAX & 0x1f) && (s.uEBX & 0xffff); uECX++)
348 {
349 ASMCpuId_Idx_ECX(iStd, uECX, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
350 RTTestIPrintf(RTTESTLVL_ALWAYS, " [%02x] %08x %08x %08x %08x\n", uECX, s.uEAX, s.uEBX, s.uECX, s.uEDX);
351 RTTESTI_CHECK_BREAK(uECX < 128);
352 }
353 else if (iStd == 0x0d) /* Extended State Enumeration Leafs */
354 for (uint32_t uECX = 1; s.uEAX != 0 || s.uEBX != 0 || s.uECX != 0 || s.uEDX != 0; uECX++)
355 {
356 ASMCpuId_Idx_ECX(iStd, uECX, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
357 RTTestIPrintf(RTTESTLVL_ALWAYS, " [%02x] %08x %08x %08x %08x\n", uECX, s.uEAX, s.uEBX, s.uECX, s.uEDX);
358 RTTESTI_CHECK_BREAK(uECX < 128);
359 }
360 else if ( iStd == 0x0f /* Platform quality of service monitoring (PQM) */
361 || iStd == 0x10 /* Platform quality of service enforcement (PQE) */
362 || iStd == 0x12 /* SGX Enumeration */
363 || iStd == 0x14 /* Processor Trace Enumeration */
364 || iStd == 0x17 /* SoC Vendor Attribute Enumeration */
365 || iStd == 0x18 /* Deterministic Address Translation Parameters */)
366 {
367 /** @todo */
368 }
369 else
370 {
371 u32 = ASMCpuId_EAX(iStd);
372 CHECKVAL(u32, s.uEAX, "%x");
373
374 uint32_t u32EbxMask = UINT32_MAX;
375 if (iStd == 1)
376 u32EbxMask = UINT32_C(0x00ffffff); /* Omit the local apic ID in case we're rescheduled. */
377 u32 = ASMCpuId_EBX(iStd);
378 CHECKVAL(u32 & u32EbxMask, s.uEBX & u32EbxMask, "%x");
379
380 u32 = ASMCpuId_ECX(iStd);
381 CHECKVAL(u32, s.uECX, "%x");
382 u32 = ASMCpuId_EDX(iStd);
383 CHECKVAL(u32, s.uEDX, "%x");
384
385 uECX2 = s.uECX - 1;
386 uEDX2 = s.uEDX - 1;
387 ASMCpuId_ECX_EDX(iStd, &uECX2, &uEDX2);
388 CHECKVAL(uECX2, s.uECX, "%x");
389 CHECKVAL(uEDX2, s.uEDX, "%x");
390
391 uEAX2 = s.uEAX - 1;
392 uEBX2 = s.uEBX - 1;
393 uECX2 = s.uECX - 1;
394 uEDX2 = s.uEDX - 1;
395 ASMCpuId(iStd, &uEAX2, &uEBX2, &uECX2, &uEDX2);
396 CHECKVAL(uEAX2, s.uEAX, "%x");
397 CHECKVAL(uEBX2 & u32EbxMask, s.uEBX & u32EbxMask, "%x");
398 CHECKVAL(uECX2, s.uECX, "%x");
399 CHECKVAL(uEDX2, s.uEDX, "%x");
400 }
401 }
402
403 /*
404 * Understandable output
405 */
406 ASMCpuId(0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
407 RTTestIPrintf(RTTESTLVL_ALWAYS,
408 "Name: %.04s%.04s%.04s\n"
409 "Support: 0-%u\n",
410 &s.uEBX, &s.uEDX, &s.uECX, s.uEAX);
411 bool const fIntel = RTX86IsIntelCpu(s.uEBX, s.uECX, s.uEDX);
412
413 /*
414 * Get Features.
415 */
416 if (cFunctions >= 1)
417 {
418 static const char * const s_apszTypes[4] = { "primary", "overdrive", "MP", "reserved" };
419 ASMCpuId(1, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
420 RTTestIPrintf(RTTESTLVL_ALWAYS,
421 "Family: %#x \tExtended: %#x \tEffective: %#x\n"
422 "Model: %#x \tExtended: %#x \tEffective: %#x\n"
423 "Stepping: %d\n"
424 "Type: %d (%s)\n"
425 "APIC ID: %#04x\n"
426 "Logical CPUs: %d\n"
427 "CLFLUSH Size: %d\n"
428 "Brand ID: %#04x\n",
429 (s.uEAX >> 8) & 0xf, (s.uEAX >> 20) & 0x7f, RTX86GetCpuFamily(s.uEAX),
430 (s.uEAX >> 4) & 0xf, (s.uEAX >> 16) & 0x0f, RTX86GetCpuModel(s.uEAX, fIntel),
431 RTX86GetCpuStepping(s.uEAX),
432 (s.uEAX >> 12) & 0x3, s_apszTypes[(s.uEAX >> 12) & 0x3],
433 (s.uEBX >> 24) & 0xff,
434 (s.uEBX >> 16) & 0xff,
435 (s.uEBX >> 8) & 0xff,
436 (s.uEBX >> 0) & 0xff);
437
438 RTTestIPrintf(RTTESTLVL_ALWAYS, "Features EDX: ");
439 if (s.uEDX & RT_BIT(0)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FPU");
440 if (s.uEDX & RT_BIT(1)) RTTestIPrintf(RTTESTLVL_ALWAYS, " VME");
441 if (s.uEDX & RT_BIT(2)) RTTestIPrintf(RTTESTLVL_ALWAYS, " DE");
442 if (s.uEDX & RT_BIT(3)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PSE");
443 if (s.uEDX & RT_BIT(4)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TSC");
444 if (s.uEDX & RT_BIT(5)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MSR");
445 if (s.uEDX & RT_BIT(6)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PAE");
446 if (s.uEDX & RT_BIT(7)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MCE");
447 if (s.uEDX & RT_BIT(8)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CX8");
448 if (s.uEDX & RT_BIT(9)) RTTestIPrintf(RTTESTLVL_ALWAYS, " APIC");
449 if (s.uEDX & RT_BIT(10)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 10");
450 if (s.uEDX & RT_BIT(11)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SEP");
451 if (s.uEDX & RT_BIT(12)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MTRR");
452 if (s.uEDX & RT_BIT(13)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PGE");
453 if (s.uEDX & RT_BIT(14)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MCA");
454 if (s.uEDX & RT_BIT(15)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CMOV");
455 if (s.uEDX & RT_BIT(16)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PAT");
456 if (s.uEDX & RT_BIT(17)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PSE36");
457 if (s.uEDX & RT_BIT(18)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PSN");
458 if (s.uEDX & RT_BIT(19)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CLFSH");
459 if (s.uEDX & RT_BIT(20)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 20");
460 if (s.uEDX & RT_BIT(21)) RTTestIPrintf(RTTESTLVL_ALWAYS, " DS");
461 if (s.uEDX & RT_BIT(22)) RTTestIPrintf(RTTESTLVL_ALWAYS, " ACPI");
462 if (s.uEDX & RT_BIT(23)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MMX");
463 if (s.uEDX & RT_BIT(24)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FXSR");
464 if (s.uEDX & RT_BIT(25)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SSE");
465 if (s.uEDX & RT_BIT(26)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SSE2");
466 if (s.uEDX & RT_BIT(27)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SS");
467 if (s.uEDX & RT_BIT(28)) RTTestIPrintf(RTTESTLVL_ALWAYS, " HTT");
468 if (s.uEDX & RT_BIT(29)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 29");
469 if (s.uEDX & RT_BIT(30)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 30");
470 if (s.uEDX & RT_BIT(31)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 31");
471 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
472
473 /** @todo check intel docs. */
474 RTTestIPrintf(RTTESTLVL_ALWAYS, "Features ECX: ");
475 if (s.uECX & RT_BIT(0)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SSE3");
476 for (iBit = 1; iBit < 13; iBit++)
477 if (s.uECX & RT_BIT(iBit))
478 RTTestIPrintf(RTTESTLVL_ALWAYS, " %d", iBit);
479 if (s.uECX & RT_BIT(13)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CX16");
480 for (iBit = 14; iBit < 32; iBit++)
481 if (s.uECX & RT_BIT(iBit))
482 RTTestIPrintf(RTTESTLVL_ALWAYS, " %d", iBit);
483 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
484 }
485 if (ASMCpuId_EAX(0) >= 0xb)
486 RTTestIPrintf(RTTESTLVL_ALWAYS, "APIC ID(Ext 0b): %#010x\n", ASMGetApicIdExt0B());
487
488 /*
489 * Extended.
490 * Implemented after AMD specs.
491 */
492 /** @todo check out the intel specs. */
493 ASMCpuId(0x80000000, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
494 if (!s.uEAX && !s.uEBX && !s.uECX && !s.uEDX)
495 {
496 RTTestIPrintf(RTTESTLVL_ALWAYS, "No extended CPUID info? Check the manual on how to detect this...\n");
497 return;
498 }
499 const uint32_t cExtFunctions = s.uEAX | 0x80000000;
500
501 /* raw dump */
502 RTTestIPrintf(RTTESTLVL_ALWAYS,
503 "\n"
504 " RAW Extended CPUIDs\n"
505 "Function eax ebx ecx edx\n");
506 for (unsigned iExt = 0x80000000; iExt <= cExtFunctions + 3; iExt++)
507 {
508 ASMCpuId(iExt, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
509 RTTestIPrintf(RTTESTLVL_ALWAYS, "%08x %08x %08x %08x %08x%s\n",
510 iExt, s.uEAX, s.uEBX, s.uECX, s.uEDX, iExt <= cExtFunctions ? "" : "*");
511
512 if (iExt > cExtFunctions)
513 continue; /* Invalid extended functions seems change the value if ECX changes */
514 if (iExt == 0x8000001d)
515 continue; /* Takes cache level in ecx. */
516
517 u32 = ASMCpuId_EAX(iExt);
518 CHECKVAL(u32, s.uEAX, "%x");
519 u32 = ASMCpuId_EBX(iExt);
520 CHECKVAL(u32, s.uEBX, "%x");
521 u32 = ASMCpuId_ECX(iExt);
522 CHECKVAL(u32, s.uECX, "%x");
523 u32 = ASMCpuId_EDX(iExt);
524 CHECKVAL(u32, s.uEDX, "%x");
525
526 uECX2 = s.uECX - 1;
527 uEDX2 = s.uEDX - 1;
528 ASMCpuId_ECX_EDX(iExt, &uECX2, &uEDX2);
529 CHECKVAL(uECX2, s.uECX, "%x");
530 CHECKVAL(uEDX2, s.uEDX, "%x");
531
532 uEAX2 = s.uEAX - 1;
533 uEBX2 = s.uEBX - 1;
534 uECX2 = s.uECX - 1;
535 uEDX2 = s.uEDX - 1;
536 ASMCpuId(iExt, &uEAX2, &uEBX2, &uECX2, &uEDX2);
537 CHECKVAL(uEAX2, s.uEAX, "%x");
538 CHECKVAL(uEBX2, s.uEBX, "%x");
539 CHECKVAL(uECX2, s.uECX, "%x");
540 CHECKVAL(uEDX2, s.uEDX, "%x");
541 }
542
543 /*
544 * Understandable output
545 */
546 ASMCpuId(0x80000000, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
547 RTTestIPrintf(RTTESTLVL_ALWAYS,
548 "Ext Name: %.4s%.4s%.4s\n"
549 "Ext Supports: 0x80000000-%#010x\n",
550 &s.uEBX, &s.uEDX, &s.uECX, s.uEAX);
551
552 if (cExtFunctions >= 0x80000001)
553 {
554 ASMCpuId(0x80000001, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
555 RTTestIPrintf(RTTESTLVL_ALWAYS,
556 "Family: %#x \tExtended: %#x \tEffective: %#x\n"
557 "Model: %#x \tExtended: %#x \tEffective: %#x\n"
558 "Stepping: %d\n"
559 "Brand ID: %#05x\n",
560 (s.uEAX >> 8) & 0xf, (s.uEAX >> 20) & 0x7f, RTX86GetCpuFamily(s.uEAX),
561 (s.uEAX >> 4) & 0xf, (s.uEAX >> 16) & 0x0f, RTX86GetCpuModel(s.uEAX, fIntel),
562 RTX86GetCpuStepping(s.uEAX),
563 s.uEBX & 0xfff);
564
565 RTTestIPrintf(RTTESTLVL_ALWAYS, "Features EDX: ");
566 if (s.uEDX & RT_BIT(0)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FPU");
567 if (s.uEDX & RT_BIT(1)) RTTestIPrintf(RTTESTLVL_ALWAYS, " VME");
568 if (s.uEDX & RT_BIT(2)) RTTestIPrintf(RTTESTLVL_ALWAYS, " DE");
569 if (s.uEDX & RT_BIT(3)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PSE");
570 if (s.uEDX & RT_BIT(4)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TSC");
571 if (s.uEDX & RT_BIT(5)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MSR");
572 if (s.uEDX & RT_BIT(6)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PAE");
573 if (s.uEDX & RT_BIT(7)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MCE");
574 if (s.uEDX & RT_BIT(8)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CMPXCHG8B");
575 if (s.uEDX & RT_BIT(9)) RTTestIPrintf(RTTESTLVL_ALWAYS, " APIC");
576 if (s.uEDX & RT_BIT(10)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 10");
577 if (s.uEDX & RT_BIT(11)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SysCallSysRet");
578 if (s.uEDX & RT_BIT(12)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MTRR");
579 if (s.uEDX & RT_BIT(13)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PGE");
580 if (s.uEDX & RT_BIT(14)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MCA");
581 if (s.uEDX & RT_BIT(15)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CMOV");
582 if (s.uEDX & RT_BIT(16)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PAT");
583 if (s.uEDX & RT_BIT(17)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PSE36");
584 if (s.uEDX & RT_BIT(18)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 18");
585 if (s.uEDX & RT_BIT(19)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 19");
586 if (s.uEDX & RT_BIT(20)) RTTestIPrintf(RTTESTLVL_ALWAYS, " NX");
587 if (s.uEDX & RT_BIT(21)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 21");
588 if (s.uEDX & RT_BIT(22)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MmxExt");
589 if (s.uEDX & RT_BIT(23)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MMX");
590 if (s.uEDX & RT_BIT(24)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FXSR");
591 if (s.uEDX & RT_BIT(25)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FastFXSR");
592 if (s.uEDX & RT_BIT(26)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 26");
593 if (s.uEDX & RT_BIT(27)) RTTestIPrintf(RTTESTLVL_ALWAYS, " RDTSCP");
594 if (s.uEDX & RT_BIT(28)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 28");
595 if (s.uEDX & RT_BIT(29)) RTTestIPrintf(RTTESTLVL_ALWAYS, " LongMode");
596 if (s.uEDX & RT_BIT(30)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 3DNowExt");
597 if (s.uEDX & RT_BIT(31)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 3DNow");
598 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
599
600 RTTestIPrintf(RTTESTLVL_ALWAYS, "Features ECX: ");
601 if (s.uECX & RT_BIT(0)) RTTestIPrintf(RTTESTLVL_ALWAYS, " LahfSahf");
602 if (s.uECX & RT_BIT(1)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CmpLegacy");
603 if (s.uECX & RT_BIT(2)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SVM");
604 if (s.uECX & RT_BIT(3)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 3");
605 if (s.uECX & RT_BIT(4)) RTTestIPrintf(RTTESTLVL_ALWAYS, " AltMovCr8");
606 for (iBit = 5; iBit < 32; iBit++)
607 if (s.uECX & RT_BIT(iBit))
608 RTTestIPrintf(RTTESTLVL_ALWAYS, " %d", iBit);
609 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
610 }
611
612 char szString[4*4*3+1] = {0};
613 if (cExtFunctions >= 0x80000002)
614 ASMCpuId(0x80000002, &szString[0 + 0], &szString[0 + 4], &szString[0 + 8], &szString[0 + 12]);
615 if (cExtFunctions >= 0x80000003)
616 ASMCpuId(0x80000003, &szString[16 + 0], &szString[16 + 4], &szString[16 + 8], &szString[16 + 12]);
617 if (cExtFunctions >= 0x80000004)
618 ASMCpuId(0x80000004, &szString[32 + 0], &szString[32 + 4], &szString[32 + 8], &szString[32 + 12]);
619 if (cExtFunctions >= 0x80000002)
620 RTTestIPrintf(RTTESTLVL_ALWAYS, "Full Name: %s\n", szString);
621
622 if (cExtFunctions >= 0x80000005)
623 {
624 ASMCpuId(0x80000005, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
625 RTTestIPrintf(RTTESTLVL_ALWAYS,
626 "TLB 2/4M Instr/Uni: %s %3d entries\n"
627 "TLB 2/4M Data: %s %3d entries\n",
628 getCacheAss((s.uEAX >> 8) & 0xff), (s.uEAX >> 0) & 0xff,
629 getCacheAss((s.uEAX >> 24) & 0xff), (s.uEAX >> 16) & 0xff);
630 RTTestIPrintf(RTTESTLVL_ALWAYS,
631 "TLB 4K Instr/Uni: %s %3d entries\n"
632 "TLB 4K Data: %s %3d entries\n",
633 getCacheAss((s.uEBX >> 8) & 0xff), (s.uEBX >> 0) & 0xff,
634 getCacheAss((s.uEBX >> 24) & 0xff), (s.uEBX >> 16) & 0xff);
635 RTTestIPrintf(RTTESTLVL_ALWAYS,
636 "L1 Instr Cache Line Size: %d bytes\n"
637 "L1 Instr Cache Lines Per Tag: %d\n"
638 "L1 Instr Cache Associativity: %s\n"
639 "L1 Instr Cache Size: %d KB\n",
640 (s.uEDX >> 0) & 0xff,
641 (s.uEDX >> 8) & 0xff,
642 getCacheAss((s.uEDX >> 16) & 0xff),
643 (s.uEDX >> 24) & 0xff);
644 RTTestIPrintf(RTTESTLVL_ALWAYS,
645 "L1 Data Cache Line Size: %d bytes\n"
646 "L1 Data Cache Lines Per Tag: %d\n"
647 "L1 Data Cache Associativity: %s\n"
648 "L1 Data Cache Size: %d KB\n",
649 (s.uECX >> 0) & 0xff,
650 (s.uECX >> 8) & 0xff,
651 getCacheAss((s.uECX >> 16) & 0xff),
652 (s.uECX >> 24) & 0xff);
653 }
654
655 if (cExtFunctions >= 0x80000006)
656 {
657 ASMCpuId(0x80000006, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
658 RTTestIPrintf(RTTESTLVL_ALWAYS,
659 "L2 TLB 2/4M Instr/Uni: %s %4d entries\n"
660 "L2 TLB 2/4M Data: %s %4d entries\n",
661 getL2CacheAss((s.uEAX >> 12) & 0xf), (s.uEAX >> 0) & 0xfff,
662 getL2CacheAss((s.uEAX >> 28) & 0xf), (s.uEAX >> 16) & 0xfff);
663 RTTestIPrintf(RTTESTLVL_ALWAYS,
664 "L2 TLB 4K Instr/Uni: %s %4d entries\n"
665 "L2 TLB 4K Data: %s %4d entries\n",
666 getL2CacheAss((s.uEBX >> 12) & 0xf), (s.uEBX >> 0) & 0xfff,
667 getL2CacheAss((s.uEBX >> 28) & 0xf), (s.uEBX >> 16) & 0xfff);
668 RTTestIPrintf(RTTESTLVL_ALWAYS,
669 "L2 Cache Line Size: %d bytes\n"
670 "L2 Cache Lines Per Tag: %d\n"
671 "L2 Cache Associativity: %s\n"
672 "L2 Cache Size: %d KB\n",
673 (s.uEDX >> 0) & 0xff,
674 (s.uEDX >> 8) & 0xf,
675 getL2CacheAss((s.uEDX >> 12) & 0xf),
676 (s.uEDX >> 16) & 0xffff);
677 }
678
679 if (cExtFunctions >= 0x80000007)
680 {
681 ASMCpuId(0x80000007, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
682 RTTestIPrintf(RTTESTLVL_ALWAYS, "APM Features: ");
683 if (s.uEDX & RT_BIT(0)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TS");
684 if (s.uEDX & RT_BIT(1)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FID");
685 if (s.uEDX & RT_BIT(2)) RTTestIPrintf(RTTESTLVL_ALWAYS, " VID");
686 if (s.uEDX & RT_BIT(3)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TTP");
687 if (s.uEDX & RT_BIT(4)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TM");
688 if (s.uEDX & RT_BIT(5)) RTTestIPrintf(RTTESTLVL_ALWAYS, " STC");
689 if (s.uEDX & RT_BIT(6)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 6");
690 if (s.uEDX & RT_BIT(7)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 7");
691 if (s.uEDX & RT_BIT(8)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TscInvariant");
692 for (iBit = 9; iBit < 32; iBit++)
693 if (s.uEDX & RT_BIT(iBit))
694 RTTestIPrintf(RTTESTLVL_ALWAYS, " %d", iBit);
695 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
696 }
697
698 if (cExtFunctions >= 0x80000008)
699 {
700 ASMCpuId(0x80000008, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
701 RTTestIPrintf(RTTESTLVL_ALWAYS,
702 "Physical Address Width: %d bits\n"
703 "Virtual Address Width: %d bits\n"
704 "Guest Physical Address Width: %d bits\n",
705 (s.uEAX >> 0) & 0xff,
706 (s.uEAX >> 8) & 0xff,
707 (s.uEAX >> 16) & 0xff);
708 RTTestIPrintf(RTTESTLVL_ALWAYS,
709 "Physical Core Count: %d\n",
710 ((s.uECX >> 0) & 0xff) + 1);
711 if ((s.uECX >> 12) & 0xf)
712 RTTestIPrintf(RTTESTLVL_ALWAYS, "ApicIdCoreIdSize: %d bits\n", (s.uECX >> 12) & 0xf);
713 }
714
715 if (cExtFunctions >= 0x8000000a)
716 {
717 ASMCpuId(0x8000000a, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
718 RTTestIPrintf(RTTESTLVL_ALWAYS,
719 "SVM Revision: %d (%#x)\n"
720 "Number of Address Space IDs: %d (%#x)\n",
721 s.uEAX & 0xff, s.uEAX & 0xff,
722 s.uEBX, s.uEBX);
723 }
724 if (ASMCpuId_EAX(UINT32_C(0x80000000)) >= UINT32_C(0x8000001E))
725 RTTestIPrintf(RTTESTLVL_ALWAYS, "APIC ID(Ext 8000001b): %#010x\n", ASMGetApicIdExt8000001E());
726}
727
728# if 0
729static void bruteForceCpuId(void)
730{
731 RTTestISub("brute force CPUID leafs");
732 uint32_t auPrevValues[4] = { 0, 0, 0, 0};
733 uint32_t uLeaf = 0;
734 do
735 {
736 uint32_t auValues[4];
737 ASMCpuIdExSlow(uLeaf, 0, 0, 0, &auValues[0], &auValues[1], &auValues[2], &auValues[3]);
738 if ( (auValues[0] != auPrevValues[0] && auValues[0] != uLeaf)
739 || (auValues[1] != auPrevValues[1] && auValues[1] != 0)
740 || (auValues[2] != auPrevValues[2] && auValues[2] != 0)
741 || (auValues[3] != auPrevValues[3] && auValues[3] != 0)
742 || (uLeaf & (UINT32_C(0x08000000) - UINT32_C(1))) == 0)
743 {
744 RTTestIPrintf(RTTESTLVL_ALWAYS,
745 "%08x: %08x %08x %08x %08x\n", uLeaf,
746 auValues[0], auValues[1], auValues[2], auValues[3]);
747 }
748 auPrevValues[0] = auValues[0];
749 auPrevValues[1] = auValues[1];
750 auPrevValues[2] = auValues[2];
751 auPrevValues[3] = auValues[3];
752
753 //uint32_t uSubLeaf = 0;
754 //do
755 //{
756 //
757 //
758 //} while (false);
759 } while (uLeaf++ < UINT32_MAX);
760}
761# endif
762
763#endif /* AMD64 || X86 */
764
765#define TEST_READ(a_pVar, a_Type, a_Fmt, a_Function, a_Val) \
766 do { *a_pVar = a_Val; CHECKOP(a_Function(a_pVar), a_Val, a_Fmt, a_Type); CHECKVAL(*a_pVar, a_Val, a_Fmt); } while (0)
767
768DECLINLINE(void) tstASMAtomicReadU8Worker(uint8_t volatile *pu8)
769{
770 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 0);
771 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 1);
772 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 2);
773 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 16);
774 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 32);
775 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 32);
776 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 127);
777 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 128);
778 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 169);
779 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 239);
780 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 254);
781 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicReadU8, 255);
782
783 int8_t volatile *pi8 = (int8_t volatile *)pu8;
784 TEST_READ(pi8, uint8_t, "%d", ASMAtomicReadS8, INT8_MAX);
785 TEST_READ(pi8, uint8_t, "%d", ASMAtomicReadS8, INT8_MIN);
786 TEST_READ(pi8, uint8_t, "%d", ASMAtomicReadS8, 42);
787 TEST_READ(pi8, uint8_t, "%d", ASMAtomicReadS8, -21);
788
789 bool volatile *pf = (bool volatile *)pu8;
790 TEST_READ(pf, bool, "%d", ASMAtomicReadBool, true);
791 TEST_READ(pf, bool, "%d", ASMAtomicReadBool, false);
792}
793
794
795DECLINLINE(void) tstASMAtomicUoReadU8Worker(uint8_t volatile *pu8)
796{
797 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 0);
798 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 1);
799 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 2);
800 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 16);
801 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 32);
802 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 32);
803 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 127);
804 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 128);
805 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 169);
806 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 239);
807 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 254);
808 TEST_READ(pu8, uint8_t, "%#x", ASMAtomicUoReadU8, 255);
809
810 int8_t volatile *pi8 = (int8_t volatile *)pu8;
811 TEST_READ(pi8, uint8_t, "%d", ASMAtomicUoReadS8, INT8_MAX);
812 TEST_READ(pi8, uint8_t, "%d", ASMAtomicUoReadS8, INT8_MIN);
813 TEST_READ(pi8, uint8_t, "%d", ASMAtomicUoReadS8, 42);
814 TEST_READ(pi8, uint8_t, "%d", ASMAtomicUoReadS8, -21);
815
816 bool volatile *pf = (bool volatile *)pu8;
817 TEST_READ(pf, bool, "%d", ASMAtomicUoReadBool, true);
818 TEST_READ(pf, bool, "%d", ASMAtomicUoReadBool, false);
819}
820
821
822DECLINLINE(void) tstASMAtomicReadU16Worker(uint16_t volatile *pu16)
823{
824 TEST_READ(pu16, uint16_t, "%#x", ASMAtomicReadU16, 0);
825 TEST_READ(pu16, uint16_t, "%#x", ASMAtomicReadU16, 19983);
826 TEST_READ(pu16, uint16_t, "%#x", ASMAtomicReadU16, INT16_MAX);
827 TEST_READ(pu16, uint16_t, "%#x", ASMAtomicReadU16, UINT16_MAX);
828
829 int16_t volatile *pi16 = (int16_t volatile *)pu16;
830 TEST_READ(pi16, uint16_t, "%d", ASMAtomicReadS16, INT16_MAX);
831 TEST_READ(pi16, uint16_t, "%d", ASMAtomicReadS16, INT16_MIN);
832 TEST_READ(pi16, uint16_t, "%d", ASMAtomicReadS16, 42);
833 TEST_READ(pi16, uint16_t, "%d", ASMAtomicReadS16, -21);
834}
835
836
837DECLINLINE(void) tstASMAtomicUoReadU16Worker(uint16_t volatile *pu16)
838{
839 TEST_READ(pu16, uint16_t, "%#x", ASMAtomicUoReadU16, 0);
840 TEST_READ(pu16, uint16_t, "%#x", ASMAtomicUoReadU16, 19983);
841 TEST_READ(pu16, uint16_t, "%#x", ASMAtomicUoReadU16, INT16_MAX);
842 TEST_READ(pu16, uint16_t, "%#x", ASMAtomicUoReadU16, UINT16_MAX);
843
844 int16_t volatile *pi16 = (int16_t volatile *)pu16;
845 TEST_READ(pi16, uint16_t, "%d", ASMAtomicUoReadS16, INT16_MAX);
846 TEST_READ(pi16, uint16_t, "%d", ASMAtomicUoReadS16, INT16_MIN);
847 TEST_READ(pi16, uint16_t, "%d", ASMAtomicUoReadS16, 42);
848 TEST_READ(pi16, uint16_t, "%d", ASMAtomicUoReadS16, -21);
849}
850
851
852DECLINLINE(void) tstASMAtomicReadU32Worker(uint32_t volatile *pu32)
853{
854 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicReadU32, 0);
855 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicReadU32, 19983);
856 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicReadU32, INT16_MAX);
857 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicReadU32, UINT16_MAX);
858 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicReadU32, _1M-1);
859 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicReadU32, _1M+1);
860 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicReadU32, _1G-1);
861 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicReadU32, _1G+1);
862 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicReadU32, INT32_MAX);
863 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicReadU32, UINT32_MAX);
864
865 int32_t volatile *pi32 = (int32_t volatile *)pu32;
866 TEST_READ(pi32, uint32_t, "%d", ASMAtomicReadS32, INT32_MAX);
867 TEST_READ(pi32, uint32_t, "%d", ASMAtomicReadS32, INT32_MIN);
868 TEST_READ(pi32, uint32_t, "%d", ASMAtomicReadS32, 42);
869 TEST_READ(pi32, uint32_t, "%d", ASMAtomicReadS32, -21);
870
871#if ARCH_BITS == 32
872 size_t volatile *pcb = (size_t volatile *)pu32;
873 TEST_READ(pcb, size_t, "%#llz", ASMAtomicReadZ, 0);
874 TEST_READ(pcb, size_t, "%#llz", ASMAtomicReadZ, ~(size_t)2);
875 TEST_READ(pcb, size_t, "%#llz", ASMAtomicReadZ, ~(size_t)0 / 4);
876
877 void * volatile *ppv = (void * volatile *)pu32;
878 TEST_READ(ppv, void *, "%p", ASMAtomicReadPtr, NULL);
879 TEST_READ(ppv, void *, "%p", ASMAtomicReadPtr, (void *)~(uintptr_t)42);
880
881 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu32;
882 RTSEMEVENT hEvt = ASMAtomicReadPtrT(phEvt, RTSEMEVENT);
883 CHECKVAL(hEvt, (RTSEMEVENT)~(uintptr_t)42, "%p");
884
885 ASMAtomicReadHandle(phEvt, &hEvt);
886 CHECKVAL(hEvt, (RTSEMEVENT)~(uintptr_t)42, "%p");
887#endif
888}
889
890
891DECLINLINE(void) tstASMAtomicUoReadU32Worker(uint32_t volatile *pu32)
892{
893 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicUoReadU32, 0);
894 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicUoReadU32, 19983);
895 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicUoReadU32, INT16_MAX);
896 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicUoReadU32, UINT16_MAX);
897 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicUoReadU32, _1M-1);
898 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicUoReadU32, _1M+1);
899 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicUoReadU32, _1G-1);
900 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicUoReadU32, _1G+1);
901 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicUoReadU32, INT32_MAX);
902 TEST_READ(pu32, uint32_t, "%#x", ASMAtomicUoReadU32, UINT32_MAX);
903
904 int32_t volatile *pi32 = (int32_t volatile *)pu32;
905 TEST_READ(pi32, uint32_t, "%d", ASMAtomicUoReadS32, INT32_MAX);
906 TEST_READ(pi32, uint32_t, "%d", ASMAtomicUoReadS32, INT32_MIN);
907 TEST_READ(pi32, uint32_t, "%d", ASMAtomicUoReadS32, 42);
908 TEST_READ(pi32, uint32_t, "%d", ASMAtomicUoReadS32, -21);
909
910#if ARCH_BITS == 32
911 size_t volatile *pcb = (size_t volatile *)pu32;
912 TEST_READ(pcb, size_t, "%#llz", ASMAtomicUoReadZ, 0);
913 TEST_READ(pcb, size_t, "%#llz", ASMAtomicUoReadZ, ~(size_t)2);
914 TEST_READ(pcb, size_t, "%#llz", ASMAtomicUoReadZ, ~(size_t)0 / 4);
915
916 void * volatile *ppv = (void * volatile *)pu32;
917 TEST_READ(ppv, void *, "%p", ASMAtomicUoReadPtr, NULL);
918 TEST_READ(ppv, void *, "%p", ASMAtomicUoReadPtr, (void *)~(uintptr_t)42);
919
920 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu32;
921 RTSEMEVENT hEvt = ASMAtomicUoReadPtrT(phEvt, RTSEMEVENT);
922 CHECKVAL(hEvt, (RTSEMEVENT)~(uintptr_t)42, "%p");
923
924 ASMAtomicUoReadHandle(phEvt, &hEvt);
925 CHECKVAL(hEvt, (RTSEMEVENT)~(uintptr_t)42, "%p");
926#endif
927}
928
929
930DECLINLINE(void) tstASMAtomicReadU64Worker(uint64_t volatile *pu64)
931{
932 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, 0);
933 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, 19983);
934 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, INT16_MAX);
935 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, UINT16_MAX);
936 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, _1M-1);
937 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, _1M+1);
938 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, _1G-1);
939 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, _1G+1);
940 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, INT32_MAX);
941 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, UINT32_MAX);
942 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, INT64_MAX);
943 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, UINT64_MAX);
944 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicReadU64, UINT64_C(0x450872549687134));
945
946 int64_t volatile *pi64 = (int64_t volatile *)pu64;
947 TEST_READ(pi64, uint64_t, "%d", ASMAtomicReadS64, INT64_MAX);
948 TEST_READ(pi64, uint64_t, "%d", ASMAtomicReadS64, INT64_MIN);
949 TEST_READ(pi64, uint64_t, "%d", ASMAtomicReadS64, 42);
950 TEST_READ(pi64, uint64_t, "%d", ASMAtomicReadS64, -21);
951
952#if ARCH_BITS == 64
953 size_t volatile *pcb = (size_t volatile *)pu64;
954 TEST_READ(pcb, size_t, "%#llz", ASMAtomicReadZ, 0);
955 TEST_READ(pcb, size_t, "%#llz", ASMAtomicReadZ, ~(size_t)2);
956 TEST_READ(pcb, size_t, "%#llz", ASMAtomicReadZ, ~(size_t)0 / 4);
957
958 void * volatile *ppv = (void * volatile *)pu64;
959 TEST_READ(ppv, void *, "%p", ASMAtomicReadPtr, NULL);
960 TEST_READ(ppv, void *, "%p", ASMAtomicReadPtr, (void *)~(uintptr_t)42);
961
962 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu64;
963 RTSEMEVENT hEvt = ASMAtomicReadPtrT(phEvt, RTSEMEVENT);
964 CHECKVAL(hEvt, (RTSEMEVENT)~(uintptr_t)42, "%p");
965
966 ASMAtomicReadHandle(phEvt, &hEvt);
967 CHECKVAL(hEvt, (RTSEMEVENT)~(uintptr_t)42, "%p");
968#endif
969}
970
971
972DECLINLINE(void) tstASMAtomicUoReadU64Worker(uint64_t volatile *pu64)
973{
974 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, 0);
975 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, 19983);
976 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, INT16_MAX);
977 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, UINT16_MAX);
978 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, _1M-1);
979 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, _1M+1);
980 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, _1G-1);
981 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, _1G+1);
982 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, INT32_MAX);
983 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, UINT32_MAX);
984 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, INT64_MAX);
985 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, UINT64_MAX);
986 TEST_READ(pu64, uint64_t, "%#llx", ASMAtomicUoReadU64, UINT64_C(0x450872549687134));
987
988 int64_t volatile *pi64 = (int64_t volatile *)pu64;
989 TEST_READ(pi64, uint64_t, "%d", ASMAtomicUoReadS64, INT64_MAX);
990 TEST_READ(pi64, uint64_t, "%d", ASMAtomicUoReadS64, INT64_MIN);
991 TEST_READ(pi64, uint64_t, "%d", ASMAtomicUoReadS64, 42);
992 TEST_READ(pi64, uint64_t, "%d", ASMAtomicUoReadS64, -21);
993
994#if ARCH_BITS == 64
995 size_t volatile *pcb = (size_t volatile *)pu64;
996 TEST_READ(pcb, size_t, "%#llz", ASMAtomicUoReadZ, 0);
997 TEST_READ(pcb, size_t, "%#llz", ASMAtomicUoReadZ, ~(size_t)2);
998 TEST_READ(pcb, size_t, "%#llz", ASMAtomicUoReadZ, ~(size_t)0 / 4);
999
1000 void * volatile *ppv = (void * volatile *)pu64;
1001 TEST_READ(ppv, void *, "%p", ASMAtomicUoReadPtr, NULL);
1002 TEST_READ(ppv, void *, "%p", ASMAtomicUoReadPtr, (void *)~(uintptr_t)42);
1003
1004 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu64;
1005 RTSEMEVENT hEvt = ASMAtomicUoReadPtrT(phEvt, RTSEMEVENT);
1006 CHECKVAL(hEvt, (RTSEMEVENT)~(uintptr_t)42, "%p");
1007
1008 ASMAtomicUoReadHandle(phEvt, &hEvt);
1009 CHECKVAL(hEvt, (RTSEMEVENT)~(uintptr_t)42, "%p");
1010#endif
1011}
1012
1013
1014static void tstASMAtomicRead(void)
1015{
1016 DO_SIMPLE_TEST(ASMAtomicReadU8, uint8_t);
1017 DO_SIMPLE_TEST(ASMAtomicUoReadU8, uint8_t);
1018
1019 DO_SIMPLE_TEST(ASMAtomicReadU16, uint16_t);
1020 DO_SIMPLE_TEST(ASMAtomicUoReadU16, uint16_t);
1021
1022 DO_SIMPLE_TEST(ASMAtomicReadU32, uint32_t);
1023 DO_SIMPLE_TEST(ASMAtomicUoReadU32, uint32_t);
1024
1025 DO_SIMPLE_TEST(ASMAtomicReadU64, uint64_t);
1026 DO_SIMPLE_TEST(ASMAtomicUoReadU64, uint64_t);
1027}
1028
1029
1030#define TEST_WRITE(a_pVar, a_Type, a_Fmt, a_Function, a_Val) \
1031 do { a_Function(a_pVar, a_Val); CHECKVAL(*a_pVar, a_Val, a_Fmt); } while (0)
1032
1033DECLINLINE(void) tstASMAtomicWriteU8Worker(uint8_t volatile *pu8)
1034{
1035 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 0);
1036 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 1);
1037 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 2);
1038 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 16);
1039 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 32);
1040 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 32);
1041 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 127);
1042 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 128);
1043 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 169);
1044 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 239);
1045 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 254);
1046 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicWriteU8, 255);
1047
1048 volatile int8_t *pi8 = (volatile int8_t *)pu8;
1049 TEST_WRITE(pi8, int8_t, "%d", ASMAtomicWriteS8, INT8_MIN);
1050 TEST_WRITE(pi8, int8_t, "%d", ASMAtomicWriteS8, INT8_MAX);
1051 TEST_WRITE(pi8, int8_t, "%d", ASMAtomicWriteS8, 42);
1052 TEST_WRITE(pi8, int8_t, "%d", ASMAtomicWriteS8, -41);
1053
1054 volatile bool *pf = (volatile bool *)pu8;
1055 TEST_WRITE(pf, bool, "%d", ASMAtomicWriteBool, true);
1056 TEST_WRITE(pf, bool, "%d", ASMAtomicWriteBool, false);
1057}
1058
1059
1060DECLINLINE(void) tstASMAtomicUoWriteU8Worker(uint8_t volatile *pu8)
1061{
1062 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 0);
1063 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 1);
1064 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 2);
1065 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 16);
1066 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 32);
1067 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 32);
1068 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 127);
1069 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 128);
1070 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 169);
1071 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 239);
1072 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 254);
1073 TEST_WRITE(pu8, uint8_t, "%#x", ASMAtomicUoWriteU8, 255);
1074
1075 volatile int8_t *pi8 = (volatile int8_t *)pu8;
1076 TEST_WRITE(pi8, int8_t, "%d", ASMAtomicUoWriteS8, INT8_MIN);
1077 TEST_WRITE(pi8, int8_t, "%d", ASMAtomicUoWriteS8, INT8_MAX);
1078 TEST_WRITE(pi8, int8_t, "%d", ASMAtomicUoWriteS8, 42);
1079 TEST_WRITE(pi8, int8_t, "%d", ASMAtomicUoWriteS8, -41);
1080
1081 volatile bool *pf = (volatile bool *)pu8;
1082 TEST_WRITE(pf, bool, "%d", ASMAtomicUoWriteBool, true);
1083 TEST_WRITE(pf, bool, "%d", ASMAtomicUoWriteBool, false);
1084}
1085
1086
1087DECLINLINE(void) tstASMAtomicWriteU16Worker(uint16_t volatile *pu16)
1088{
1089 TEST_WRITE(pu16, uint16_t, "%#x", ASMAtomicWriteU16, 0);
1090 TEST_WRITE(pu16, uint16_t, "%#x", ASMAtomicWriteU16, 19983);
1091 TEST_WRITE(pu16, uint16_t, "%#x", ASMAtomicWriteU16, INT16_MAX);
1092 TEST_WRITE(pu16, uint16_t, "%#x", ASMAtomicWriteU16, UINT16_MAX);
1093
1094 volatile int16_t *pi16 = (volatile int16_t *)pu16;
1095 TEST_WRITE(pi16, int16_t, "%d", ASMAtomicWriteS16, INT16_MIN);
1096 TEST_WRITE(pi16, int16_t, "%d", ASMAtomicWriteS16, INT16_MAX);
1097 TEST_WRITE(pi16, int16_t, "%d", ASMAtomicWriteS16, 42);
1098 TEST_WRITE(pi16, int16_t, "%d", ASMAtomicWriteS16, -41);
1099}
1100
1101
1102DECLINLINE(void) tstASMAtomicUoWriteU16Worker(uint16_t volatile *pu16)
1103{
1104 TEST_WRITE(pu16, uint16_t, "%#x", ASMAtomicUoWriteU16, 0);
1105 TEST_WRITE(pu16, uint16_t, "%#x", ASMAtomicUoWriteU16, 19983);
1106 TEST_WRITE(pu16, uint16_t, "%#x", ASMAtomicUoWriteU16, INT16_MAX);
1107 TEST_WRITE(pu16, uint16_t, "%#x", ASMAtomicUoWriteU16, UINT16_MAX);
1108
1109 volatile int16_t *pi16 = (volatile int16_t *)pu16;
1110 TEST_WRITE(pi16, int16_t, "%d", ASMAtomicUoWriteS16, INT16_MIN);
1111 TEST_WRITE(pi16, int16_t, "%d", ASMAtomicUoWriteS16, INT16_MAX);
1112 TEST_WRITE(pi16, int16_t, "%d", ASMAtomicUoWriteS16, 42);
1113 TEST_WRITE(pi16, int16_t, "%d", ASMAtomicUoWriteS16, -41);
1114}
1115
1116
1117DECLINLINE(void) tstASMAtomicWriteU32Worker(uint32_t volatile *pu32)
1118{
1119 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicWriteU32, 0);
1120 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicWriteU32, 19983);
1121 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicWriteU32, INT16_MAX);
1122 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicWriteU32, UINT16_MAX);
1123 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicWriteU32, _1M-1);
1124 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicWriteU32, _1M+1);
1125 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicWriteU32, _1G-1);
1126 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicWriteU32, _1G+1);
1127 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicWriteU32, INT32_MAX);
1128 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicWriteU32, UINT32_MAX);
1129
1130 volatile int32_t *pi32 = (volatile int32_t *)pu32;
1131 TEST_WRITE(pi32, int32_t, "%d", ASMAtomicWriteS32, INT32_MIN);
1132 TEST_WRITE(pi32, int32_t, "%d", ASMAtomicWriteS32, INT32_MAX);
1133 TEST_WRITE(pi32, int32_t, "%d", ASMAtomicWriteS32, 42);
1134 TEST_WRITE(pi32, int32_t, "%d", ASMAtomicWriteS32, -41);
1135
1136#if ARCH_BITS == 32
1137 size_t volatile *pcb = (size_t volatile *)pu32;
1138 TEST_WRITE(pcb, size_t, "%#zx", ASMAtomicWriteZ, ~(size_t)42);
1139 TEST_WRITE(pcb, size_t, "%#zx", ASMAtomicWriteZ, 42);
1140
1141 void * volatile *ppv = (void * volatile *)pu32;
1142 TEST_WRITE(ppv, void *, "%#zx", ASMAtomicWritePtrVoid, NULL);
1143 TEST_WRITE(ppv, void *, "%#zx", ASMAtomicWritePtrVoid, (void *)~(uintptr_t)12938754);
1144
1145 ASMAtomicWriteNullPtr(ppv); CHECKVAL(*ppv, NULL, "%p");
1146 ASMAtomicWritePtr(ppv, (void *)~(intptr_t)2322434); CHECKVAL(*ppv, (void *)~(intptr_t)2322434, "%p");
1147
1148 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu32;
1149 ASMAtomicWriteHandle(phEvt, (RTSEMEVENT)(uintptr_t)99753456); CHECKVAL(*phEvt, (RTSEMEVENT)(uintptr_t)99753456, "%p");
1150#endif
1151}
1152
1153
1154DECLINLINE(void) tstASMAtomicUoWriteU32Worker(uint32_t volatile *pu32)
1155{
1156 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicUoWriteU32, 0);
1157 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicUoWriteU32, 19983);
1158 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicUoWriteU32, INT16_MAX);
1159 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicUoWriteU32, UINT16_MAX);
1160 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicUoWriteU32, _1M-1);
1161 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicUoWriteU32, _1M+1);
1162 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicUoWriteU32, _1G-1);
1163 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicUoWriteU32, _1G+1);
1164 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicUoWriteU32, INT32_MAX);
1165 TEST_WRITE(pu32, uint32_t, "%#x", ASMAtomicUoWriteU32, UINT32_MAX);
1166
1167 volatile int32_t *pi32 = (volatile int32_t *)pu32;
1168 TEST_WRITE(pi32, int32_t, "%d", ASMAtomicUoWriteS32, INT32_MIN);
1169 TEST_WRITE(pi32, int32_t, "%d", ASMAtomicUoWriteS32, INT32_MAX);
1170 TEST_WRITE(pi32, int32_t, "%d", ASMAtomicUoWriteS32, 42);
1171 TEST_WRITE(pi32, int32_t, "%d", ASMAtomicUoWriteS32, -41);
1172
1173#if ARCH_BITS == 32
1174 size_t volatile *pcb = (size_t volatile *)pu32;
1175 TEST_WRITE(pcb, size_t, "%#zx", ASMAtomicUoWriteZ, ~(size_t)42);
1176 TEST_WRITE(pcb, size_t, "%#zx", ASMAtomicUoWriteZ, 42);
1177
1178 void * volatile *ppv = (void * volatile *)pu32;
1179 TEST_WRITE(ppv, void *, "%#zx", ASMAtomicUoWritePtrVoid, NULL);
1180 TEST_WRITE(ppv, void *, "%#zx", ASMAtomicUoWritePtrVoid, (void *)~(uintptr_t)12938754);
1181
1182 ASMAtomicUoWriteNullPtr(ppv); CHECKVAL(*ppv, NULL, "%p");
1183 ASMAtomicUoWritePtr(ppv, (void *)~(intptr_t)2322434); CHECKVAL(*ppv, (void *)~(intptr_t)2322434, "%p");
1184
1185 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu32;
1186 ASMAtomicUoWriteHandle(phEvt, (RTSEMEVENT)(uintptr_t)99753456); CHECKVAL(*phEvt, (RTSEMEVENT)(uintptr_t)99753456, "%p");
1187#endif
1188}
1189
1190
1191DECLINLINE(void) tstASMAtomicWriteU64Worker(uint64_t volatile *pu64)
1192{
1193 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, 0);
1194 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, 19983);
1195 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, INT16_MAX);
1196 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, UINT16_MAX);
1197 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, _1M-1);
1198 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, _1M+1);
1199 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, _1G-1);
1200 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, _1G+1);
1201 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, INT32_MAX);
1202 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, UINT32_MAX);
1203 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, INT64_MAX);
1204 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, UINT64_MAX);
1205 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicWriteU64, UINT64_C(0x450872549687134));
1206
1207 volatile int64_t *pi64 = (volatile int64_t *)pu64;
1208 TEST_WRITE(pi64, int64_t, "%d", ASMAtomicWriteS64, INT64_MIN);
1209 TEST_WRITE(pi64, int64_t, "%d", ASMAtomicWriteS64, INT64_MAX);
1210 TEST_WRITE(pi64, int64_t, "%d", ASMAtomicWriteS64, 42);
1211
1212#if ARCH_BITS == 64
1213 size_t volatile *pcb = (size_t volatile *)pu64;
1214 TEST_WRITE(pcb, size_t, "%#zx", ASMAtomicWriteZ, ~(size_t)42);
1215 TEST_WRITE(pcb, size_t, "%#zx", ASMAtomicWriteZ, 42);
1216
1217 void * volatile *ppv = (void * volatile *)pu64;
1218 TEST_WRITE(ppv, void *, "%#zx", ASMAtomicWritePtrVoid, NULL);
1219 TEST_WRITE(ppv, void *, "%#zx", ASMAtomicWritePtrVoid, (void *)~(uintptr_t)12938754);
1220
1221 ASMAtomicWriteNullPtr(ppv); CHECKVAL(*ppv, NULL, "%p");
1222 ASMAtomicWritePtr(ppv, (void *)~(intptr_t)2322434); CHECKVAL(*ppv, (void *)~(intptr_t)2322434, "%p");
1223
1224 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu64;
1225 ASMAtomicWriteHandle(phEvt, (RTSEMEVENT)(uintptr_t)99753456); CHECKVAL(*phEvt, (RTSEMEVENT)(uintptr_t)99753456, "%p");
1226#endif
1227}
1228
1229
1230DECLINLINE(void) tstASMAtomicUoWriteU64Worker(uint64_t volatile *pu64)
1231{
1232 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, 0);
1233 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, 19983);
1234 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, INT16_MAX);
1235 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, UINT16_MAX);
1236 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, _1M-1);
1237 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, _1M+1);
1238 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, _1G-1);
1239 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, _1G+1);
1240 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, INT32_MAX);
1241 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, UINT32_MAX);
1242 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, INT64_MAX);
1243 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, UINT64_MAX);
1244 TEST_WRITE(pu64, uint64_t, "%#llx", ASMAtomicUoWriteU64, UINT64_C(0x450872549687134));
1245
1246 volatile int64_t *pi64 = (volatile int64_t *)pu64;
1247 TEST_WRITE(pi64, int64_t, "%d", ASMAtomicUoWriteS64, INT64_MIN);
1248 TEST_WRITE(pi64, int64_t, "%d", ASMAtomicUoWriteS64, INT64_MAX);
1249 TEST_WRITE(pi64, int64_t, "%d", ASMAtomicUoWriteS64, 42);
1250
1251#if ARCH_BITS == 64
1252 size_t volatile *pcb = (size_t volatile *)pu64;
1253 TEST_WRITE(pcb, size_t, "%#zx", ASMAtomicUoWriteZ, ~(size_t)42);
1254 TEST_WRITE(pcb, size_t, "%#zx", ASMAtomicUoWriteZ, 42);
1255
1256 void * volatile *ppv = (void * volatile *)pu64;
1257 TEST_WRITE(ppv, void *, "%#zx", ASMAtomicUoWritePtrVoid, NULL);
1258 TEST_WRITE(ppv, void *, "%#zx", ASMAtomicUoWritePtrVoid, (void *)~(uintptr_t)12938754);
1259
1260 ASMAtomicUoWriteNullPtr(ppv); CHECKVAL(*ppv, NULL, "%p");
1261 ASMAtomicUoWritePtr(ppv, (void *)~(intptr_t)2322434); CHECKVAL(*ppv, (void *)~(intptr_t)2322434, "%p");
1262
1263 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu64;
1264 ASMAtomicUoWriteHandle(phEvt, (RTSEMEVENT)(uintptr_t)99753456); CHECKVAL(*phEvt, (RTSEMEVENT)(uintptr_t)99753456, "%p");
1265#endif
1266}
1267
1268static void tstASMAtomicWrite(void)
1269{
1270 DO_SIMPLE_TEST(ASMAtomicWriteU8, uint8_t);
1271 DO_SIMPLE_TEST(ASMAtomicUoWriteU8, uint8_t);
1272
1273 DO_SIMPLE_TEST(ASMAtomicWriteU16, uint16_t);
1274 DO_SIMPLE_TEST(ASMAtomicUoWriteU16, uint16_t);
1275
1276 DO_SIMPLE_TEST(ASMAtomicWriteU32, uint32_t);
1277 DO_SIMPLE_TEST(ASMAtomicUoWriteU32, uint32_t);
1278
1279 DO_SIMPLE_TEST(ASMAtomicWriteU64, uint64_t);
1280 DO_SIMPLE_TEST(ASMAtomicUoWriteU64, uint64_t);
1281}
1282
1283
1284DECLINLINE(void) tstASMAtomicXchgU8Worker(uint8_t volatile *pu8)
1285{
1286 *pu8 = 0;
1287 CHECK_OP_AND_VAL(uint8_t, "%#x", pu8, ASMAtomicXchgU8(pu8, 1), 0, 1);
1288 CHECK_OP_AND_VAL(uint8_t, "%#x", pu8, ASMAtomicXchgU8(pu8, UINT8_C(0xff)), 1, UINT8_C(0xff));
1289 CHECK_OP_AND_VAL(uint8_t, "%#x", pu8, ASMAtomicXchgU8(pu8, UINT8_C(0x87)), UINT8_C(0xff), UINT8_C(0x87));
1290 CHECK_OP_AND_VAL(uint8_t, "%#x", pu8, ASMAtomicXchgU8(pu8, UINT8_C(0xfe)), UINT8_C(0x87), UINT8_C(0xfe));
1291
1292 int8_t volatile *pi8 = (int8_t volatile *)pu8;
1293 CHECK_OP_AND_VAL(int8_t, "%d", pi8, ASMAtomicXchgS8(pi8, INT8_C(-4)), INT8_C(-2), INT8_C(-4));
1294 CHECK_OP_AND_VAL(int8_t, "%d", pi8, ASMAtomicXchgS8(pi8, INT8_C(4)), INT8_C(-4), INT8_C(4));
1295 CHECK_OP_AND_VAL(int8_t, "%d", pi8, ASMAtomicXchgS8(pi8, INT8_MAX), INT8_C(4), INT8_MAX);
1296 CHECK_OP_AND_VAL(int8_t, "%d", pi8, ASMAtomicXchgS8(pi8, INT8_MIN), INT8_MAX, INT8_MIN);
1297 CHECK_OP_AND_VAL(int8_t, "%d", pi8, ASMAtomicXchgS8(pi8, 1), INT8_MIN, 1);
1298
1299 bool volatile *pf = (bool volatile *)pu8;
1300 CHECK_OP_AND_VAL(bool, "%d", pf, ASMAtomicXchgBool(pf, false), true, false);
1301 CHECK_OP_AND_VAL(bool, "%d", pf, ASMAtomicXchgBool(pf, false), false, false);
1302 CHECK_OP_AND_VAL(bool, "%d", pf, ASMAtomicXchgBool(pf, true), false, true);
1303}
1304
1305
1306DECLINLINE(void) tstASMAtomicXchgU16Worker(uint16_t volatile *pu16)
1307{
1308 *pu16 = 0;
1309 CHECK_OP_AND_VAL(uint16_t, "%#x", pu16, ASMAtomicXchgU16(pu16, 1), 0, 1);
1310 CHECK_OP_AND_VAL(uint16_t, "%#x", pu16, ASMAtomicXchgU16(pu16, 0), 1, 0);
1311 CHECK_OP_AND_VAL(uint16_t, "%#x", pu16, ASMAtomicXchgU16(pu16, UINT16_MAX), 0, UINT16_MAX);
1312 CHECK_OP_AND_VAL(uint16_t, "%#x", pu16, ASMAtomicXchgU16(pu16, UINT16_C(0x7fff)), UINT16_MAX, UINT16_C(0x7fff));
1313 CHECK_OP_AND_VAL(uint16_t, "%#x", pu16, ASMAtomicXchgU16(pu16, UINT16_C(0x8765)), UINT16_C(0x7fff), UINT16_C(0x8765));
1314 CHECK_OP_AND_VAL(uint16_t, "%#x", pu16, ASMAtomicXchgU16(pu16, UINT16_C(0xfffe)), UINT16_C(0x8765), UINT16_C(0xfffe));
1315
1316 int16_t volatile *pi16 = (int16_t volatile *)pu16;
1317 CHECK_OP_AND_VAL(int16_t, "%d", pi16, ASMAtomicXchgS16(pi16, INT16_MIN), INT16_C(-2), INT16_MIN);
1318 CHECK_OP_AND_VAL(int16_t, "%d", pi16, ASMAtomicXchgS16(pi16, INT16_MAX), INT16_MIN, INT16_MAX);
1319 CHECK_OP_AND_VAL(int16_t, "%d", pi16, ASMAtomicXchgS16(pi16, -8), INT16_MAX, -8);
1320 CHECK_OP_AND_VAL(int16_t, "%d", pi16, ASMAtomicXchgS16(pi16, 8), -8, 8);
1321}
1322
1323
1324DECLINLINE(void) tstASMAtomicXchgU32Worker(uint32_t volatile *pu32)
1325{
1326 *pu32 = 0;
1327 CHECK_OP_AND_VAL(uint32_t, "%#x", pu32, ASMAtomicXchgU32(pu32, 1), 0, 1);
1328 CHECK_OP_AND_VAL(uint32_t, "%#x", pu32, ASMAtomicXchgU32(pu32, 0), 1, 0);
1329 CHECK_OP_AND_VAL(uint32_t, "%#x", pu32, ASMAtomicXchgU32(pu32, UINT32_MAX), 0, UINT32_MAX);
1330 CHECK_OP_AND_VAL(uint32_t, "%#x", pu32, ASMAtomicXchgU32(pu32, UINT32_C(0x87654321)), UINT32_MAX, UINT32_C(0x87654321));
1331 CHECK_OP_AND_VAL(uint32_t, "%#x", pu32, ASMAtomicXchgU32(pu32, UINT32_C(0xfffffffe)), UINT32_C(0x87654321), UINT32_C(0xfffffffe));
1332
1333 int32_t volatile *pi32 = (int32_t volatile *)pu32;
1334 CHECK_OP_AND_VAL(int32_t, "%d", pi32, ASMAtomicXchgS32(pi32, INT32_MIN), INT32_C(-2), INT32_MIN);
1335 CHECK_OP_AND_VAL(int32_t, "%d", pi32, ASMAtomicXchgS32(pi32, INT32_MAX), INT32_MIN, INT32_MAX);
1336 CHECK_OP_AND_VAL(int32_t, "%d", pi32, ASMAtomicXchgS32(pi32, -16), INT32_MAX, -16);
1337 CHECK_OP_AND_VAL(int32_t, "%d", pi32, ASMAtomicXchgS32(pi32, 16), -16, 16);
1338
1339#if ARCH_BITS == 32
1340 size_t volatile *pcb = (size_t volatile *)pu32;
1341 CHECK_OP_AND_VAL(size_t, "%#zx", pcb, ASMAtomicXchgZ(pcb, UINT32_C(0x9481239b)), 0x10, UINT32_C(0x9481239b));
1342 CHECK_OP_AND_VAL(size_t, "%#zx", pcb, ASMAtomicXchgZ(pcb, UINT32_C(0xcdef1234)), UINT32_C(0x9481239b), UINT32_C(0xcdef1234));
1343#endif
1344
1345#if R0_ARCH_BITS == 32
1346 RTR0PTR volatile *pR0Ptr = (RTR0PTR volatile *)pu32;
1347 CHECK_OP_AND_VAL(size_t, "%#llx", pcb, ASMAtomicXchgR0Ptr(pR0Ptr, UINT32_C(0x80341237)), UINT32_C(0xcdef1234), UINT32_C(0x80341237));
1348#endif
1349}
1350
1351
1352DECLINLINE(void) tstASMAtomicXchgU64Worker(uint64_t volatile *pu64)
1353{
1354 *pu64 = 0;
1355 CHECK_OP_AND_VAL(uint64_t, "%#llx", pu64, ASMAtomicXchgU64(pu64, 1), 0, 1);
1356 CHECK_OP_AND_VAL(uint64_t, "%#llx", pu64, ASMAtomicXchgU64(pu64, 0), 1, 0);
1357 CHECK_OP_AND_VAL(uint64_t, "%#llx", pu64, ASMAtomicXchgU64(pu64, UINT64_MAX), 0, UINT64_MAX);
1358 CHECK_OP_AND_VAL(uint64_t, "%#llx", pu64, ASMAtomicXchgU64(pu64, UINT64_C(0xfedcba0987654321)), UINT64_MAX, UINT64_C(0xfedcba0987654321));
1359 CHECK_OP_AND_VAL(uint64_t, "%#llx", pu64, ASMAtomicXchgU64(pu64, UINT64_C(0xfffffffffffffffe)), UINT64_C(0xfedcba0987654321), UINT64_C(0xfffffffffffffffe));
1360
1361 int64_t volatile *pi64 = (int64_t volatile *)pu64;
1362 CHECK_OP_AND_VAL(int64_t, "%lld", pi64, ASMAtomicXchgS64(pi64, INT64_MAX), -2, INT64_MAX);
1363 CHECK_OP_AND_VAL(int64_t, "%lld", pi64, ASMAtomicXchgS64(pi64, INT64_MIN), INT64_MAX, INT64_MIN);
1364 CHECK_OP_AND_VAL(int64_t, "%lld", pi64, ASMAtomicXchgS64(pi64, -32), INT64_MIN, -32);
1365 CHECK_OP_AND_VAL(int64_t, "%lld", pi64, ASMAtomicXchgS64(pi64, 32), -32, 32);
1366
1367#if ARCH_BITS == 64
1368 size_t volatile *pcb = (size_t volatile *)pu64;
1369 CHECK_OP_AND_VAL(size_t, "%#zx", pcb, ASMAtomicXchgZ(pcb, UINT64_C(0x94812396759)), 0x20, UINT64_C(0x94812396759));
1370 CHECK_OP_AND_VAL(size_t, "%#zx", pcb, ASMAtomicXchgZ(pcb, UINT64_C(0xcdef1234abdf7896)), UINT64_C(0x94812396759), UINT64_C(0xcdef1234abdf7896));
1371#endif
1372
1373#if R0_ARCH_BITS == 64
1374 RTR0PTR volatile *pR0Ptr = (RTR0PTR volatile *)pu64;
1375 CHECK_OP_AND_VAL(size_t, "%#llx", pcb, ASMAtomicXchgR0Ptr(pR0Ptr, UINT64_C(0xfedc1234567890ab)), UINT64_C(0xcdef1234abdf7896), UINT64_C(0xfedc1234567890ab));
1376#endif
1377}
1378
1379
1380DECLINLINE(void) tstASMAtomicXchgPtrWorker(void * volatile *ppv)
1381{
1382 *ppv = NULL;
1383 CHECK_OP_AND_VAL(void *, "%p", ppv, ASMAtomicXchgPtr(ppv, (void *)(~(uintptr_t)0)), NULL, (void *)(~(uintptr_t)0));
1384 CHECK_OP_AND_VAL(void *, "%p", ppv, ASMAtomicXchgPtr(ppv, (void *)(~(uintptr_t)0x87654321)), (void *)(~(uintptr_t)0), (void *)(~(uintptr_t)0x87654321));
1385 CHECK_OP_AND_VAL(void *, "%p", ppv, ASMAtomicXchgPtr(ppv, NULL), (void *)(~(uintptr_t)0x87654321), NULL);
1386
1387 CHECK_OP_AND_VAL(void *, "%p", ppv, ASMAtomicXchgR3Ptr(ppv, (void *)ppv), NULL, (void *)ppv);
1388
1389 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)ppv;
1390 RTSEMEVENT hRet;
1391 ASMAtomicXchgHandle(phEvt, (RTSEMEVENT)(~(uintptr_t)12345), &hRet);
1392 CHECKVAL(hRet, (RTSEMEVENT)ppv, "%p");
1393 CHECKVAL(*phEvt, (RTSEMEVENT)(~(uintptr_t)12345), "%p");
1394}
1395
1396
1397static void tstASMAtomicXchg(void)
1398{
1399 DO_SIMPLE_TEST(ASMAtomicXchgU8, uint8_t);
1400 DO_SIMPLE_TEST(ASMAtomicXchgU16, uint16_t);
1401 DO_SIMPLE_TEST(ASMAtomicXchgU32, uint32_t);
1402 DO_SIMPLE_TEST(ASMAtomicXchgU64, uint64_t);
1403 DO_SIMPLE_TEST(ASMAtomicXchgPtr, void *);
1404}
1405
1406
1407DECLINLINE(void) tstASMAtomicCmpXchgU8Worker(uint8_t volatile *pu8)
1408{
1409 *pu8 = 0xff;
1410 CHECK_OP_AND_VAL_EX(bool, "%d", "%#x", pu8, ASMAtomicCmpXchgU8(pu8, 0, 0), false, 0xff);
1411 CHECK_OP_AND_VAL_EX(bool, "%d", "%#x", pu8, ASMAtomicCmpXchgU8(pu8, 0, 0xff), true, 0);
1412 CHECK_OP_AND_VAL_EX(bool, "%d", "%#x", pu8, ASMAtomicCmpXchgU8(pu8, 0x97, 0), true, 0x97);
1413 CHECK_OP_AND_VAL_EX(bool, "%d", "%#x", pu8, ASMAtomicCmpXchgU8(pu8, 0x97, 0), false, 0x97);
1414 CHECK_OP_AND_VAL_EX(bool, "%d", "%#x", pu8, ASMAtomicCmpXchgU8(pu8, 0x7f, 0x97), true, 0x7f);
1415
1416 int8_t volatile *pi8 = (int8_t volatile *)pu8;
1417 CHECK_OP_AND_VAL(bool, "%d", pi8, ASMAtomicCmpXchgS8(pi8, -2, 0x7f), true, -2);
1418 CHECK_OP_AND_VAL(bool, "%d", pi8, ASMAtomicCmpXchgS8(pi8, INT8_MAX, -2), true, INT8_MAX);
1419 CHECK_OP_AND_VAL(bool, "%d", pi8, ASMAtomicCmpXchgS8(pi8, INT8_MAX, INT8_MIN), false, INT8_MAX);
1420 CHECK_OP_AND_VAL(bool, "%d", pi8, ASMAtomicCmpXchgS8(pi8, INT8_MIN, INT8_MAX), true, INT8_MIN);
1421 CHECK_OP_AND_VAL(bool, "%d", pi8, ASMAtomicCmpXchgS8(pi8, 1, INT8_MIN), true, 1);
1422
1423 bool volatile *pf = (bool volatile *)pu8;
1424 CHECK_OP_AND_VAL(bool, "%d", pf, ASMAtomicCmpXchgBool(pf, true, true), true, true);
1425 CHECK_OP_AND_VAL(bool, "%d", pf, ASMAtomicCmpXchgBool(pf, false, true), true, false);
1426 CHECK_OP_AND_VAL(bool, "%d", pf, ASMAtomicCmpXchgBool(pf, false, true), false, false);
1427 CHECK_OP_AND_VAL(bool, "%d", pf, ASMAtomicCmpXchgBool(pf, false, false), true, false);
1428}
1429
1430
1431DECLINLINE(void) tstASMAtomicCmpXchgU32Worker(uint32_t volatile *pu32)
1432{
1433 *pu32 = UINT32_C(0xffffffff);
1434 CHECK_OP_AND_VAL_EX(bool, "%d", "%#x", pu32, ASMAtomicCmpXchgU32(pu32, 0, 0), false, UINT32_C(0xffffffff));
1435 CHECK_OP_AND_VAL_EX(bool, "%d", "%#x", pu32, ASMAtomicCmpXchgU32(pu32, 0, UINT32_C(0xffffffff)), true, 0);
1436 CHECK_OP_AND_VAL_EX(bool, "%d", "%#x", pu32, ASMAtomicCmpXchgU32(pu32, UINT32_C(0x80088efd), UINT32_C(0x12345678)), false, 0);
1437 CHECK_OP_AND_VAL_EX(bool, "%d", "%#x", pu32, ASMAtomicCmpXchgU32(pu32, UINT32_C(0x80088efd), 0), true, UINT32_C(0x80088efd));
1438 CHECK_OP_AND_VAL_EX(bool, "%d", "%#x", pu32, ASMAtomicCmpXchgU32(pu32, UINT32_C(0xfffffffe), UINT32_C(0x80088efd)), true, UINT32_C(0xfffffffe));
1439
1440 int32_t volatile *pi32 = (int32_t volatile *)pu32;
1441 CHECK_OP_AND_VAL_EX(bool, "%d", "%d", pi32, ASMAtomicCmpXchgS32(pi32, INT32_MIN, 2), false, -2);
1442 CHECK_OP_AND_VAL_EX(bool, "%d", "%d", pi32, ASMAtomicCmpXchgS32(pi32, INT32_MIN, -2), true, INT32_MIN);
1443 CHECK_OP_AND_VAL_EX(bool, "%d", "%d", pi32, ASMAtomicCmpXchgS32(pi32, -19, -2), false, INT32_MIN);
1444 CHECK_OP_AND_VAL_EX(bool, "%d", "%d", pi32, ASMAtomicCmpXchgS32(pi32, -19, INT32_MIN), true, -19);
1445 CHECK_OP_AND_VAL_EX(bool, "%d", "%d", pi32, ASMAtomicCmpXchgS32(pi32, -19, INT32_MIN), false, -19);
1446 CHECK_OP_AND_VAL_EX(bool, "%d", "%d", pi32, ASMAtomicCmpXchgS32(pi32, 19, -19), true, 19);
1447 CHECK_OP_AND_VAL_EX(bool, "%d", "%d", pi32, ASMAtomicCmpXchgS32(pi32, INT32_MAX, -234), false, 19);
1448 CHECK_OP_AND_VAL_EX(bool, "%d", "%d", pi32, ASMAtomicCmpXchgS32(pi32, INT32_MAX, 19), true, INT32_MAX);
1449
1450#if ARCH_BITS == 32
1451 *pu32 = 29;
1452 void * volatile *ppv = (void * volatile *)pu32;
1453 CHECK_OP_AND_VAL_EX(bool, "%d", "%p", ppv, ASMAtomicCmpXchgPtrVoid(ppv, NULL, (void *)(intptr_t)-29), false, (void *)(intptr_t)29);
1454 CHECK_OP_AND_VAL_EX(bool, "%d", "%p", ppv, ASMAtomicCmpXchgPtrVoid(ppv, NULL, (void *)(intptr_t)29), true, NULL);
1455 CHECK_OP_AND_VAL_EX(bool, "%d", "%p", ppv, ASMAtomicCmpXchgPtrVoid(ppv, NULL, (void *)(intptr_t)29), false, NULL);
1456 CHECK_OP_AND_VAL_EX(bool, "%d", "%p", ppv, ASMAtomicCmpXchgPtrVoid(ppv, (void *)~(uintptr_t)42, NULL), true, (void *)~(uintptr_t)42);
1457
1458 bool fRc;
1459 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu32;
1460 ASMAtomicCmpXchgHandle(phEvt, (RTSEMEVENT)~(uintptr_t)0x12356389, (RTSEMEVENT)NULL, fRc);
1461 CHECKVAL(fRc, false, "%d");
1462 CHECKVAL(*phEvt, (RTSEMEVENT)~(uintptr_t)42, "%p");
1463
1464 ASMAtomicCmpXchgHandle(phEvt, (RTSEMEVENT)~(uintptr_t)0x12356389, (RTSEMEVENT)~(uintptr_t)42, fRc);
1465 CHECKVAL(fRc, true, "%d");
1466 CHECKVAL(*phEvt, (RTSEMEVENT)~(uintptr_t)0x12356389, "%p");
1467#endif
1468}
1469
1470
1471DECLINLINE(void) tstASMAtomicCmpXchgU64Worker(uint64_t volatile *pu64)
1472{
1473 *pu64 = UINT64_C(0xffffffffffffff);
1474 CHECK_OP_AND_VAL_EX(bool, "%d", "%#llx", pu64, ASMAtomicCmpXchgU64(pu64, 0, 0), false, UINT64_C(0xffffffffffffff));
1475 CHECK_OP_AND_VAL_EX(bool, "%d", "%#llx", pu64, ASMAtomicCmpXchgU64(pu64, 0, UINT64_C(0xffffffffffffff)), true, 0);
1476 CHECK_OP_AND_VAL_EX(bool, "%d", "%#llx", pu64, ASMAtomicCmpXchgU64(pu64, UINT64_C(0x80040008008efd), 1), false, 0);
1477 CHECK_OP_AND_VAL_EX(bool, "%d", "%#llx", pu64, ASMAtomicCmpXchgU64(pu64, UINT64_C(0x80040008008efd), 0), true, UINT64_C(0x80040008008efd));
1478 CHECK_OP_AND_VAL_EX(bool, "%d", "%#llx", pu64, ASMAtomicCmpXchgU64(pu64, UINT64_C(0x80040008008efd), 0), false, UINT64_C(0x80040008008efd));
1479 CHECK_OP_AND_VAL_EX(bool, "%d", "%#llx", pu64, ASMAtomicCmpXchgU64(pu64, UINT64_C(0xfffffffffffffffd), UINT64_C(0x80040008008efd)), true, UINT64_C(0xfffffffffffffffd));
1480
1481 int64_t volatile *pi64 = (int64_t volatile *)pu64;
1482 CHECK_OP_AND_VAL_EX(bool, "%d", "%#lld", pi64, ASMAtomicCmpXchgS64(pi64, INT64_MAX, 0), false, -3);
1483 CHECK_OP_AND_VAL_EX(bool, "%d", "%#lld", pi64, ASMAtomicCmpXchgS64(pi64, INT64_MAX, -3), true, INT64_MAX);
1484 CHECK_OP_AND_VAL_EX(bool, "%d", "%#lld", pi64, ASMAtomicCmpXchgS64(pi64, INT64_MIN, INT64_MIN), false, INT64_MAX);
1485 CHECK_OP_AND_VAL_EX(bool, "%d", "%#lld", pi64, ASMAtomicCmpXchgS64(pi64, INT64_MIN, INT64_MAX), true, INT64_MIN);
1486 CHECK_OP_AND_VAL_EX(bool, "%d", "%#lld", pi64, ASMAtomicCmpXchgS64(pi64, -29, -29), false, INT64_MIN);
1487 CHECK_OP_AND_VAL_EX(bool, "%d", "%#lld", pi64, ASMAtomicCmpXchgS64(pi64, -29, INT64_MIN), true, -29);
1488 CHECK_OP_AND_VAL_EX(bool, "%d", "%#lld", pi64, ASMAtomicCmpXchgS64(pi64, -29, INT64_MIN), false, -29);
1489 CHECK_OP_AND_VAL_EX(bool, "%d", "%#lld", pi64, ASMAtomicCmpXchgS64(pi64, 29, -29), true, 29);
1490
1491#if ARCH_BITS == 64
1492 void * volatile *ppv = (void * volatile *)pu64;
1493 CHECK_OP_AND_VAL_EX(bool, "%d", "%p", ppv, ASMAtomicCmpXchgPtrVoid(ppv, NULL, (void *)(intptr_t)-29), false, (void *)(intptr_t)29);
1494 CHECK_OP_AND_VAL_EX(bool, "%d", "%p", ppv, ASMAtomicCmpXchgPtrVoid(ppv, NULL, (void *)(intptr_t)29), true, NULL);
1495 CHECK_OP_AND_VAL_EX(bool, "%d", "%p", ppv, ASMAtomicCmpXchgPtrVoid(ppv, NULL, (void *)(intptr_t)29), false, NULL);
1496 CHECK_OP_AND_VAL_EX(bool, "%d", "%p", ppv, ASMAtomicCmpXchgPtrVoid(ppv, (void *)~(uintptr_t)42, NULL), true, (void *)~(uintptr_t)42);
1497
1498 bool fRc;
1499 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu64;
1500 ASMAtomicCmpXchgHandle(phEvt, (RTSEMEVENT)~(uintptr_t)0x12356389, (RTSEMEVENT)NULL, fRc);
1501 CHECKVAL(fRc, false, "%d");
1502 CHECKVAL(*phEvt, (RTSEMEVENT)~(uintptr_t)42, "%p");
1503
1504 ASMAtomicCmpXchgHandle(phEvt, (RTSEMEVENT)~(uintptr_t)0x12356389, (RTSEMEVENT)~(uintptr_t)42, fRc);
1505 CHECKVAL(fRc, true, "%d");
1506 CHECKVAL(*phEvt, (RTSEMEVENT)~(uintptr_t)0x12356389, "%p");
1507#endif
1508}
1509
1510
1511#ifdef RTASM_HAVE_CMP_WRITE_U128
1512DECLINLINE(void) tstASMAtomicCmpWriteU128Worker(RTUINT128U volatile *pu128)
1513{
1514 pu128->s.Lo = UINT64_C(0xffffffffffffff);
1515 pu128->s.Hi = UINT64_C(0xffffffffffffff);
1516
1517 RTUINT128U u128A, u128B;
1518 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpWriteU128U(pu128,
1519 u128A = RTUINT128_INIT_C(0, 0),
1520 u128B = RTUINT128_INIT_C(0, 0)),
1521 false, 0xffffffffffffff, 0xffffffffffffff);
1522 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpWriteU128U(pu128,
1523 u128A = RTUINT128_INIT_C(0, 0),
1524 u128B = RTUINT128_INIT_C(0xffffffffffffff, 0xffffffffffffff)),
1525 true, 0, 0);
1526
1527 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpWriteU128U(pu128,
1528 u128A = RTUINT128_INIT_C(0x80040008008efd, 0x40080004004def),
1529 u128B = RTUINT128_INIT_C(0, 1)),
1530 false, 0, 0);
1531 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpWriteU128U(pu128,
1532 u128A = RTUINT128_INIT_C(0x80040008008efd, 0x40080004004def),
1533 u128B = RTUINT128_INIT_C(1, 0)),
1534 false, 0, 0);
1535 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpWriteU128U(pu128,
1536 u128A = RTUINT128_INIT_C(0x80040008008efd, 0x40080004004def),
1537 u128B = RTUINT128_INIT_C(0, 0)),
1538 true, 0x80040008008efd, 0x40080004004def);
1539
1540 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpWriteU128U(pu128,
1541 u128A = RTUINT128_INIT_C(0xfff40ff8f08ef3, 0x4ee8ee04cc4de4),
1542 u128B = RTUINT128_INIT_C(0x80040008008efd, 0)),
1543 false, 0x80040008008efd, 0x40080004004def);
1544 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpWriteU128U(pu128,
1545 u128A = RTUINT128_INIT_C(0xfff40ff8f08ef3, 0x4ee8ee04cc4de4),
1546 u128B = RTUINT128_INIT_C(0, 0x40080004004def)),
1547 false, 0x80040008008efd, 0x40080004004def);
1548 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpWriteU128U(pu128,
1549 u128A = RTUINT128_INIT_C(0xfff40ff8f08ef3, 0x4ee8ee04cc4de4),
1550 u128B = RTUINT128_INIT_C(0x80040008008efd, 0x40080004004def)),
1551 true, 0xfff40ff8f08ef3, 0x4ee8ee04cc4de4);
1552
1553 /* Make sure the v2 version works too (arm) */
1554 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpWriteU128v2(&pu128->u,
1555 UINT64_C(0x95487930069587), UINT64_C(0x89958490385964),
1556 UINT64_C(0xfff40ff8f08ef3), UINT64_C(0x4ee8ee04cc4de4)),
1557 true, 0x95487930069587, 0x89958490385964);
1558 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpWriteU128v2(&pu128->u,
1559 UINT64_C(0x99969404869434), UINT64_C(0x11049309994567),
1560 UINT64_C(0x33f40ff8f08eff), UINT64_C(0x99e8ee04cc4dee)),
1561 false, 0x95487930069587, 0x89958490385964);
1562}
1563#endif /* RTASM_HAVE_CMP_WRITE_U128 */
1564
1565
1566static void tstASMAtomicCmpXchg(void)
1567{
1568 DO_SIMPLE_TEST(ASMAtomicCmpXchgU8, uint8_t);
1569 DO_SIMPLE_TEST(ASMAtomicCmpXchgU32, uint32_t);
1570 DO_SIMPLE_TEST(ASMAtomicCmpXchgU64, uint64_t);
1571#ifdef RTASM_HAVE_CMP_WRITE_U128
1572# ifdef RT_ARCH_AMD64
1573 if (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_CX16)
1574# endif
1575 {
1576 RTTestISub("ASMAtomicCmpWriteU128U");
1577 DO_SIMPLE_TEST_NO_SUB_NO_STACK(tstASMAtomicCmpWriteU128Worker, RTUINT128U);
1578 }
1579#endif
1580}
1581
1582
1583DECLINLINE(void) tstASMAtomicCmpXchgExU8Worker(uint8_t volatile *pu8)
1584{
1585 *pu8 = UINT8_C(0xff);
1586 uint8_t u8Old = UINT8_C(0x11);
1587 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu8, u8Old, ASMAtomicCmpXchgExU8(pu8, 0, 0, &u8Old), false, UINT8_C(0xff), UINT8_C(0xff));
1588 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu8, u8Old, ASMAtomicCmpXchgExU8(pu8, 0, UINT8_C(0xff), &u8Old), true, 0, UINT8_C(0xff));
1589 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu8, u8Old, ASMAtomicCmpXchgExU8(pu8, 0, UINT8_C(0xff), &u8Old), false, 0, UINT8_C(0x00));
1590 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu8, u8Old, ASMAtomicCmpXchgExU8(pu8, UINT8_C(0xfd), 0, &u8Old), true, UINT8_C(0xfd), 0);
1591 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu8, u8Old, ASMAtomicCmpXchgExU8(pu8, UINT8_C(0xfd), 0, &u8Old), false, UINT8_C(0xfd), UINT8_C(0xfd));
1592 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu8, u8Old, ASMAtomicCmpXchgExU8(pu8, UINT8_C(0xe0), UINT8_C(0xfd), &u8Old), true, UINT8_C(0xe0), UINT8_C(0xfd));
1593
1594 int8_t volatile *pi8 = (int8_t volatile *)pu8;
1595 int8_t i8Old = 0;
1596 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi8, i8Old, ASMAtomicCmpXchgExS8(pi8, 32, 32, &i8Old), false, -32, -32);
1597 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi8, i8Old, ASMAtomicCmpXchgExS8(pi8, 32, -32, &i8Old), true, 32, -32);
1598 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi8, i8Old, ASMAtomicCmpXchgExS8(pi8, INT8_MIN, 32, &i8Old), true, INT8_MIN, 32);
1599 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi8, i8Old, ASMAtomicCmpXchgExS8(pi8, INT8_MIN, 32, &i8Old), false, INT8_MIN, INT8_MIN);
1600 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi8, i8Old, ASMAtomicCmpXchgExS8(pi8, INT8_MAX, INT8_MAX, &i8Old), false, INT8_MIN, INT8_MIN);
1601 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi8, i8Old, ASMAtomicCmpXchgExS8(pi8, INT8_MAX, INT8_MIN, &i8Old), true, INT8_MAX, INT8_MIN);
1602 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi8, i8Old, ASMAtomicCmpXchgExS8(pi8, 42, INT8_MAX, &i8Old), true, 42, INT8_MAX);
1603}
1604
1605
1606DECLINLINE(void) tstASMAtomicCmpXchgExU16Worker(uint16_t volatile *pu16)
1607{
1608 *pu16 = UINT16_C(0xffff);
1609 uint16_t u16Old = UINT16_C(0x5111);
1610 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu16, u16Old, ASMAtomicCmpXchgExU16(pu16, 0, 0, &u16Old), false, UINT16_C(0xffff), UINT16_C(0xffff));
1611 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu16, u16Old, ASMAtomicCmpXchgExU16(pu16, 0, UINT16_C(0xffff), &u16Old), true, 0, UINT16_C(0xffff));
1612 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu16, u16Old, ASMAtomicCmpXchgExU16(pu16, 0, UINT16_C(0xffff), &u16Old), false, 0, UINT16_C(0x0000));
1613 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu16, u16Old, ASMAtomicCmpXchgExU16(pu16, UINT16_C(0x8efd), 0, &u16Old), true, UINT16_C(0x8efd), 0);
1614 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu16, u16Old, ASMAtomicCmpXchgExU16(pu16, UINT16_C(0x8efd), 0, &u16Old), false, UINT16_C(0x8efd), UINT16_C(0x8efd));
1615 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu16, u16Old, ASMAtomicCmpXchgExU16(pu16, UINT16_C(0xffe0), UINT16_C(0x8efd), &u16Old), true, UINT16_C(0xffe0), UINT16_C(0x8efd));
1616
1617 int16_t volatile *pi16 = (int16_t volatile *)pu16;
1618 int16_t i16Old = 0;
1619 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi16, i16Old, ASMAtomicCmpXchgExS16(pi16, 32, 32, &i16Old), false, -32, -32);
1620 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi16, i16Old, ASMAtomicCmpXchgExS16(pi16, 32, -32, &i16Old), true, 32, -32);
1621 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi16, i16Old, ASMAtomicCmpXchgExS16(pi16, INT16_MIN, 32, &i16Old), true, INT16_MIN, 32);
1622 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi16, i16Old, ASMAtomicCmpXchgExS16(pi16, INT16_MIN, 32, &i16Old), false, INT16_MIN, INT16_MIN);
1623 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi16, i16Old, ASMAtomicCmpXchgExS16(pi16, INT16_MAX, INT16_MAX, &i16Old), false, INT16_MIN, INT16_MIN);
1624 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi16, i16Old, ASMAtomicCmpXchgExS16(pi16, INT16_MAX, INT16_MIN, &i16Old), true, INT16_MAX, INT16_MIN);
1625 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi16, i16Old, ASMAtomicCmpXchgExS16(pi16, 42, INT16_MAX, &i16Old), true, 42, INT16_MAX);
1626}
1627
1628
1629DECLINLINE(void) tstASMAtomicCmpXchgExU32Worker(uint32_t volatile *pu32)
1630{
1631 *pu32 = UINT32_C(0xffffffff);
1632 uint32_t u32Old = UINT32_C(0x80005111);
1633 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu32, u32Old, ASMAtomicCmpXchgExU32(pu32, 0, 0, &u32Old), false, UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1634 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu32, u32Old, ASMAtomicCmpXchgExU32(pu32, 0, UINT32_C(0xffffffff), &u32Old), true, 0, UINT32_C(0xffffffff));
1635 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu32, u32Old, ASMAtomicCmpXchgExU32(pu32, 0, UINT32_C(0xffffffff), &u32Old), false, 0, UINT32_C(0x00000000));
1636 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu32, u32Old, ASMAtomicCmpXchgExU32(pu32, UINT32_C(0x80088efd), 0, &u32Old), true, UINT32_C(0x80088efd), 0);
1637 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu32, u32Old, ASMAtomicCmpXchgExU32(pu32, UINT32_C(0x80088efd), 0, &u32Old), false, UINT32_C(0x80088efd), UINT32_C(0x80088efd));
1638 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#x", pu32, u32Old, ASMAtomicCmpXchgExU32(pu32, UINT32_C(0xffffffe0), UINT32_C(0x80088efd), &u32Old), true, UINT32_C(0xffffffe0), UINT32_C(0x80088efd));
1639
1640 int32_t volatile *pi32 = (int32_t volatile *)pu32;
1641 int32_t i32Old = 0;
1642 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi32, i32Old, ASMAtomicCmpXchgExS32(pi32, 32, 32, &i32Old), false, -32, -32);
1643 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi32, i32Old, ASMAtomicCmpXchgExS32(pi32, 32, -32, &i32Old), true, 32, -32);
1644 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi32, i32Old, ASMAtomicCmpXchgExS32(pi32, INT32_MIN, 32, &i32Old), true, INT32_MIN, 32);
1645 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi32, i32Old, ASMAtomicCmpXchgExS32(pi32, INT32_MIN, 32, &i32Old), false, INT32_MIN, INT32_MIN);
1646 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi32, i32Old, ASMAtomicCmpXchgExS32(pi32, INT32_MAX, INT32_MAX, &i32Old), false, INT32_MIN, INT32_MIN);
1647 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi32, i32Old, ASMAtomicCmpXchgExS32(pi32, INT32_MAX, INT32_MIN, &i32Old), true, INT32_MAX, INT32_MIN);
1648 CHECK_OP_AND_VAL_EX2(bool, "%d", "%d", pi32, i32Old, ASMAtomicCmpXchgExS32(pi32, 42, INT32_MAX, &i32Old), true, 42, INT32_MAX);
1649
1650#if ARCH_BITS == 32
1651 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu32;
1652 RTSEMEVENT hEvtOld = (RTSEMEVENT)~(uintptr_t)31;
1653 bool fRc = true;
1654 ASMAtomicCmpXchgExHandle(phEvt, (RTSEMEVENT)~(uintptr_t)0x12380964, (RTSEMEVENT)~(uintptr_t)0, fRc, &hEvtOld);
1655 CHECKVAL(fRc, false, "%d");
1656 CHECKVAL(*phEvt, (RTSEMEVENT)(uintptr_t)42, "%p");
1657 CHECKVAL(hEvtOld, (RTSEMEVENT)(uintptr_t)42, "%p");
1658
1659 ASMAtomicCmpXchgExHandle(phEvt, (RTSEMEVENT)~(uintptr_t)0x12380964, (RTSEMEVENT)(uintptr_t)42, fRc, &hEvtOld);
1660 CHECKVAL(fRc, true, "%d");
1661 CHECKVAL(*phEvt, (RTSEMEVENT)~(uintptr_t)0x12380964, "%p");
1662 CHECKVAL(hEvtOld, (RTSEMEVENT)(uintptr_t)42, "%p");
1663#endif
1664}
1665
1666
1667DECLINLINE(void) tstASMAtomicCmpXchgExU64Worker(uint64_t volatile *pu64)
1668{
1669 *pu64 = UINT64_C(0xffffffffffffffff);
1670 uint64_t u64Old = UINT64_C(0x8000000051111111);
1671 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#llx", pu64, u64Old, ASMAtomicCmpXchgExU64(pu64, 0, 0, &u64Old), false, UINT64_C(0xffffffffffffffff), UINT64_C(0xffffffffffffffff));
1672 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#llx", pu64, u64Old, ASMAtomicCmpXchgExU64(pu64, 0, UINT64_C(0xffffffffffffffff), &u64Old), true, 0, UINT64_C(0xffffffffffffffff));
1673 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#llx", pu64, u64Old, ASMAtomicCmpXchgExU64(pu64, UINT64_C(0x0080040008008efd), 0x342, &u64Old), false, 0, 0);
1674 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#llx", pu64, u64Old, ASMAtomicCmpXchgExU64(pu64, UINT64_C(0x0080040008008efd), 0, &u64Old), true, UINT64_C(0x0080040008008efd), 0);
1675 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#llx", pu64, u64Old, ASMAtomicCmpXchgExU64(pu64, UINT64_C(0xffffffffffffffc0), UINT64_C(0x0080040008008efd), &u64Old), true, UINT64_C(0xffffffffffffffc0), UINT64_C(0x0080040008008efd));
1676
1677 int64_t volatile *pi64 = (int64_t volatile *)pu64;
1678 int64_t i64Old = -3;
1679 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#lld", pi64, i64Old, ASMAtomicCmpXchgExS64(pi64, 64, 64, &i64Old), false, -64, -64);
1680 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#lld", pi64, i64Old, ASMAtomicCmpXchgExS64(pi64, 64, -64, &i64Old), true, 64, -64);
1681 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#lld", pi64, i64Old, ASMAtomicCmpXchgExS64(pi64, 64, -64, &i64Old), false, 64, 64);
1682 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#lld", pi64, i64Old, ASMAtomicCmpXchgExS64(pi64, INT64_MIN, -64, &i64Old), false, 64, 64);
1683 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#lld", pi64, i64Old, ASMAtomicCmpXchgExS64(pi64, INT64_MIN, 64, &i64Old), true, INT64_MIN, 64);
1684 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#lld", pi64, i64Old, ASMAtomicCmpXchgExS64(pi64, INT64_MAX, INT64_MIN, &i64Old), true, INT64_MAX, INT64_MIN);
1685 CHECK_OP_AND_VAL_EX2(bool, "%d", "%#lld", pi64, i64Old, ASMAtomicCmpXchgExS64(pi64, 42, INT64_MAX, &i64Old), true, 42, INT64_MAX);
1686
1687#if ARCH_BITS == 64
1688 RTSEMEVENT volatile *phEvt = (RTSEMEVENT volatile *)pu64;
1689 RTSEMEVENT hEvtOld = (RTSEMEVENT)~(uintptr_t)31;
1690 bool fRc = true;
1691 ASMAtomicCmpXchgExHandle(phEvt, (RTSEMEVENT)~(uintptr_t)0x12380964, (RTSEMEVENT)~(uintptr_t)0, fRc, &hEvtOld);
1692 CHECKVAL(fRc, false, "%d");
1693 CHECKVAL(*phEvt, (RTSEMEVENT)(uintptr_t)42, "%p");
1694 CHECKVAL(hEvtOld, (RTSEMEVENT)(uintptr_t)42, "%p");
1695
1696 ASMAtomicCmpXchgExHandle(phEvt, (RTSEMEVENT)~(uintptr_t)0x12380964, (RTSEMEVENT)(uintptr_t)42, fRc, &hEvtOld);
1697 CHECKVAL(fRc, true, "%d");
1698 CHECKVAL(*phEvt, (RTSEMEVENT)~(uintptr_t)0x12380964, "%p");
1699 CHECKVAL(hEvtOld, (RTSEMEVENT)(uintptr_t)42, "%p");
1700
1701 void * volatile *ppv = (void * volatile *)pu64;
1702 void *pvOld;
1703 CHECK_OP_AND_VAL_EX2(bool, "%d", "%p", ppv, pvOld, ASMAtomicCmpXchgExPtrVoid(ppv, (void *)(intptr_t)12345678, NULL, &pvOld), false, (void *)~(uintptr_t)0x12380964, (void *)~(uintptr_t)0x12380964);
1704 CHECK_OP_AND_VAL_EX2(bool, "%d", "%p", ppv, pvOld, ASMAtomicCmpXchgExPtrVoid(ppv, (void *)(intptr_t)12345678, (void *)~(uintptr_t)0x12380964, &pvOld), true, (void *)(intptr_t)12345678, (void *)~(uintptr_t)0x12380964);
1705
1706 CHECK_OP_AND_VAL_EX2(bool, "%d", "%p", ppv, pvOld, ASMAtomicCmpXchgExPtr(ppv, (void *)~(uintptr_t)99, (void *)~(uintptr_t)99, &pvOld), false, (void *)(intptr_t)12345678, (void *)(intptr_t)12345678);
1707 CHECK_OP_AND_VAL_EX2(bool, "%d", "%p", ppv, pvOld, ASMAtomicCmpXchgExPtr(ppv, (void *)~(uintptr_t)99, (void *)(intptr_t)12345678, &pvOld), true, (void *)~(intptr_t)99, (void *)(intptr_t)12345678);
1708#endif
1709}
1710
1711
1712#ifdef RTASM_HAVE_CMP_XCHG_U128
1713DECLINLINE(void) tstASMAtomicCmpXchgU128Worker(RTUINT128U volatile *pu128)
1714{
1715 pu128->s.Lo = UINT64_C(0xffffffffffffff);
1716 pu128->s.Hi = UINT64_C(0xffffffffffffff);
1717
1718 RTUINT128U u128A, u128B;
1719 RTUINT128U const u128OldInit = RTUINT128_INIT_C(0x4242424242424242, 0x2222222222222222);
1720 RTUINT128U u128Old = u128OldInit;
1721 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpXchgU128U(pu128,
1722 u128A = RTUINT128_INIT_C(0, 0),
1723 u128B = RTUINT128_INIT_C(0, 0),
1724 &u128Old),
1725 false, 0xffffffffffffff, 0xffffffffffffff);
1726 CHECKVAL128_C(&u128Old, 0xffffffffffffff, 0xffffffffffffff);
1727
1728 u128Old = u128OldInit;
1729 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpXchgU128U(pu128,
1730 u128A = RTUINT128_INIT_C(0, 0),
1731 u128B = RTUINT128_INIT_C(0xffffffffffffff, 0xffffffffffffff),
1732 &u128Old),
1733 true, 0, 0);
1734 CHECKVAL128_C(&u128Old, 0xffffffffffffff, 0xffffffffffffff);
1735
1736 u128Old = u128OldInit;
1737 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpXchgU128U(pu128,
1738 u128A = RTUINT128_INIT_C(0x80040008008efd, 0x40080004004def),
1739 u128B = RTUINT128_INIT_C(0, 1),
1740 &u128Old),
1741 false, 0, 0);
1742 CHECKVAL128_C(&u128Old, 0, 0);
1743
1744 u128Old = u128OldInit;
1745 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpXchgU128U(pu128,
1746 u128A = RTUINT128_INIT_C(0x80040008008efd, 0x40080004004def),
1747 u128B = RTUINT128_INIT_C(1, 0),
1748 &u128Old),
1749 false, 0, 0);
1750 CHECKVAL128_C(&u128Old, 0, 0);
1751
1752 u128Old = u128OldInit;
1753 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpXchgU128U(pu128,
1754 u128A = RTUINT128_INIT_C(0x80040008008efd, 0x40080004004def),
1755 u128B = RTUINT128_INIT_C(0, 0),
1756 &u128Old),
1757 true, 0x80040008008efd, 0x40080004004def);
1758 CHECKVAL128_C(&u128Old, 0, 0);
1759
1760 u128Old = u128OldInit;
1761 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpXchgU128U(pu128,
1762 u128A = RTUINT128_INIT_C(0xfff40ff8f08ef3, 0x4ee8ee04cc4de4),
1763 u128B = RTUINT128_INIT_C(0x80040008008efd, 0),
1764 &u128Old),
1765 false, 0x80040008008efd, 0x40080004004def);
1766 CHECKVAL128_C(&u128Old, 0x80040008008efd, 0x40080004004def);
1767
1768 u128Old = u128OldInit;
1769 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpXchgU128U(pu128,
1770 u128A = RTUINT128_INIT_C(0xfff40ff8f08ef3, 0x4ee8ee04cc4de4),
1771 u128B = RTUINT128_INIT_C(0, 0x40080004004def),
1772 &u128Old),
1773 false, 0x80040008008efd, 0x40080004004def);
1774 CHECKVAL128_C(&u128Old, 0x80040008008efd, 0x40080004004def);
1775
1776 u128Old = u128OldInit;
1777 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpXchgU128U(pu128,
1778 u128A = RTUINT128_INIT_C(0xfff40ff8f08ef3, 0x4ee8ee04cc4de4),
1779 u128B = RTUINT128_INIT_C(0x80040008008efd, 0x40080004004def),
1780 &u128Old),
1781 true, 0xfff40ff8f08ef3, 0x4ee8ee04cc4de4);
1782 CHECKVAL128_C(&u128Old, 0x80040008008efd, 0x40080004004def);
1783
1784 /* Make sure the v2 version works too (arm) */
1785 u128Old = u128OldInit;
1786 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpXchgU128v2(&pu128->u,
1787 UINT64_C(0x78039485960543), UINT64_C(0x97058437294586),
1788 UINT64_C(0xfff40ff8f08ef3), UINT64_C(0x4ee8ee04cc4de4),
1789 &u128Old.u),
1790 true, 0x78039485960543, 0x97058437294586);
1791 CHECKVAL128_C(&u128Old, 0xfff40ff8f08ef3, 0x4ee8ee04cc4de4);
1792
1793 u128Old = u128OldInit;
1794 CHECK_OP_AND_VAL_128_C(bool, "%d", pu128, ASMAtomicCmpXchgU128v2(&pu128->u,
1795 UINT64_C(0x13495874560495), UINT64_C(0x12304896098597),
1796 UINT64_C(0xfff40ff8f08ef3), UINT64_C(0x4ee8ee04cc4de4),
1797 &u128Old.u),
1798 false, 0x78039485960543, 0x97058437294586);
1799 CHECKVAL128_C(&u128Old, 0x78039485960543, 0x97058437294586);
1800}
1801#endif /* RTASM_HAVE_CMP_XCHG_U128 */
1802
1803
1804static void tstASMAtomicCmpXchgEx(void)
1805{
1806 DO_SIMPLE_TEST(ASMAtomicCmpXchgExU8, uint8_t);
1807 DO_SIMPLE_TEST(ASMAtomicCmpXchgExU16, uint16_t);
1808 DO_SIMPLE_TEST(ASMAtomicCmpXchgExU32, uint32_t);
1809 DO_SIMPLE_TEST(ASMAtomicCmpXchgExU64, uint64_t);
1810#ifdef RTASM_HAVE_CMP_XCHG_U128
1811# ifdef RT_ARCH_AMD64
1812 if (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_CX16)
1813# endif
1814 {
1815 RTTestISub("ASMAtomicCmpXchgU128");
1816 DO_SIMPLE_TEST_NO_SUB_NO_STACK(tstASMAtomicCmpXchgU128Worker, RTUINT128U);
1817 }
1818#endif
1819}
1820
1821
1822#define TEST_RET_OLD(a_Type, a_Fmt, a_pVar, a_Function, a_uVal, a_VarExpect) do { \
1823 a_Type const uOldExpect = *(a_pVar); \
1824 a_Type uOldRet = a_Function(a_pVar, a_uVal); \
1825 if (RT_LIKELY( uOldRet == (uOldExpect) && *(a_pVar) == (a_VarExpect) )) { } \
1826 else RTTestFailed(g_hTest, "%s, %d: FAILURE: %s(%s," a_Fmt ") -> " a_Fmt ", expected " a_Fmt "; %s=" a_Fmt ", expected " a_Fmt "\n", \
1827 __FUNCTION__, __LINE__, #a_Function, #a_pVar, a_uVal, uOldRet, uOldExpect, #a_pVar, *(a_pVar), (a_VarExpect)); \
1828 } while (0)
1829
1830
1831DECLINLINE(void) tstASMAtomicAddU32Worker(uint32_t *pu32)
1832{
1833 *pu32 = 10;
1834 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAddU32, 1, 11);
1835 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAddU32, UINT32_C(0xfffffffe), 9);
1836 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAddU32, UINT32_C(0xfffffff7), 0);
1837 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAddU32, UINT32_C(0x7fffffff), UINT32_C(0x7fffffff));
1838 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAddU32, 1, UINT32_C(0x80000000));
1839 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAddU32, 1, UINT32_C(0x80000001));
1840 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAddU32, UINT32_C(0x7fffffff), 0);
1841 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAddU32, 0, 0);
1842
1843 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicSubU32, 0, 0);
1844 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicSubU32, 32, UINT32_C(0xffffffe0));
1845 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicSubU32, UINT32_C(0x7fffffff), UINT32_C(0x7fffffe1));
1846 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicSubU32, UINT32_C(0x7fffffde), UINT32_C(0x00000003));
1847}
1848
1849
1850DECLINLINE(void) tstASMAtomicAddS32Worker(int32_t *pi32)
1851{
1852 *pi32 = 10;
1853 TEST_RET_OLD(int32_t, "%d", pi32, ASMAtomicAddS32, 1, 11);
1854 TEST_RET_OLD(int32_t, "%d", pi32, ASMAtomicAddS32, -2, 9);
1855 TEST_RET_OLD(int32_t, "%d", pi32, ASMAtomicAddS32, -9, 0);
1856 TEST_RET_OLD(int32_t, "%d", pi32, ASMAtomicAddS32, -0x7fffffff, -0x7fffffff);
1857 TEST_RET_OLD(int32_t, "%d", pi32, ASMAtomicAddS32, 0, -0x7fffffff);
1858 TEST_RET_OLD(int32_t, "%d", pi32, ASMAtomicAddS32, 0x7fffffff, 0);
1859 TEST_RET_OLD(int32_t, "%d", pi32, ASMAtomicAddS32, 0, 0);
1860
1861 TEST_RET_OLD(int32_t, "%d", pi32, ASMAtomicSubS32, 0, 0);
1862 TEST_RET_OLD(int32_t, "%d", pi32, ASMAtomicSubS32, 1, -1);
1863 TEST_RET_OLD(int32_t, "%d", pi32, ASMAtomicSubS32, INT32_MIN, INT32_MAX);
1864}
1865
1866
1867DECLINLINE(void) tstASMAtomicAddU64Worker(uint64_t volatile *pu64)
1868{
1869 *pu64 = 10;
1870 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicAddU64, 1, 11);
1871 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicAddU64, UINT64_C(0xfffffffffffffffe), UINT64_C(0x0000000000000009));
1872 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicAddU64, UINT64_C(0xfffffffffffffff7), UINT64_C(0x0000000000000000));
1873 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicAddU64, UINT64_C(0x7ffffffffffffff0), UINT64_C(0x7ffffffffffffff0));
1874 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicAddU64, UINT64_C(0x7ffffffffffffff0), UINT64_C(0xffffffffffffffe0));
1875 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicAddU64, UINT64_C(0x0000000000000000), UINT64_C(0xffffffffffffffe0));
1876 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicAddU64, UINT64_C(0x000000000000001f), UINT64_C(0xffffffffffffffff));
1877 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicAddU64, UINT64_C(0x0000000000000001), UINT64_C(0x0000000000000000));
1878
1879 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicSubU64, UINT64_C(0x0000000000000000), UINT64_C(0x0000000000000000));
1880 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicSubU64, UINT64_C(0x0000000000000020), UINT64_C(0xffffffffffffffe0));
1881 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicSubU64, UINT64_C(0x7fffffffffffffff), UINT64_C(0x7fffffffffffffe1));
1882 TEST_RET_OLD(uint64_t, "%llx", pu64, ASMAtomicSubU64, UINT64_C(0x7fffffffffffffdd), UINT64_C(0x0000000000000004));
1883}
1884
1885
1886DECLINLINE(void) tstASMAtomicAddS64Worker(int64_t volatile *pi64)
1887{
1888 *pi64 = 10;
1889 TEST_RET_OLD(int64_t, "%lld", pi64, ASMAtomicAddS64, 1, 11);
1890 TEST_RET_OLD(int64_t, "%lld", pi64, ASMAtomicAddS64, -2, 9);
1891 TEST_RET_OLD(int64_t, "%lld", pi64, ASMAtomicAddS64, -9, 0);
1892 TEST_RET_OLD(int64_t, "%lld", pi64, ASMAtomicAddS64, -INT64_MAX, -INT64_MAX);
1893 TEST_RET_OLD(int64_t, "%lld", pi64, ASMAtomicAddS64, 0, -INT64_MAX);
1894 TEST_RET_OLD(int64_t, "%lld", pi64, ASMAtomicAddS64, -1, INT64_MIN);
1895 TEST_RET_OLD(int64_t, "%lld", pi64, ASMAtomicAddS64, INT64_MAX, -1);
1896 TEST_RET_OLD(int64_t, "%lld", pi64, ASMAtomicAddS64, 1, 0);
1897 TEST_RET_OLD(int64_t, "%lld", pi64, ASMAtomicAddS64, 0, 0);
1898
1899 TEST_RET_OLD(int64_t, "%d", pi64, ASMAtomicSubS64, 0, 0);
1900 TEST_RET_OLD(int64_t, "%d", pi64, ASMAtomicSubS64, 1, -1);
1901 TEST_RET_OLD(int64_t, "%d", pi64, ASMAtomicSubS64, INT64_MIN, INT64_MAX);
1902}
1903
1904
1905
1906DECLINLINE(void) tstASMAtomicAddZWorker(size_t volatile *pcb)
1907{
1908 *pcb = 10;
1909 TEST_RET_OLD(size_t, "%zx", pcb, ASMAtomicAddZ, 1, 11);
1910 TEST_RET_OLD(size_t, "%zx", pcb, ASMAtomicAddZ, ~(size_t)1, 9);
1911 TEST_RET_OLD(size_t, "%zx", pcb, ASMAtomicAddZ, ~(size_t)8, 0);
1912
1913 TEST_RET_OLD(size_t, "%zx", pcb, ASMAtomicSubZ, 0, 0);
1914 TEST_RET_OLD(size_t, "%zx", pcb, ASMAtomicSubZ, 10, ~(size_t)9);
1915}
1916
1917static void tstASMAtomicAdd(void)
1918{
1919 DO_SIMPLE_TEST(ASMAtomicAddU32, uint32_t);
1920 DO_SIMPLE_TEST(ASMAtomicAddS32, int32_t);
1921 DO_SIMPLE_TEST(ASMAtomicAddU64, uint64_t);
1922 DO_SIMPLE_TEST(ASMAtomicAddS64, int64_t);
1923 DO_SIMPLE_TEST(ASMAtomicAddZ, size_t);
1924}
1925
1926
1927#define TEST_RET_NEW_NV(a_Type, a_Fmt, a_pVar, a_Function, a_VarExpect) do { \
1928 a_Type uNewRet = a_Function(a_pVar); \
1929 if (RT_LIKELY( uNewRet == (a_VarExpect) && *(a_pVar) == (a_VarExpect) )) { } \
1930 else RTTestFailed(g_hTest, "%s, %d: FAILURE: %s(%s) -> " a_Fmt " and %s=" a_Fmt ", expected both " a_Fmt "\n", \
1931 __FUNCTION__, __LINE__, #a_Function, #a_pVar, uNewRet, #a_pVar, *(a_pVar), (a_VarExpect)); \
1932 } while (0)
1933
1934
1935DECLINLINE(void) tstASMAtomicDecIncU32Worker(uint32_t volatile *pu32)
1936{
1937 *pu32 = 3;
1938 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicDecU32, 2);
1939 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicDecU32, 1);
1940 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicDecU32, 0);
1941 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicDecU32, UINT32_MAX);
1942 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicDecU32, UINT32_MAX - 1);
1943 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicDecU32, UINT32_MAX - 2);
1944 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicIncU32, UINT32_MAX - 1);
1945 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicIncU32, UINT32_MAX);
1946 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicIncU32, 0);
1947 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicIncU32, 1);
1948 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicIncU32, 2);
1949 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicDecU32, 1);
1950 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicIncU32, 2);
1951 *pu32 = _1M;
1952 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicDecU32, _1M - 1);
1953 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicIncU32, _1M);
1954 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicIncU32, _1M + 1);
1955}
1956
1957DECLINLINE(void) tstASMAtomicUoDecIncU32Worker(uint32_t volatile *pu32)
1958{
1959 *pu32 = 3;
1960 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoDecU32, 2);
1961 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoDecU32, 1);
1962 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoDecU32, 0);
1963 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoDecU32, UINT32_MAX);
1964 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoDecU32, UINT32_MAX - 1);
1965 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoDecU32, UINT32_MAX - 2);
1966 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoIncU32, UINT32_MAX - 1);
1967 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoIncU32, UINT32_MAX);
1968 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoIncU32, 0);
1969 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoIncU32, 1);
1970 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoIncU32, 2);
1971 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoDecU32, 1);
1972 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoIncU32, 2);
1973 *pu32 = _1M;
1974 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoDecU32, _1M - 1);
1975 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoIncU32, _1M);
1976 TEST_RET_NEW_NV(uint32_t, "%#x", pu32, ASMAtomicUoIncU32, _1M + 1);
1977}
1978
1979
1980DECLINLINE(void) tstASMAtomicDecIncS32Worker(int32_t volatile *pi32)
1981{
1982 *pi32 = 10;
1983 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 9);
1984 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 8);
1985 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 7);
1986 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 6);
1987 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 5);
1988 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 4);
1989 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 3);
1990 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 2);
1991 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 1);
1992 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 0);
1993 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, -1);
1994 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, -2);
1995 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicIncS32, -1);
1996 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicIncS32, 0);
1997 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicIncS32, 1);
1998 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicIncS32, 2);
1999 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicIncS32, 3);
2000 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 2);
2001 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicIncS32, 3);
2002 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, 2);
2003 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicIncS32, 3);
2004 *pi32 = INT32_MAX;
2005 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicDecS32, INT32_MAX - 1);
2006 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicIncS32, INT32_MAX);
2007 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicIncS32, INT32_MIN);
2008}
2009
2010
2011#if 0
2012DECLINLINE(void) tstASMAtomicUoDecIncS32Worker(int32_t volatile *pi32)
2013{
2014 *pi32 = 10;
2015 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 9);
2016 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 8);
2017 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 7);
2018 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 6);
2019 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 5);
2020 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 4);
2021 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 3);
2022 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 2);
2023 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 1);
2024 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 0);
2025 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, -1);
2026 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, -2);
2027 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoIncS32, -1);
2028 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoIncS32, 0);
2029 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoIncS32, 1);
2030 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoIncS32, 2);
2031 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoIncS32, 3);
2032 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 2);
2033 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoIncS32, 3);
2034 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, 2);
2035 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoIncS32, 3);
2036 *pi32 = INT32_MAX;
2037 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoDecS32, INT32_MAX - 1);
2038 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoIncS32, INT32_MAX);
2039 TEST_RET_NEW_NV(int32_t, "%d", pi32, ASMAtomicUoIncS32, INT32_MIN);
2040}
2041#endif
2042
2043
2044DECLINLINE(void) tstASMAtomicDecIncU64Worker(uint64_t volatile *pu64)
2045{
2046 *pu64 = 3;
2047 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicDecU64, 2);
2048 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicDecU64, 1);
2049 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicDecU64, 0);
2050 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicDecU64, UINT64_MAX);
2051 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicDecU64, UINT64_MAX - 1);
2052 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicDecU64, UINT64_MAX - 2);
2053 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicIncU64, UINT64_MAX - 1);
2054 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicIncU64, UINT64_MAX);
2055 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicIncU64, 0);
2056 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicIncU64, 1);
2057 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicIncU64, 2);
2058 *pu64 = _4G - 1;
2059 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicDecU64, _4G - 2);
2060 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicIncU64, _4G - 1);
2061 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicIncU64, _4G);
2062 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicIncU64, _4G + 1);
2063 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicDecU64, _4G);
2064}
2065
2066
2067#if 0
2068DECLINLINE(void) tstASMAtomicUoDecIncU64Worker(uint64_t volatile *pu64)
2069{
2070 *pu64 = 3;
2071 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoDecU64, 2);
2072 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoDecU64, 1);
2073 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoDecU64, 0);
2074 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoDecU64, UINT64_MAX);
2075 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoDecU64, UINT64_MAX - 1);
2076 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoDecU64, UINT64_MAX - 2);
2077 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoIncU64, UINT64_MAX - 1);
2078 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoIncU64, UINT64_MAX);
2079 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoIncU64, 0);
2080 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoIncU64, 1);
2081 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoIncU64, 2);
2082 *pu64 = _4G - 1;
2083 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoDecU64, _4G - 2);
2084 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoIncU64, _4G - 1);
2085 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoIncU64, _4G);
2086 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoIncU64, _4G + 1);
2087 TEST_RET_NEW_NV(uint64_t, "%lld", pu64, ASMAtomicUoDecU64, _4G);
2088}
2089#endif
2090
2091
2092DECLINLINE(void) tstASMAtomicDecIncS64Worker(int64_t volatile *pi64)
2093{
2094 *pi64 = 10;
2095 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 9);
2096 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 8);
2097 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 7);
2098 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 6);
2099 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 5);
2100 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 4);
2101 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 3);
2102 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 2);
2103 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 1);
2104 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 0);
2105 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, -1);
2106 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, -2);
2107 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicIncS64, -1);
2108 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicIncS64, 0);
2109 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicIncS64, 1);
2110 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicIncS64, 2);
2111 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicIncS64, 3);
2112 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 2);
2113 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicIncS64, 3);
2114 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, 2);
2115 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicIncS64, 3);
2116 *pi64 = INT64_MAX;
2117 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicDecS64, INT64_MAX - 1);
2118}
2119
2120
2121#if 0
2122DECLINLINE(void) tstASMAtomicUoDecIncS64Worker(int64_t volatile *pi64)
2123{
2124 *pi64 = 10;
2125 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 9);
2126 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 8);
2127 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 7);
2128 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 6);
2129 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 5);
2130 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 4);
2131 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 3);
2132 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 2);
2133 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 1);
2134 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 0);
2135 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, -1);
2136 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, -2);
2137 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoIncS64, -1);
2138 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoIncS64, 0);
2139 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoIncS64, 1);
2140 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoIncS64, 2);
2141 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoIncS64, 3);
2142 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 2);
2143 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoIncS64, 3);
2144 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, 2);
2145 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoIncS64, 3);
2146 *pi64 = INT64_MAX;
2147 TEST_RET_NEW_NV(int64_t, "%lld", pi64, ASMAtomicUoDecS64, INT64_MAX - 1);
2148}
2149#endif
2150
2151
2152DECLINLINE(void) tstASMAtomicDecIncZWorker(size_t volatile *pcb)
2153{
2154 size_t const uBaseVal = ~(size_t)0 >> 7;
2155 *pcb = uBaseVal;
2156 TEST_RET_NEW_NV(size_t, "%zx", pcb, ASMAtomicDecZ, uBaseVal - 1);
2157 TEST_RET_NEW_NV(size_t, "%zx", pcb, ASMAtomicDecZ, uBaseVal - 2);
2158 TEST_RET_NEW_NV(size_t, "%zx", pcb, ASMAtomicDecZ, uBaseVal - 3);
2159 TEST_RET_NEW_NV(size_t, "%zx", pcb, ASMAtomicIncZ, uBaseVal - 2);
2160 TEST_RET_NEW_NV(size_t, "%zx", pcb, ASMAtomicIncZ, uBaseVal - 1);
2161 TEST_RET_NEW_NV(size_t, "%zx", pcb, ASMAtomicIncZ, uBaseVal);
2162 TEST_RET_NEW_NV(size_t, "%zx", pcb, ASMAtomicIncZ, uBaseVal + 1);
2163 TEST_RET_NEW_NV(size_t, "%zx", pcb, ASMAtomicDecZ, uBaseVal);
2164 TEST_RET_NEW_NV(size_t, "%zx", pcb, ASMAtomicDecZ, uBaseVal - 1);
2165 TEST_RET_NEW_NV(size_t, "%zx", pcb, ASMAtomicIncZ, uBaseVal);
2166}
2167
2168
2169static void tstASMAtomicDecInc(void)
2170{
2171 DO_SIMPLE_TEST(ASMAtomicDecIncU32, uint32_t);
2172 DO_SIMPLE_TEST(ASMAtomicUoDecIncU32, uint32_t);
2173 DO_SIMPLE_TEST(ASMAtomicDecIncS32, int32_t);
2174 //DO_SIMPLE_TEST(ASMAtomicUoDecIncS32, int32_t);
2175 DO_SIMPLE_TEST(ASMAtomicDecIncU64, uint64_t);
2176 //DO_SIMPLE_TEST(ASMAtomicUoDecIncU64, uint64_t);
2177 DO_SIMPLE_TEST(ASMAtomicDecIncS64, int64_t);
2178 //DO_SIMPLE_TEST(ASMAtomicUoDecIncS64, int64_t);
2179 DO_SIMPLE_TEST(ASMAtomicDecIncZ, size_t);
2180}
2181
2182
2183#define TEST_RET_VOID(a_Type, a_Fmt, a_pVar, a_Function, a_uVal, a_VarExpect) do { \
2184 a_Function(a_pVar, a_uVal); \
2185 if (RT_LIKELY( *(a_pVar) == (a_VarExpect) )) { } \
2186 else RTTestFailed(g_hTest, "%s, %d: FAILURE: %s(%s, " a_Fmt ") -> %s=" a_Fmt ", expected " a_Fmt "\n", \
2187 __FUNCTION__, __LINE__, #a_Function, #a_pVar, a_uVal, #a_pVar, *(a_pVar), (a_VarExpect)); \
2188 } while (0)
2189
2190#define TEST_RET_NEW(a_Type, a_Fmt, a_pVar, a_Function, a_uVal, a_VarExpect) do { \
2191 a_Type uNewRet = a_Function(a_pVar, a_uVal); \
2192 if (RT_LIKELY( uNewRet == (a_VarExpect) && *(a_pVar) == (a_VarExpect) )) { } \
2193 else RTTestFailed(g_hTest, "%s, %d: FAILURE: %s(%s, " a_Fmt ") -> " a_Fmt " and %s=" a_Fmt ", expected both " a_Fmt "\n", \
2194 __FUNCTION__, __LINE__, #a_Function, #a_pVar, a_uVal, uNewRet, #a_pVar, *(a_pVar), (a_VarExpect)); \
2195 } while (0)
2196
2197
2198DECLINLINE(void) tstASMAtomicAndOrXorU32Worker(uint32_t volatile *pu32)
2199{
2200 *pu32 = UINT32_C(0xffffffff);
2201 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicOrU32, UINT32_C(0xffffffff), UINT32_C(0xffffffff));
2202 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicAndU32, UINT32_C(0xffffffff), UINT32_C(0xffffffff));
2203 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicAndU32, UINT32_C(0x8f8f8f8f), UINT32_C(0x8f8f8f8f));
2204 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicOrU32, UINT32_C(0x70707070), UINT32_C(0xffffffff));
2205 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicAndU32, UINT32_C(1), UINT32_C(1));
2206 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicOrU32, UINT32_C(0x80000000), UINT32_C(0x80000001));
2207 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicAndU32, UINT32_C(0x80000000), UINT32_C(0x80000000));
2208 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicAndU32, UINT32_C(0), UINT32_C(0));
2209 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicOrU32, UINT32_C(0x42424242), UINT32_C(0x42424242));
2210 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicAndU32, UINT32_C(0x00ff0f00), UINT32_C(0x00420200));
2211 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicXorU32, UINT32_C(0x42004042), UINT32_C(0x42424242));
2212 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicXorU32, UINT32_C(0xff024200), UINT32_C(0xbd400042));
2213 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicXorU32, UINT32_C(0x00000000), UINT32_C(0xbd400042));
2214}
2215
2216
2217DECLINLINE(void) tstASMAtomicUoAndOrXorU32Worker(uint32_t volatile *pu32)
2218{
2219 *pu32 = UINT32_C(0xffffffff);
2220 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoOrU32, UINT32_C(0xffffffff), UINT32_C(0xffffffff));
2221 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoAndU32, UINT32_C(0xffffffff), UINT32_C(0xffffffff));
2222 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoAndU32, UINT32_C(0x8f8f8f8f), UINT32_C(0x8f8f8f8f));
2223 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoOrU32, UINT32_C(0x70707070), UINT32_C(0xffffffff));
2224 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoAndU32, UINT32_C(1), UINT32_C(1));
2225 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoOrU32, UINT32_C(0x80000000), UINT32_C(0x80000001));
2226 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoAndU32, UINT32_C(0x80000000), UINT32_C(0x80000000));
2227 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoAndU32, UINT32_C(0), UINT32_C(0));
2228 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoOrU32, UINT32_C(0x42424242), UINT32_C(0x42424242));
2229 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoAndU32, UINT32_C(0x00ff0f00), UINT32_C(0x00420200));
2230 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoXorU32, UINT32_C(0x42004042), UINT32_C(0x42424242));
2231 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoXorU32, UINT32_C(0xff024200), UINT32_C(0xbd400042));
2232 TEST_RET_VOID(uint32_t, "%#x", pu32, ASMAtomicUoXorU32, UINT32_C(0x00000000), UINT32_C(0xbd400042));
2233}
2234
2235
2236DECLINLINE(void) tstASMAtomicAndOrXorExU32Worker(uint32_t volatile *pu32)
2237{
2238 *pu32 = UINT32_C(0xffffffff);
2239 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicOrExU32, UINT32_C(0xffffffff), UINT32_C(0xffffffff));
2240 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAndExU32, UINT32_C(0xffffffff), UINT32_C(0xffffffff));
2241 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAndExU32, UINT32_C(0x8f8f8f8f), UINT32_C(0x8f8f8f8f));
2242 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicOrExU32, UINT32_C(0x70707070), UINT32_C(0xffffffff));
2243 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAndExU32, UINT32_C(1), UINT32_C(1));
2244 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicOrExU32, UINT32_C(0x80000000), UINT32_C(0x80000001));
2245 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAndExU32, UINT32_C(0x80000000), UINT32_C(0x80000000));
2246 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAndExU32, UINT32_C(0), UINT32_C(0));
2247 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicOrExU32, UINT32_C(0x42424242), UINT32_C(0x42424242));
2248 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicAndExU32, UINT32_C(0x00ff0f00), UINT32_C(0x00420200));
2249 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicXorExU32, UINT32_C(0x42004042), UINT32_C(0x42424242));
2250 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicXorExU32, UINT32_C(0xff024200), UINT32_C(0xbd400042));
2251 TEST_RET_OLD(uint32_t, "%#x", pu32, ASMAtomicXorExU32, UINT32_C(0x00000000), UINT32_C(0xbd400042));
2252}
2253
2254
2255DECLINLINE(void) tstASMAtomicAndOrXorU64Worker(uint64_t volatile *pu64)
2256{
2257 *pu64 = UINT64_C(0xffffffff);
2258 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicOrU64, UINT64_C(0xffffffff), UINT64_C(0xffffffff));
2259 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0xffffffff), UINT64_C(0xffffffff));
2260 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0x8f8f8f8f), UINT64_C(0x8f8f8f8f));
2261 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicOrU64, UINT64_C(0x70707070), UINT64_C(0xffffffff));
2262 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(1), UINT64_C(1));
2263 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicOrU64, UINT64_C(0x80000000), UINT64_C(0x80000001));
2264 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0x80000000), UINT64_C(0x80000000));
2265 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0), UINT64_C(0));
2266 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicOrU64, UINT64_C(0x42424242), UINT64_C(0x42424242));
2267 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0x00ff0f00), UINT64_C(0x00420200));
2268 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicXorU64, UINT64_C(0x42004042), UINT64_C(0x42424242));
2269 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicXorU64, UINT64_C(0xff024200), UINT64_C(0xbd400042));
2270 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicXorU64, UINT64_C(0x00000000), UINT64_C(0xbd400042));
2271
2272 /* full 64-bit */
2273 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0x0000000000000000), UINT64_C(0x0000000000000000));
2274 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicOrU64, UINT64_C(0xffffffffffffffff), UINT64_C(0xffffffffffffffff));
2275 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0xffffffffffffffff), UINT64_C(0xffffffffffffffff));
2276 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0x8f8f8f8f8f8f8f8f), UINT64_C(0x8f8f8f8f8f8f8f8f));
2277 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicOrU64, UINT64_C(0x7070707070707070), UINT64_C(0xffffffffffffffff));
2278 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0x0000000000000001), UINT64_C(0x0000000000000001));
2279 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicOrU64, UINT64_C(0x8000000000000000), UINT64_C(0x8000000000000001));
2280 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0x8000000000000000), UINT64_C(0x8000000000000000));
2281 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0), UINT64_C(0));
2282 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicOrU64, UINT64_C(0x4242424242424242), UINT64_C(0x4242424242424242));
2283 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicAndU64, UINT64_C(0x00ff0f00ff0f0000), UINT64_C(0x0042020042020000));
2284 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicXorU64, UINT64_C(0x4200404242040000), UINT64_C(0x4242424242420000));
2285 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicXorU64, UINT64_C(0xff02420000ff2127), UINT64_C(0xbd40004242bd2127));
2286 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicXorU64, UINT64_C(0x0000000000000000), UINT64_C(0xbd40004242bd2127));
2287}
2288
2289
2290DECLINLINE(void) tstASMAtomicUoAndOrXorU64Worker(uint64_t volatile *pu64)
2291{
2292 *pu64 = UINT64_C(0xffffffff);
2293 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoOrU64, UINT64_C(0xffffffff), UINT64_C(0xffffffff));
2294 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0xffffffff), UINT64_C(0xffffffff));
2295 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0x8f8f8f8f), UINT64_C(0x8f8f8f8f));
2296 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoOrU64, UINT64_C(0x70707070), UINT64_C(0xffffffff));
2297 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(1), UINT64_C(1));
2298 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoOrU64, UINT64_C(0x80000000), UINT64_C(0x80000001));
2299 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0x80000000), UINT64_C(0x80000000));
2300 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0), UINT64_C(0));
2301 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoOrU64, UINT64_C(0x42424242), UINT64_C(0x42424242));
2302 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0x00ff0f00), UINT64_C(0x00420200));
2303 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoXorU64, UINT64_C(0x42004042), UINT64_C(0x42424242));
2304 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoXorU64, UINT64_C(0xff024200), UINT64_C(0xbd400042));
2305 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoXorU64, UINT64_C(0x00000000), UINT64_C(0xbd400042));
2306
2307 /* full 64-bit */
2308 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0x0000000000000000), UINT64_C(0x0000000000000000));
2309 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoOrU64, UINT64_C(0xffffffffffffffff), UINT64_C(0xffffffffffffffff));
2310 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0xffffffffffffffff), UINT64_C(0xffffffffffffffff));
2311 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0x8f8f8f8f8f8f8f8f), UINT64_C(0x8f8f8f8f8f8f8f8f));
2312 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoOrU64, UINT64_C(0x7070707070707070), UINT64_C(0xffffffffffffffff));
2313 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0x0000000000000001), UINT64_C(0x0000000000000001));
2314 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoOrU64, UINT64_C(0x8000000000000000), UINT64_C(0x8000000000000001));
2315 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0x8000000000000000), UINT64_C(0x8000000000000000));
2316 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0), UINT64_C(0));
2317 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoOrU64, UINT64_C(0x4242424242424242), UINT64_C(0x4242424242424242));
2318 TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoAndU64, UINT64_C(0x00ff0f00ff0f0000), UINT64_C(0x0042020042020000));
2319 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoXorU64, UINT64_C(0x4200404242040000), UINT64_C(0x4242424242420000));
2320 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoXorU64, UINT64_C(0xff02420000ff2127), UINT64_C(0xbd40004242bd2127));
2321 //TEST_RET_VOID(uint64_t, "%#llx", pu64, ASMAtomicUoXorU64, UINT64_C(0x0000000000000000), UINT64_C(0xbd40004242bd2127));
2322}
2323
2324
2325#if 0
2326DECLINLINE(void) tstASMAtomicAndOrXorExU64Worker(uint64_t volatile *pu64)
2327{
2328 *pu64 = UINT64_C(0xffffffff);
2329 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicOrExU64, UINT64_C(0xffffffff), UINT64_C(0xffffffff));
2330 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0xffffffff), UINT64_C(0xffffffff));
2331 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0x8f8f8f8f), UINT64_C(0x8f8f8f8f));
2332 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicOrExU64, UINT64_C(0x70707070), UINT64_C(0xffffffff));
2333 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(1), UINT64_C(1));
2334 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicOrExU64, UINT64_C(0x80000000), UINT64_C(0x80000001));
2335 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0x80000000), UINT64_C(0x80000000));
2336 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0), UINT64_C(0));
2337 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicOrExU64, UINT64_C(0x42424242), UINT64_C(0x42424242));
2338 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0x00ff0f00), UINT64_C(0x00420200));
2339 //TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicXorExU64, UINT64_C(0x42004042), UINT64_C(0x42424242));
2340 //TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicXorExU64, UINT64_C(0xff024200), UINT64_C(0xbd400042));
2341 //TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicXorExU64, UINT64_C(0x00000000), UINT64_C(0xbd400042));
2342
2343 /* full 64-bit */
2344 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0x0000000000000000), UINT64_C(0x0000000000000000));
2345 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicOrExU64, UINT64_C(0xffffffffffffffff), UINT64_C(0xffffffffffffffff));
2346 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0xffffffffffffffff), UINT64_C(0xffffffffffffffff));
2347 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0x8f8f8f8f8f8f8f8f), UINT64_C(0x8f8f8f8f8f8f8f8f));
2348 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicOrExU64, UINT64_C(0x7070707070707070), UINT64_C(0xffffffffffffffff));
2349 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0x0000000000000001), UINT64_C(0x0000000000000001));
2350 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicOrExU64, UINT64_C(0x8000000000000000), UINT64_C(0x8000000000000001));
2351 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0x8000000000000000), UINT64_C(0x8000000000000000));
2352 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0), UINT64_C(0));
2353 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicOrExU64, UINT64_C(0x4242424242424242), UINT64_C(0x4242424242424242));
2354 TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicAndExU64, UINT64_C(0x00ff0f00ff0f0000), UINT64_C(0x0042020042020000));
2355 //TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicXorExU64, UINT64_C(0x4200404242040000), UINT64_C(0x4242424242420000));
2356 //TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicXorExU64, UINT64_C(0xff02420000ff2127), UINT64_C(0xbd40004242bd2127));
2357 //TEST_RET_OLD(uint64_t, "%#llx", pu64, ASMAtomicXorExU64, UINT64_C(0x0000000000000000), UINT64_C(0xbd40004242bd2127));
2358}
2359#endif
2360
2361
2362static void tstASMAtomicAndOrXor(void)
2363{
2364 DO_SIMPLE_TEST(ASMAtomicAndOrXorU32, uint32_t);
2365 DO_SIMPLE_TEST(ASMAtomicUoAndOrXorU32, uint32_t);
2366 DO_SIMPLE_TEST(ASMAtomicAndOrXorExU32, uint32_t);
2367 DO_SIMPLE_TEST(ASMAtomicAndOrXorU64, uint64_t);
2368 DO_SIMPLE_TEST(ASMAtomicUoAndOrXorU64, uint64_t);
2369 //DO_SIMPLE_TEST(ASMAtomicAndOrXorExU64, uint64_t);
2370}
2371
2372
2373typedef struct
2374{
2375 uint8_t ab[PAGE_SIZE];
2376} TSTPAGE;
2377
2378
2379DECLINLINE(void) tstASMMemZeroPageWorker(TSTPAGE *pPage)
2380{
2381 for (unsigned j = 0; j < 16; j++)
2382 {
2383 memset(pPage, 0x11 * j, sizeof(*pPage));
2384 ASMMemZeroPage(pPage);
2385 for (unsigned i = 0; i < sizeof(pPage->ab); i++)
2386 if (pPage->ab[i])
2387 RTTestFailed(g_hTest, "ASMMemZeroPage didn't clear byte at offset %#x!\n", i);
2388 if (ASMMemIsZeroPage(pPage) != true)
2389 RTTestFailed(g_hTest, "ASMMemIsZeroPage returns false after ASMMemZeroPage!\n");
2390 if (ASMMemFirstMismatchingU32(pPage, sizeof(pPage), 0) != NULL)
2391 RTTestFailed(g_hTest, "ASMMemFirstMismatchingU32(,,0) returns non-NULL after ASMMemZeroPage!\n");
2392 }
2393}
2394
2395
2396static void tstASMMemZeroPage(void)
2397{
2398 RTTestISub("ASMMemZeroPage");
2399 DO_SIMPLE_TEST_NO_SUB_NO_STACK(tstASMMemZeroPageWorker, TSTPAGE);
2400}
2401
2402
2403void tstASMMemIsZeroPage(RTTEST hTest)
2404{
2405 RTTestSub(hTest, "ASMMemIsZeroPage");
2406
2407 void *pvPage1 = RTTestGuardedAllocHead(hTest, PAGE_SIZE);
2408 void *pvPage2 = RTTestGuardedAllocTail(hTest, PAGE_SIZE);
2409 RTTESTI_CHECK_RETV(pvPage1 && pvPage2);
2410
2411 memset(pvPage1, 0, PAGE_SIZE);
2412 memset(pvPage2, 0, PAGE_SIZE);
2413 RTTESTI_CHECK(ASMMemIsZeroPage(pvPage1));
2414 RTTESTI_CHECK(ASMMemIsZeroPage(pvPage2));
2415
2416 memset(pvPage1, 0xff, PAGE_SIZE);
2417 memset(pvPage2, 0xff, PAGE_SIZE);
2418 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage1));
2419 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage2));
2420
2421 memset(pvPage1, 0, PAGE_SIZE);
2422 memset(pvPage2, 0, PAGE_SIZE);
2423 for (unsigned off = 0; off < PAGE_SIZE; off++)
2424 {
2425 ((uint8_t *)pvPage1)[off] = 1;
2426 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage1));
2427 ((uint8_t *)pvPage1)[off] = 0;
2428
2429 ((uint8_t *)pvPage2)[off] = 0x80;
2430 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage2));
2431 ((uint8_t *)pvPage2)[off] = 0;
2432 }
2433
2434 RTTestSubDone(hTest);
2435}
2436
2437
2438void tstASMMemFirstMismatchingU8(RTTEST hTest)
2439{
2440 RTTestSub(hTest, "ASMMemFirstMismatchingU8");
2441
2442 uint8_t *pbPage1 = (uint8_t *)RTTestGuardedAllocHead(hTest, PAGE_SIZE);
2443 uint8_t *pbPage2 = (uint8_t *)RTTestGuardedAllocTail(hTest, PAGE_SIZE);
2444 RTTESTI_CHECK_RETV(pbPage1 && pbPage2);
2445
2446 memset(pbPage1, 0, PAGE_SIZE);
2447 memset(pbPage2, 0, PAGE_SIZE);
2448 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, PAGE_SIZE, 0) == NULL);
2449 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, PAGE_SIZE, 0) == NULL);
2450 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, PAGE_SIZE, 1) == pbPage1);
2451 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, PAGE_SIZE, 1) == pbPage2);
2452 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, PAGE_SIZE, 0x87) == pbPage1);
2453 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, PAGE_SIZE, 0x87) == pbPage2);
2454 RTTESTI_CHECK(ASMMemIsZero(pbPage1, PAGE_SIZE));
2455 RTTESTI_CHECK(ASMMemIsZero(pbPage2, PAGE_SIZE));
2456 RTTESTI_CHECK(ASMMemIsAllU8(pbPage1, PAGE_SIZE, 0));
2457 RTTESTI_CHECK(ASMMemIsAllU8(pbPage2, PAGE_SIZE, 0));
2458 RTTESTI_CHECK(!ASMMemIsAllU8(pbPage1, PAGE_SIZE, 0x34));
2459 RTTESTI_CHECK(!ASMMemIsAllU8(pbPage2, PAGE_SIZE, 0x88));
2460 unsigned cbSub = 32;
2461 while (cbSub-- > 0)
2462 {
2463 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage1[PAGE_SIZE - cbSub], cbSub, 0) == NULL);
2464 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage2[PAGE_SIZE - cbSub], cbSub, 0) == NULL);
2465 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, cbSub, 0) == NULL);
2466 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, cbSub, 0) == NULL);
2467
2468 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage1[PAGE_SIZE - cbSub], cbSub, 0x34) == &pbPage1[PAGE_SIZE - cbSub] || !cbSub);
2469 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage2[PAGE_SIZE - cbSub], cbSub, 0x99) == &pbPage2[PAGE_SIZE - cbSub] || !cbSub);
2470 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, cbSub, 0x42) == pbPage1 || !cbSub);
2471 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, cbSub, 0x88) == pbPage2 || !cbSub);
2472 }
2473
2474 memset(pbPage1, 0xff, PAGE_SIZE);
2475 memset(pbPage2, 0xff, PAGE_SIZE);
2476 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, PAGE_SIZE, 0xff) == NULL);
2477 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, PAGE_SIZE, 0xff) == NULL);
2478 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, PAGE_SIZE, 0xfe) == pbPage1);
2479 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, PAGE_SIZE, 0xfe) == pbPage2);
2480 RTTESTI_CHECK(!ASMMemIsZero(pbPage1, PAGE_SIZE));
2481 RTTESTI_CHECK(!ASMMemIsZero(pbPage2, PAGE_SIZE));
2482 RTTESTI_CHECK(ASMMemIsAllU8(pbPage1, PAGE_SIZE, 0xff));
2483 RTTESTI_CHECK(ASMMemIsAllU8(pbPage2, PAGE_SIZE, 0xff));
2484 RTTESTI_CHECK(!ASMMemIsAllU8(pbPage1, PAGE_SIZE, 0));
2485 RTTESTI_CHECK(!ASMMemIsAllU8(pbPage2, PAGE_SIZE, 0));
2486 cbSub = 32;
2487 while (cbSub-- > 0)
2488 {
2489 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage1[PAGE_SIZE - cbSub], cbSub, 0xff) == NULL);
2490 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage2[PAGE_SIZE - cbSub], cbSub, 0xff) == NULL);
2491 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, cbSub, 0xff) == NULL);
2492 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, cbSub, 0xff) == NULL);
2493
2494 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage1[PAGE_SIZE - cbSub], cbSub, 0xfe) == &pbPage1[PAGE_SIZE - cbSub] || !cbSub);
2495 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage2[PAGE_SIZE - cbSub], cbSub, 0xfe) == &pbPage2[PAGE_SIZE - cbSub] || !cbSub);
2496 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, cbSub, 0xfe) == pbPage1 || !cbSub);
2497 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, cbSub, 0xfe) == pbPage2 || !cbSub);
2498 }
2499
2500
2501 /*
2502 * Various alignments and sizes.
2503 */
2504 uint8_t const bFiller1 = 0x00;
2505 uint8_t const bFiller2 = 0xf6;
2506 size_t const cbBuf = 128;
2507 uint8_t *pbBuf1 = pbPage1;
2508 uint8_t *pbBuf2 = &pbPage2[PAGE_SIZE - cbBuf]; /* Put it up against the tail guard */
2509 memset(pbPage1, ~bFiller1, PAGE_SIZE);
2510 memset(pbPage2, ~bFiller2, PAGE_SIZE);
2511 memset(pbBuf1, bFiller1, cbBuf);
2512 memset(pbBuf2, bFiller2, cbBuf);
2513 for (size_t offNonZero = 0; offNonZero < cbBuf; offNonZero++)
2514 {
2515 uint8_t bRand = (uint8_t)RTRandU32();
2516 pbBuf1[offNonZero] = bRand | 1;
2517 pbBuf2[offNonZero] = (0x80 | bRand) ^ 0xf6;
2518
2519 for (size_t offStart = 0; offStart < 32; offStart++)
2520 {
2521 size_t const cbMax = cbBuf - offStart;
2522 for (size_t cb = 0; cb < cbMax; cb++)
2523 {
2524 size_t const offEnd = offStart + cb;
2525 uint8_t bSaved1, bSaved2;
2526 if (offEnd < PAGE_SIZE)
2527 {
2528 bSaved1 = pbBuf1[offEnd];
2529 bSaved2 = pbBuf2[offEnd];
2530 pbBuf1[offEnd] = 0xff;
2531 pbBuf2[offEnd] = 0xff;
2532 }
2533#ifdef _MSC_VER /* simple stupid compiler warnings */
2534 else
2535 bSaved1 = bSaved2 = 0;
2536#endif
2537
2538 uint8_t *pbRet = (uint8_t *)ASMMemFirstMismatchingU8(pbBuf1 + offStart, cb, bFiller1);
2539 RTTESTI_CHECK(offNonZero - offStart < cb ? pbRet == &pbBuf1[offNonZero] : pbRet == NULL);
2540
2541 pbRet = (uint8_t *)ASMMemFirstMismatchingU8(pbBuf2 + offStart, cb, bFiller2);
2542 RTTESTI_CHECK(offNonZero - offStart < cb ? pbRet == &pbBuf2[offNonZero] : pbRet == NULL);
2543
2544 if (offEnd < PAGE_SIZE)
2545 {
2546 pbBuf1[offEnd] = bSaved1;
2547 pbBuf2[offEnd] = bSaved2;
2548 }
2549 }
2550 }
2551
2552 pbBuf1[offNonZero] = 0;
2553 pbBuf2[offNonZero] = 0xf6;
2554 }
2555
2556 RTTestSubDone(hTest);
2557}
2558
2559
2560typedef struct TSTBUF32 { uint32_t au32[384]; } TSTBUF32;
2561
2562DECLINLINE(void) tstASMMemZero32Worker(TSTBUF32 *pBuf)
2563{
2564 ASMMemZero32(pBuf, sizeof(*pBuf));
2565 for (unsigned i = 0; i < RT_ELEMENTS(pBuf->au32); i++)
2566 if (pBuf->au32[i])
2567 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear dword at index %#x!\n", i);
2568 if (ASMMemFirstNonZero(pBuf, sizeof(*pBuf)) != NULL)
2569 RTTestFailed(g_hTest, "ASMMemFirstNonZero return non-NULL after ASMMemZero32\n");
2570 if (!ASMMemIsZero(pBuf, sizeof(*pBuf)))
2571 RTTestFailed(g_hTest, "ASMMemIsZero return false after ASMMemZero32\n");
2572
2573 memset(pBuf, 0xfe, sizeof(*pBuf));
2574 ASMMemZero32(pBuf, sizeof(*pBuf));
2575 for (unsigned i = 0; i < RT_ELEMENTS(pBuf->au32); i++)
2576 if (pBuf->au32[i])
2577 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear dword at index %#x!\n", i);
2578 if (ASMMemFirstNonZero(pBuf, sizeof(*pBuf)) != NULL)
2579 RTTestFailed(g_hTest, "ASMMemFirstNonZero return non-NULL after ASMMemZero32\n");
2580 if (!ASMMemIsZero(pBuf, sizeof(*pBuf)))
2581 RTTestFailed(g_hTest, "ASMMemIsZero return false after ASMMemZero32\n");
2582}
2583
2584
2585void tstASMMemZero32(void)
2586{
2587 RTTestSub(g_hTest, "ASMMemZero32");
2588
2589 struct
2590 {
2591 uint64_t u64Magic1;
2592 uint8_t abPage[PAGE_SIZE - 32];
2593 uint64_t u64Magic2;
2594 } Buf1, Buf2, Buf3;
2595
2596 Buf1.u64Magic1 = UINT64_C(0xffffffffffffffff);
2597 memset(Buf1.abPage, 0x55, sizeof(Buf1.abPage));
2598 Buf1.u64Magic2 = UINT64_C(0xffffffffffffffff);
2599 Buf2.u64Magic1 = UINT64_C(0xffffffffffffffff);
2600 memset(Buf2.abPage, 0x77, sizeof(Buf2.abPage));
2601 Buf2.u64Magic2 = UINT64_C(0xffffffffffffffff);
2602 Buf3.u64Magic1 = UINT64_C(0xffffffffffffffff);
2603 memset(Buf3.abPage, 0x99, sizeof(Buf3.abPage));
2604 Buf3.u64Magic2 = UINT64_C(0xffffffffffffffff);
2605 ASMMemZero32(Buf1.abPage, sizeof(Buf1.abPage));
2606 ASMMemZero32(Buf2.abPage, sizeof(Buf2.abPage));
2607 ASMMemZero32(Buf3.abPage, sizeof(Buf3.abPage));
2608 if ( Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
2609 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
2610 || Buf2.u64Magic1 != UINT64_C(0xffffffffffffffff)
2611 || Buf2.u64Magic2 != UINT64_C(0xffffffffffffffff)
2612 || Buf3.u64Magic1 != UINT64_C(0xffffffffffffffff)
2613 || Buf3.u64Magic2 != UINT64_C(0xffffffffffffffff))
2614 {
2615 RTTestFailed(g_hTest, "ASMMemZero32 violated one/both magic(s)!\n");
2616 }
2617 for (unsigned i = 0; i < RT_ELEMENTS(Buf1.abPage); i++)
2618 if (Buf1.abPage[i])
2619 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear byte at offset %#x!\n", i);
2620 for (unsigned i = 0; i < RT_ELEMENTS(Buf2.abPage); i++)
2621 if (Buf2.abPage[i])
2622 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear byte at offset %#x!\n", i);
2623 for (unsigned i = 0; i < RT_ELEMENTS(Buf3.abPage); i++)
2624 if (Buf3.abPage[i])
2625 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear byte at offset %#x!\n", i);
2626
2627 DO_SIMPLE_TEST_NO_SUB(tstASMMemZero32Worker, TSTBUF32);
2628}
2629
2630
2631DECLINLINE(void) tstASMMemFill32Worker(TSTBUF32 *pBuf)
2632{
2633 ASMMemFill32(pBuf, sizeof(*pBuf), UINT32_C(0xf629bce1));
2634 for (unsigned i = 0; i < RT_ELEMENTS(pBuf->au32); i++)
2635 if (pBuf->au32[i] != UINT32_C(0xf629bce1))
2636 RTTestFailed(g_hTest, "ASMMemFill32 didn't set dword at index %#x correctly!\n", i);
2637 if (ASMMemFirstMismatchingU32(pBuf, sizeof(*pBuf), UINT32_C(0xf629bce1)) != NULL)
2638 RTTestFailed(g_hTest, "ASMMemFirstMismatchingU32(,,UINT32_C(0xf629bce1)) returns non-NULL after ASMMemFill32!\n");
2639
2640 memset(pBuf, 0xfe, sizeof(*pBuf));
2641 ASMMemFill32(pBuf, sizeof(*pBuf), UINT32_C(0x12345678));
2642 for (unsigned i = 0; i < RT_ELEMENTS(pBuf->au32); i++)
2643 if (pBuf->au32[i] != UINT32_C(0x12345678))
2644 RTTestFailed(g_hTest, "ASMMemFill32 didn't set dword at index %#x correctly!\n", i);
2645 if (ASMMemFirstMismatchingU32(pBuf, sizeof(*pBuf), UINT32_C(0x12345678)) != NULL)
2646 RTTestFailed(g_hTest, "ASMMemFirstMismatchingU32(,,UINT32_C(0x12345678)) returns non-NULL after ASMMemFill32!\n");
2647}
2648
2649void tstASMMemFill32(void)
2650{
2651 RTTestSub(g_hTest, "ASMMemFill32");
2652
2653 struct
2654 {
2655 uint64_t u64Magic1;
2656 uint32_t au32Page[PAGE_SIZE / 4];
2657 uint64_t u64Magic2;
2658 } Buf1;
2659 struct
2660 {
2661 uint64_t u64Magic1;
2662 uint32_t au32Page[(PAGE_SIZE / 4) - 3];
2663 uint64_t u64Magic2;
2664 } Buf2;
2665 struct
2666 {
2667 uint64_t u64Magic1;
2668 uint32_t au32Page[(PAGE_SIZE / 4) - 1];
2669 uint64_t u64Magic2;
2670 } Buf3;
2671
2672 Buf1.u64Magic1 = UINT64_C(0xffffffffffffffff);
2673 memset(Buf1.au32Page, 0x55, sizeof(Buf1.au32Page));
2674 Buf1.u64Magic2 = UINT64_C(0xffffffffffffffff);
2675 Buf2.u64Magic1 = UINT64_C(0xffffffffffffffff);
2676 memset(Buf2.au32Page, 0x77, sizeof(Buf2.au32Page));
2677 Buf2.u64Magic2 = UINT64_C(0xffffffffffffffff);
2678 Buf3.u64Magic1 = UINT64_C(0xffffffffffffffff);
2679 memset(Buf3.au32Page, 0x99, sizeof(Buf3.au32Page));
2680 Buf3.u64Magic2 = UINT64_C(0xffffffffffffffff);
2681 ASMMemFill32(Buf1.au32Page, sizeof(Buf1.au32Page), 0xdeadbeef);
2682 ASMMemFill32(Buf2.au32Page, sizeof(Buf2.au32Page), 0xcafeff01);
2683 ASMMemFill32(Buf3.au32Page, sizeof(Buf3.au32Page), 0xf00dd00f);
2684 if ( Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
2685 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
2686 || Buf2.u64Magic1 != UINT64_C(0xffffffffffffffff)
2687 || Buf2.u64Magic2 != UINT64_C(0xffffffffffffffff)
2688 || Buf3.u64Magic1 != UINT64_C(0xffffffffffffffff)
2689 || Buf3.u64Magic2 != UINT64_C(0xffffffffffffffff))
2690 RTTestFailed(g_hTest, "ASMMemFill32 violated one/both magic(s)!\n");
2691 for (unsigned i = 0; i < RT_ELEMENTS(Buf1.au32Page); i++)
2692 if (Buf1.au32Page[i] != 0xdeadbeef)
2693 RTTestFailed(g_hTest, "ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf1.au32Page[i], 0xdeadbeef);
2694 for (unsigned i = 0; i < RT_ELEMENTS(Buf2.au32Page); i++)
2695 if (Buf2.au32Page[i] != 0xcafeff01)
2696 RTTestFailed(g_hTest, "ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf2.au32Page[i], 0xcafeff01);
2697 for (unsigned i = 0; i < RT_ELEMENTS(Buf3.au32Page); i++)
2698 if (Buf3.au32Page[i] != 0xf00dd00f)
2699 RTTestFailed(g_hTest, "ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf3.au32Page[i], 0xf00dd00f);
2700
2701 DO_SIMPLE_TEST_NO_SUB(tstASMMemFill32Worker, TSTBUF32);
2702}
2703
2704
2705void tstASMProbe(RTTEST hTest)
2706{
2707 RTTestSub(hTest, "ASMProbeReadByte/Buffer");
2708
2709 uint8_t b = 42;
2710 RTTESTI_CHECK(ASMProbeReadByte(&b) == 42);
2711 ASMProbeReadBuffer(&b, sizeof(b));
2712
2713 for (uint32_t cPages = 1; cPages < 16; cPages++)
2714 {
2715 uint8_t *pbBuf1 = (uint8_t *)RTTestGuardedAllocHead(hTest, cPages * PAGE_SIZE);
2716 uint8_t *pbBuf2 = (uint8_t *)RTTestGuardedAllocTail(hTest, cPages * PAGE_SIZE);
2717 RTTESTI_CHECK_RETV(pbBuf1 && pbBuf2);
2718
2719 memset(pbBuf1, 0xf6, cPages * PAGE_SIZE);
2720 memset(pbBuf2, 0x42, cPages * PAGE_SIZE);
2721
2722 RTTESTI_CHECK(ASMProbeReadByte(&pbBuf1[cPages * PAGE_SIZE - 1]) == 0xf6);
2723 RTTESTI_CHECK(ASMProbeReadByte(&pbBuf2[cPages * PAGE_SIZE - 1]) == 0x42);
2724 RTTESTI_CHECK(ASMProbeReadByte(&pbBuf1[0]) == 0xf6);
2725 RTTESTI_CHECK(ASMProbeReadByte(&pbBuf2[0]) == 0x42);
2726
2727 ASMProbeReadBuffer(pbBuf1, cPages * PAGE_SIZE);
2728 ASMProbeReadBuffer(pbBuf2, cPages * PAGE_SIZE);
2729 }
2730}
2731
2732
2733void tstASMMisc(void)
2734{
2735 RTTestSub(g_hTest, "Misc");
2736 for (uint32_t i = 0; i < 20; i++)
2737 {
2738 ASMWriteFence();
2739 ASMCompilerBarrier();
2740 ASMReadFence();
2741 ASMNopPause();
2742 ASMSerializeInstruction();
2743 ASMMemoryFence();
2744 }
2745}
2746
2747
2748void tstASMBit(void)
2749{
2750 RTTestSub(g_hTest, "ASMBitFirstSetU16");
2751 RTTESTI_CHECK(ASMBitFirstSetU16(0x0000) == 0);
2752 RTTESTI_CHECK(ASMBitFirstSetU16(0x0001) == 1);
2753 RTTESTI_CHECK(ASMBitFirstSetU16(0x8000) == 16);
2754 RTTESTI_CHECK(ASMBitFirstSetU16(0x0ef0) == 5);
2755 for (unsigned iBit = 0; iBit < 16; iBit++)
2756 {
2757 RTTESTI_CHECK(ASMBitFirstSetU16((uint16_t)1 << iBit) == iBit + 1);
2758 RTTESTI_CHECK(ASMBitFirstSetU16(UINT16_MAX << iBit) == iBit + 1);
2759 }
2760
2761 RTTestSub(g_hTest, "ASMBitFirstSetU32");
2762 RTTESTI_CHECK(ASMBitFirstSetU32(UINT32_C(0x00000000)) == 0);
2763 RTTESTI_CHECK(ASMBitFirstSetU32(UINT32_C(0x00000001)) == 1);
2764 RTTESTI_CHECK(ASMBitFirstSetU32(UINT32_C(0x80000000)) == 32);
2765 RTTESTI_CHECK(ASMBitFirstSetU32(UINT32_C(0x0efff0f0)) == 5);
2766 for (unsigned iBit = 0; iBit < 32; iBit++)
2767 {
2768 RTTESTI_CHECK(ASMBitFirstSetU32((uint32_t)1 << iBit) == iBit + 1);
2769 RTTESTI_CHECK(ASMBitFirstSetU32(UINT32_MAX << iBit) == iBit + 1);
2770 }
2771
2772 RTTestSub(g_hTest, "ASMBitFirstSetU64");
2773 RTTESTI_CHECK(ASMBitFirstSetU64(UINT64_C(0x0000000000000000)) == 0);
2774 RTTESTI_CHECK(ASMBitFirstSetU64(UINT64_C(0x0000000000000001)) == 1);
2775 RTTESTI_CHECK(ASMBitFirstSetU64(UINT64_C(0x8000000000000000)) == 64);
2776 RTTESTI_CHECK(ASMBitFirstSetU64(UINT64_C(0x0effffff0ffff0f0)) == 5);
2777 for (unsigned iBit = 0; iBit < 64; iBit++)
2778 {
2779 RTTESTI_CHECK(ASMBitFirstSetU64((uint64_t)1 << iBit) == iBit + 1);
2780 RTTESTI_CHECK(ASMBitFirstSetU64(UINT64_MAX << iBit) == iBit + 1);
2781 }
2782
2783 RTTestSub(g_hTest, "ASMBitLastSetU16");
2784 RTTESTI_CHECK(ASMBitLastSetU16(0x0000) == 0);
2785 RTTESTI_CHECK(ASMBitLastSetU16(0x0001) == 1);
2786 RTTESTI_CHECK(ASMBitLastSetU16(0x8000) == 16);
2787 RTTESTI_CHECK(ASMBitLastSetU16(0x0fe0) == 12);
2788 for (unsigned iBit = 0; iBit < 16; iBit++)
2789 {
2790 RTTESTI_CHECK(ASMBitLastSetU16(UINT16_C(0x8000) >> (15 - iBit)) == iBit + 1);
2791 RTTESTI_CHECK(ASMBitLastSetU16(UINT16_MAX >> (15 - iBit)) == iBit + 1);
2792 }
2793
2794 RTTestSub(g_hTest, "ASMBitLastSetU32");
2795 RTTESTI_CHECK(ASMBitLastSetU32(UINT32_C(0x00000000)) == 0);
2796 RTTESTI_CHECK(ASMBitLastSetU32(UINT32_C(0x00000001)) == 1);
2797 RTTESTI_CHECK(ASMBitLastSetU32(UINT32_C(0x80000000)) == 32);
2798 RTTESTI_CHECK(ASMBitLastSetU32(UINT32_C(0x0fffffe0)) == 28);
2799 for (unsigned iBit = 0; iBit < 32; iBit++)
2800 {
2801 RTTESTI_CHECK(ASMBitLastSetU32(UINT32_C(0x80000000) >> (31 - iBit)) == iBit + 1);
2802 RTTESTI_CHECK(ASMBitLastSetU32(UINT32_MAX >> (31 - iBit)) == iBit + 1);
2803 }
2804
2805 RTTestSub(g_hTest, "ASMBitLastSetU64");
2806 RTTESTI_CHECK(ASMBitLastSetU64(UINT64_C(0x0000000000000000)) == 0);
2807 RTTESTI_CHECK(ASMBitLastSetU64(UINT64_C(0x0000000000000001)) == 1);
2808 RTTESTI_CHECK(ASMBitLastSetU64(UINT64_C(0x8000000000000000)) == 64);
2809 RTTESTI_CHECK(ASMBitLastSetU64(UINT64_C(0x0ffffefff0ffffe0)) == 60);
2810 for (unsigned iBit = 0; iBit < 64; iBit++)
2811 {
2812 RTTESTI_CHECK(ASMBitLastSetU64(UINT64_C(0x8000000000000000) >> (63 - iBit)) == iBit + 1);
2813 RTTESTI_CHECK(ASMBitLastSetU64(UINT64_MAX >> (63 - iBit)) == iBit + 1);
2814 }
2815
2816 RTTestSub(g_hTest, "ASMCountLeadingZerosU16");
2817 RTTESTI_CHECK(ASMCountLeadingZerosU16(0x0000) == 16);
2818 RTTESTI_CHECK(ASMCountLeadingZerosU16(0x0001) == 15);
2819 RTTESTI_CHECK(ASMCountLeadingZerosU16(0x8000) == 0);
2820 RTTESTI_CHECK(ASMCountLeadingZerosU16(0x0fe0) == 4);
2821 for (unsigned iBit = 0; iBit < 16; iBit++)
2822 {
2823 RTTESTI_CHECK(ASMCountLeadingZerosU16(UINT16_C(0x8000) >> iBit) == iBit);
2824 RTTESTI_CHECK(ASMCountLeadingZerosU16(UINT16_MAX >> iBit) == iBit);
2825 }
2826
2827 RTTestSub(g_hTest, "ASMCountLeadingZerosU32");
2828 RTTESTI_CHECK(ASMCountLeadingZerosU32(UINT32_C(0x00000000)) == 32);
2829 RTTESTI_CHECK(ASMCountLeadingZerosU32(UINT32_C(0x00000001)) == 31);
2830 RTTESTI_CHECK(ASMCountLeadingZerosU32(UINT32_C(0x80000000)) == 0);
2831 RTTESTI_CHECK(ASMCountLeadingZerosU32(UINT32_C(0x0fffffe0)) == 4);
2832 for (unsigned iBit = 0; iBit < 32; iBit++)
2833 {
2834 RTTESTI_CHECK(ASMCountLeadingZerosU32(UINT32_C(0x80000000) >> iBit) == iBit);
2835 RTTESTI_CHECK(ASMCountLeadingZerosU32(UINT32_MAX >> iBit) == iBit);
2836 }
2837
2838 RTTestSub(g_hTest, "ASMCountLeadingZerosU64");
2839 RTTESTI_CHECK(ASMCountLeadingZerosU64(UINT64_C(0x0000000000000000)) == 64);
2840 RTTESTI_CHECK(ASMCountLeadingZerosU64(UINT64_C(0x0000000000000001)) == 63);
2841 RTTESTI_CHECK(ASMCountLeadingZerosU64(UINT64_C(0x8000000000000000)) == 0);
2842 RTTESTI_CHECK(ASMCountLeadingZerosU64(UINT64_C(0x0fffffff0f0fffe0)) == 4);
2843 for (unsigned iBit = 0; iBit < 64; iBit++)
2844 {
2845 RTTESTI_CHECK(ASMCountLeadingZerosU64(UINT64_C(0x8000000000000000) >> iBit) == iBit);
2846 RTTESTI_CHECK(ASMCountLeadingZerosU64(UINT64_MAX >> iBit) == iBit);
2847 }
2848
2849 RTTestSub(g_hTest, "ASMCountTrailingZerosU16");
2850 RTTESTI_CHECK(ASMCountTrailingZerosU16(0x0000) == 16);
2851 RTTESTI_CHECK(ASMCountTrailingZerosU16(0x0001) == 0);
2852 RTTESTI_CHECK(ASMCountTrailingZerosU16(0x8000) == 15);
2853 RTTESTI_CHECK(ASMCountTrailingZerosU16(0x0ef0) == 4);
2854 for (unsigned iBit = 0; iBit < 16; iBit++)
2855 {
2856 RTTESTI_CHECK(ASMCountTrailingZerosU16((uint16_t)1 << iBit) == iBit);
2857 RTTESTI_CHECK(ASMCountTrailingZerosU16(UINT16_MAX << iBit) == iBit);
2858 }
2859
2860 RTTestSub(g_hTest, "ASMCountTrailingZerosU32");
2861 RTTESTI_CHECK(ASMCountTrailingZerosU32(UINT32_C(0x00000000)) == 32);
2862 RTTESTI_CHECK(ASMCountTrailingZerosU32(UINT32_C(0x00000001)) == 0);
2863 RTTESTI_CHECK(ASMCountTrailingZerosU32(UINT32_C(0x80000000)) == 31);
2864 RTTESTI_CHECK(ASMCountTrailingZerosU32(UINT32_C(0x0efffff0)) == 4);
2865 for (unsigned iBit = 0; iBit < 32; iBit++)
2866 {
2867 RTTESTI_CHECK(ASMCountTrailingZerosU32((uint32_t)1 << iBit) == iBit);
2868 RTTESTI_CHECK(ASMCountTrailingZerosU32(UINT32_MAX << iBit) == iBit);
2869 }
2870
2871 RTTestSub(g_hTest, "ASMCountTrailingZerosU64");
2872 RTTESTI_CHECK(ASMCountTrailingZerosU64(UINT64_C(0x0000000000000000)) == 64);
2873 RTTESTI_CHECK(ASMCountTrailingZerosU64(UINT64_C(0x0000000000000001)) == 0);
2874 RTTESTI_CHECK(ASMCountTrailingZerosU64(UINT64_C(0x8000000000000000)) == 63);
2875 RTTESTI_CHECK(ASMCountTrailingZerosU64(UINT64_C(0x0effff0fefef0ff0)) == 4);
2876 for (unsigned iBit = 0; iBit < 64; iBit++)
2877 {
2878 RTTESTI_CHECK(ASMCountTrailingZerosU64((uint64_t)1 << iBit) == iBit);
2879 RTTESTI_CHECK(ASMCountTrailingZerosU64(UINT64_MAX << iBit) == iBit);
2880 }
2881}
2882
2883
2884void tstASMMath(void)
2885{
2886 RTTestSub(g_hTest, "Math");
2887
2888 uint64_t u64 = ASMMult2xU32RetU64(UINT32_C(0x80000000), UINT32_C(0x10000000));
2889 CHECKVAL(u64, UINT64_C(0x0800000000000000), "%#018RX64");
2890
2891 uint32_t u32 = ASMDivU64ByU32RetU32(UINT64_C(0x0800000000000000), UINT32_C(0x10000000));
2892 CHECKVAL(u32, UINT32_C(0x80000000), "%#010RX32");
2893
2894 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x00000001), UINT32_C(0x00000001), UINT32_C(0x00000001));
2895 CHECKVAL(u32, UINT32_C(0x00000001), "%#018RX32");
2896 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x10000000), UINT32_C(0x80000000), UINT32_C(0x20000000));
2897 CHECKVAL(u32, UINT32_C(0x40000000), "%#018RX32");
2898 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x76543210), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
2899 CHECKVAL(u32, UINT32_C(0x76543210), "%#018RX32");
2900 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0xffffffff), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
2901 CHECKVAL(u32, UINT32_C(0xffffffff), "%#018RX32");
2902 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0xffffffff), UINT32_C(0xfffffff0), UINT32_C(0xffffffff));
2903 CHECKVAL(u32, UINT32_C(0xfffffff0), "%#018RX32");
2904 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x10359583), UINT32_C(0x58734981), UINT32_C(0xf8694045));
2905 CHECKVAL(u32, UINT32_C(0x05c584ce), "%#018RX32");
2906 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x10359583), UINT32_C(0xf8694045), UINT32_C(0x58734981));
2907 CHECKVAL(u32, UINT32_C(0x2d860795), "%#018RX32");
2908
2909#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
2910 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x0000000000000001), UINT32_C(0x00000001), UINT32_C(0x00000001));
2911 CHECKVAL(u64, UINT64_C(0x0000000000000001), "%#018RX64");
2912 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x0000000100000000), UINT32_C(0x80000000), UINT32_C(0x00000002));
2913 CHECKVAL(u64, UINT64_C(0x4000000000000000), "%#018RX64");
2914 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xfedcba9876543210), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
2915 CHECKVAL(u64, UINT64_C(0xfedcba9876543210), "%#018RX64");
2916 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xffffffffffffffff), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
2917 CHECKVAL(u64, UINT64_C(0xffffffffffffffff), "%#018RX64");
2918 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xffffffffffffffff), UINT32_C(0xfffffff0), UINT32_C(0xffffffff));
2919 CHECKVAL(u64, UINT64_C(0xfffffff0fffffff0), "%#018RX64");
2920 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x3415934810359583), UINT32_C(0x58734981), UINT32_C(0xf8694045));
2921 CHECKVAL(u64, UINT64_C(0x128b9c3d43184763), "%#018RX64");
2922 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x3415934810359583), UINT32_C(0xf8694045), UINT32_C(0x58734981));
2923 CHECKVAL(u64, UINT64_C(0x924719355cd35a27), "%#018RX64");
2924
2925# if 0 /* bird: question is whether this should trap or not:
2926 *
2927 * frank: Of course it must trap:
2928 *
2929 * 0xfffffff8 * 0x77d7daf8 = 0x77d7daf441412840
2930 *
2931 * During the following division, the quotient must fit into a 32-bit register.
2932 * Therefore the smallest valid divisor is
2933 *
2934 * (0x77d7daf441412840 >> 32) + 1 = 0x77d7daf5
2935 *
2936 * which is definitely greater than 0x3b9aca00.
2937 *
2938 * bird: No, the C version does *not* crash. So, the question is whether there's any
2939 * code depending on it not crashing.
2940 *
2941 * Of course the assembly versions of the code crash right now for the reasons you've
2942 * given, but the 32-bit MSC version does not crash.
2943 *
2944 * frank: The C version does not crash but delivers incorrect results for this case.
2945 * The reason is
2946 *
2947 * u.s.Hi = (unsigned long)(u64Hi / u32C);
2948 *
2949 * Here the division is actually 64-bit by 64-bit but the 64-bit result is truncated
2950 * to 32 bit. If using this (optimized and fast) function we should just be sure that
2951 * the operands are in a valid range.
2952 */
2953 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xfffffff8c65d6731), UINT32_C(0x77d7daf8), UINT32_C(0x3b9aca00));
2954 CHECKVAL(u64, UINT64_C(0x02b8f9a2aa74e3dc), "%#018RX64");
2955# endif
2956#endif /* AMD64 || X86 */
2957
2958 u32 = ASMModU64ByU32RetU32(UINT64_C(0x0ffffff8c65d6731), UINT32_C(0x77d7daf8));
2959 CHECKVAL(u32, UINT32_C(0x3B642451), "%#010RX32");
2960
2961 int32_t i32;
2962 i32 = ASMModS64ByS32RetS32(INT64_C(-11), INT32_C(-2));
2963 CHECKVAL(i32, INT32_C(-1), "%010RI32");
2964 i32 = ASMModS64ByS32RetS32(INT64_C(-11), INT32_C(2));
2965 CHECKVAL(i32, INT32_C(-1), "%010RI32");
2966 i32 = ASMModS64ByS32RetS32(INT64_C(11), INT32_C(-2));
2967 CHECKVAL(i32, INT32_C(1), "%010RI32");
2968
2969 i32 = ASMModS64ByS32RetS32(INT64_C(92233720368547758), INT32_C(2147483647));
2970 CHECKVAL(i32, INT32_C(2104533974), "%010RI32");
2971 i32 = ASMModS64ByS32RetS32(INT64_C(-92233720368547758), INT32_C(2147483647));
2972 CHECKVAL(i32, INT32_C(-2104533974), "%010RI32");
2973}
2974
2975
2976void tstASMByteSwap(void)
2977{
2978 RTTestSub(g_hTest, "ASMByteSwap*");
2979
2980 uint64_t u64In = UINT64_C(0x0011223344556677);
2981 uint64_t u64Out = ASMByteSwapU64(u64In);
2982 CHECKVAL(u64In, UINT64_C(0x0011223344556677), "%#018RX64");
2983 CHECKVAL(u64Out, UINT64_C(0x7766554433221100), "%#018RX64");
2984 u64Out = ASMByteSwapU64(u64Out);
2985 CHECKVAL(u64Out, u64In, "%#018RX64");
2986 u64In = UINT64_C(0x0123456789abcdef);
2987 u64Out = ASMByteSwapU64(u64In);
2988 CHECKVAL(u64In, UINT64_C(0x0123456789abcdef), "%#018RX64");
2989 CHECKVAL(u64Out, UINT64_C(0xefcdab8967452301), "%#018RX64");
2990 u64Out = ASMByteSwapU64(u64Out);
2991 CHECKVAL(u64Out, u64In, "%#018RX64");
2992 u64In = 0;
2993 u64Out = ASMByteSwapU64(u64In);
2994 CHECKVAL(u64Out, u64In, "%#018RX64");
2995 u64In = UINT64_MAX;
2996 u64Out = ASMByteSwapU64(u64In);
2997 CHECKVAL(u64Out, u64In, "%#018RX64");
2998
2999 uint32_t u32In = UINT32_C(0x00112233);
3000 uint32_t u32Out = ASMByteSwapU32(u32In);
3001 CHECKVAL(u32In, UINT32_C(0x00112233), "%#010RX32");
3002 CHECKVAL(u32Out, UINT32_C(0x33221100), "%#010RX32");
3003 u32Out = ASMByteSwapU32(u32Out);
3004 CHECKVAL(u32Out, u32In, "%#010RX32");
3005 u32In = UINT32_C(0x12345678);
3006 u32Out = ASMByteSwapU32(u32In);
3007 CHECKVAL(u32In, UINT32_C(0x12345678), "%#010RX32");
3008 CHECKVAL(u32Out, UINT32_C(0x78563412), "%#010RX32");
3009 u32Out = ASMByteSwapU32(u32Out);
3010 CHECKVAL(u32Out, u32In, "%#010RX32");
3011 u32In = 0;
3012 u32Out = ASMByteSwapU32(u32In);
3013 CHECKVAL(u32Out, u32In, "%#010RX32");
3014 u32In = UINT32_MAX;
3015 u32Out = ASMByteSwapU32(u32In);
3016 CHECKVAL(u32Out, u32In, "%#010RX32");
3017
3018 uint16_t u16In = UINT16_C(0x0011);
3019 uint16_t u16Out = ASMByteSwapU16(u16In);
3020 CHECKVAL(u16In, UINT16_C(0x0011), "%#06RX16");
3021 CHECKVAL(u16Out, UINT16_C(0x1100), "%#06RX16");
3022 u16Out = ASMByteSwapU16(u16Out);
3023 CHECKVAL(u16Out, u16In, "%#06RX16");
3024 u16In = UINT16_C(0x1234);
3025 u16Out = ASMByteSwapU16(u16In);
3026 CHECKVAL(u16In, UINT16_C(0x1234), "%#06RX16");
3027 CHECKVAL(u16Out, UINT16_C(0x3412), "%#06RX16");
3028 u16Out = ASMByteSwapU16(u16Out);
3029 CHECKVAL(u16Out, u16In, "%#06RX16");
3030 u16In = 0;
3031 u16Out = ASMByteSwapU16(u16In);
3032 CHECKVAL(u16Out, u16In, "%#06RX16");
3033 u16In = UINT16_MAX;
3034 u16Out = ASMByteSwapU16(u16In);
3035 CHECKVAL(u16Out, u16In, "%#06RX16");
3036}
3037
3038
3039void tstASMBench(void)
3040{
3041 /*
3042 * Make this static. We don't want to have this located on the stack.
3043 */
3044 static uint8_t volatile s_u8;
3045 static int8_t volatile s_i8;
3046 static uint16_t volatile s_u16;
3047 static int16_t volatile s_i16;
3048 static uint32_t volatile s_u32;
3049 static int32_t volatile s_i32;
3050 static uint64_t volatile s_u64;
3051 static int64_t volatile s_i64;
3052#if defined(RTASM_HAVE_CMP_WRITE_U128) || defined(RTASM_HAVE_CMP_XCHG_U128)
3053 static RTUINT128U volatile s_u128;
3054#endif
3055 static uint8_t s_u8Old;
3056 static int8_t s_i8Old;
3057 static uint16_t s_u16Old;
3058 static int16_t s_i16Old;
3059 static uint32_t s_u32Old;
3060 static int32_t s_i32Old;
3061 static uint64_t s_u64Old;
3062 static int64_t s_i64Old;
3063#if defined(RTASM_HAVE_CMP_WRITE_U128) || defined(RTASM_HAVE_CMP_XCHG_U128)
3064 static RTUINT128U s_u128Old;
3065 RTUINT128U u128Tmp1, u128Tmp2;
3066# ifdef RT_ARCH_AMD64
3067 bool const fHaveCmpXchg128 = RT_BOOL(ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_CX16);
3068# else
3069 bool const fHaveCmpXchg128 = true;
3070# endif
3071#endif
3072 unsigned i;
3073 const unsigned cRounds = _16M; /* Must be multiple of 8 */
3074 uint64_t u64Elapsed;
3075
3076 RTTestSub(g_hTest, "Benchmarking");
3077
3078#if 0 && !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) || defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32))
3079# define BENCH(op, str) \
3080 do { \
3081 RTThreadYield(); \
3082 u64Elapsed = ASMReadTSC(); \
3083 for (i = cRounds; i > 0; i--) \
3084 op; \
3085 u64Elapsed = ASMReadTSC() - u64Elapsed; \
3086 RTTestValue(g_hTest, str, u64Elapsed / cRounds, RTTESTUNIT_TICKS_PER_CALL); \
3087 } while (0)
3088#else
3089# define BENCH(op, str) \
3090 do { \
3091 RTThreadYield(); \
3092 u64Elapsed = RTTimeNanoTS(); \
3093 for (i = cRounds / 8; i > 0; i--) \
3094 { \
3095 op; \
3096 op; \
3097 op; \
3098 op; \
3099 op; \
3100 op; \
3101 op; \
3102 op; \
3103 } \
3104 u64Elapsed = RTTimeNanoTS() - u64Elapsed; \
3105 RTTestValue(g_hTest, str, u64Elapsed * 1000 / cRounds, RTTESTUNIT_PS_PER_CALL); \
3106 } while (0)
3107#endif
3108#if (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) || defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)) && !defined(GCC44_32BIT_PIC)
3109# define BENCH_TSC(op, str) \
3110 do { \
3111 RTThreadYield(); \
3112 u64Elapsed = ASMReadTSC(); \
3113 for (i = cRounds / 8; i > 0; i--) \
3114 { \
3115 op; \
3116 op; \
3117 op; \
3118 op; \
3119 op; \
3120 op; \
3121 op; \
3122 op; \
3123 } \
3124 u64Elapsed = ASMReadTSC() - u64Elapsed; \
3125 RTTestValue(g_hTest, str, u64Elapsed / cRounds, RTTESTUNIT_TICKS_PER_CALL); \
3126 } while (0)
3127#else
3128# define BENCH_TSC(op, str) BENCH(op, str)
3129#endif
3130
3131 BENCH(s_u32 = 0, "s_u32 = 0");
3132 BENCH(ASMAtomicUoReadU8(&s_u8), "ASMAtomicUoReadU8");
3133 BENCH(ASMAtomicUoReadS8(&s_i8), "ASMAtomicUoReadS8");
3134 BENCH(ASMAtomicUoReadU16(&s_u16), "ASMAtomicUoReadU16");
3135 BENCH(ASMAtomicUoReadS16(&s_i16), "ASMAtomicUoReadS16");
3136 BENCH(ASMAtomicUoReadU32(&s_u32), "ASMAtomicUoReadU32");
3137 BENCH(ASMAtomicUoReadS32(&s_i32), "ASMAtomicUoReadS32");
3138 BENCH(ASMAtomicUoReadU64(&s_u64), "ASMAtomicUoReadU64");
3139 BENCH(ASMAtomicUoReadS64(&s_i64), "ASMAtomicUoReadS64");
3140 BENCH(ASMAtomicReadU8(&s_u8), "ASMAtomicReadU8");
3141 BENCH(ASMAtomicReadS8(&s_i8), "ASMAtomicReadS8");
3142 BENCH(ASMAtomicReadU16(&s_u16), "ASMAtomicReadU16");
3143 BENCH(ASMAtomicReadS16(&s_i16), "ASMAtomicReadS16");
3144 BENCH(ASMAtomicReadU32(&s_u32), "ASMAtomicReadU32");
3145 BENCH(ASMAtomicReadS32(&s_i32), "ASMAtomicReadS32");
3146 BENCH(ASMAtomicReadU64(&s_u64), "ASMAtomicReadU64");
3147 BENCH(ASMAtomicReadS64(&s_i64), "ASMAtomicReadS64");
3148 BENCH(ASMAtomicUoWriteU8(&s_u8, 0), "ASMAtomicUoWriteU8");
3149 BENCH(ASMAtomicUoWriteS8(&s_i8, 0), "ASMAtomicUoWriteS8");
3150 BENCH(ASMAtomicUoWriteU16(&s_u16, 0), "ASMAtomicUoWriteU16");
3151 BENCH(ASMAtomicUoWriteS16(&s_i16, 0), "ASMAtomicUoWriteS16");
3152 BENCH(ASMAtomicUoWriteU32(&s_u32, 0), "ASMAtomicUoWriteU32");
3153 BENCH(ASMAtomicUoWriteS32(&s_i32, 0), "ASMAtomicUoWriteS32");
3154 BENCH(ASMAtomicUoWriteU64(&s_u64, 0), "ASMAtomicUoWriteU64");
3155 BENCH(ASMAtomicUoWriteS64(&s_i64, 0), "ASMAtomicUoWriteS64");
3156 BENCH(ASMAtomicWriteU8(&s_u8, 0), "ASMAtomicWriteU8");
3157 BENCH(ASMAtomicWriteS8(&s_i8, 0), "ASMAtomicWriteS8");
3158 BENCH(ASMAtomicWriteU16(&s_u16, 0), "ASMAtomicWriteU16");
3159 BENCH(ASMAtomicWriteS16(&s_i16, 0), "ASMAtomicWriteS16");
3160 BENCH(ASMAtomicWriteU32(&s_u32, 0), "ASMAtomicWriteU32");
3161 BENCH(ASMAtomicWriteS32(&s_i32, 0), "ASMAtomicWriteS32");
3162 BENCH(ASMAtomicWriteU64(&s_u64, 0), "ASMAtomicWriteU64");
3163 BENCH(ASMAtomicWriteS64(&s_i64, 0), "ASMAtomicWriteS64");
3164 BENCH(ASMAtomicXchgU8(&s_u8, 0), "ASMAtomicXchgU8");
3165 BENCH(ASMAtomicXchgS8(&s_i8, 0), "ASMAtomicXchgS8");
3166 BENCH(ASMAtomicXchgU16(&s_u16, 0), "ASMAtomicXchgU16");
3167 BENCH(ASMAtomicXchgS16(&s_i16, 0), "ASMAtomicXchgS16");
3168 BENCH(ASMAtomicXchgU32(&s_u32, 0), "ASMAtomicXchgU32");
3169 BENCH(ASMAtomicXchgS32(&s_i32, 0), "ASMAtomicXchgS32");
3170 BENCH(ASMAtomicXchgU64(&s_u64, 0), "ASMAtomicXchgU64");
3171 BENCH(ASMAtomicXchgS64(&s_i64, 0), "ASMAtomicXchgS64");
3172 BENCH(ASMAtomicCmpXchgU8(&s_u8, 0, 0), "ASMAtomicCmpXchgU8");
3173 BENCH(ASMAtomicCmpXchgS8(&s_i8, 0, 0), "ASMAtomicCmpXchgS8");
3174 //BENCH(ASMAtomicCmpXchgU16(&s_u16, 0, 0), "ASMAtomicCmpXchgU16");
3175 //BENCH(ASMAtomicCmpXchgS16(&s_i16, 0, 0), "ASMAtomicCmpXchgS16");
3176 BENCH(ASMAtomicCmpXchgU32(&s_u32, 0, 0), "ASMAtomicCmpXchgU32");
3177 BENCH(ASMAtomicCmpXchgS32(&s_i32, 0, 0), "ASMAtomicCmpXchgS32");
3178 BENCH(ASMAtomicCmpXchgU64(&s_u64, 0, 0), "ASMAtomicCmpXchgU64");
3179 BENCH(ASMAtomicCmpXchgS64(&s_i64, 0, 0), "ASMAtomicCmpXchgS64");
3180#ifdef RTASM_HAVE_CMP_WRITE_U128
3181 if (fHaveCmpXchg128)
3182 BENCH(ASMAtomicCmpWriteU128U(&s_u128, u128Tmp1 = RTUINT128_INIT_C(0, 0), u128Tmp2 = RTUINT128_INIT_C(0, 0)),
3183 "ASMAtomicCmpWriteU128U");
3184#endif
3185 BENCH(ASMAtomicCmpXchgU8(&s_u8, 0, 1), "ASMAtomicCmpXchgU8/neg");
3186 BENCH(ASMAtomicCmpXchgS8(&s_i8, 0, 1), "ASMAtomicCmpXchgS8/neg");
3187 //BENCH(ASMAtomicCmpXchgU16(&s_u16, 0, 1), "ASMAtomicCmpXchgU16/neg");
3188 //BENCH(ASMAtomicCmpXchgS16(&s_s16, 0, 1), "ASMAtomicCmpXchgS16/neg");
3189 BENCH(ASMAtomicCmpXchgU32(&s_u32, 0, 1), "ASMAtomicCmpXchgU32/neg");
3190 BENCH(ASMAtomicCmpXchgS32(&s_i32, 0, 1), "ASMAtomicCmpXchgS32/neg");
3191 BENCH(ASMAtomicCmpXchgU64(&s_u64, 0, 1), "ASMAtomicCmpXchgU64/neg");
3192 BENCH(ASMAtomicCmpXchgS64(&s_i64, 0, 1), "ASMAtomicCmpXchgS64/neg");
3193#ifdef RTASM_HAVE_CMP_WRITE_U128
3194 if (fHaveCmpXchg128)
3195 BENCH(ASMAtomicCmpWriteU128U(&s_u128, u128Tmp1 = RTUINT128_INIT_C(0, 0), u128Tmp2 = RTUINT128_INIT_C(0, 1)),
3196 "ASMAtomicCmpWriteU128U/neg");
3197#endif
3198 BENCH(ASMAtomicCmpXchgExU8(&s_u8, 0, 0, &s_u8Old), "ASMAtomicCmpXchgExU8");
3199 BENCH(ASMAtomicCmpXchgExS8(&s_i8, 0, 0, &s_i8Old), "ASMAtomicCmpXchgExS8");
3200 BENCH(ASMAtomicCmpXchgExU16(&s_u16, 0, 0, &s_u16Old), "ASMAtomicCmpXchgExU16");
3201 BENCH(ASMAtomicCmpXchgExS16(&s_i16, 0, 0, &s_i16Old), "ASMAtomicCmpXchgExS16");
3202 BENCH(ASMAtomicCmpXchgExU32(&s_u32, 0, 0, &s_u32Old), "ASMAtomicCmpXchgExU32");
3203 BENCH(ASMAtomicCmpXchgExS32(&s_i32, 0, 0, &s_i32Old), "ASMAtomicCmpXchgExS32");
3204 BENCH(ASMAtomicCmpXchgExU64(&s_u64, 0, 0, &s_u64Old), "ASMAtomicCmpXchgExU64");
3205 BENCH(ASMAtomicCmpXchgExS64(&s_i64, 0, 0, &s_i64Old), "ASMAtomicCmpXchgExS64");
3206#ifdef RTASM_HAVE_CMP_XCHG_U128
3207 if (fHaveCmpXchg128)
3208 BENCH(ASMAtomicCmpXchgU128U(&s_u128, u128Tmp1 = RTUINT128_INIT_C(0, 0), u128Tmp2 = RTUINT128_INIT_C(0, 0), &s_u128Old),
3209 "ASMAtomicCmpXchgU128U");
3210#endif
3211 BENCH(ASMAtomicCmpXchgExU8(&s_u8, 0, 1, &s_u8Old), "ASMAtomicCmpXchgExU8/neg");
3212 BENCH(ASMAtomicCmpXchgExS8(&s_i8, 0, 1, &s_i8Old), "ASMAtomicCmpXchgExS8/neg");
3213 BENCH(ASMAtomicCmpXchgExU16(&s_u16, 0, 1, &s_u16Old), "ASMAtomicCmpXchgExU16/neg");
3214 BENCH(ASMAtomicCmpXchgExS16(&s_i16, 0, 1, &s_i16Old), "ASMAtomicCmpXchgExS16/neg");
3215 BENCH(ASMAtomicCmpXchgExU32(&s_u32, 0, 1, &s_u32Old), "ASMAtomicCmpXchgExU32/neg");
3216 BENCH(ASMAtomicCmpXchgExS32(&s_i32, 0, 1, &s_i32Old), "ASMAtomicCmpXchgExS32/neg");
3217 BENCH(ASMAtomicCmpXchgExU64(&s_u64, 0, 1, &s_u64Old), "ASMAtomicCmpXchgExU64/neg");
3218 BENCH(ASMAtomicCmpXchgExS64(&s_i64, 0, 1, &s_i64Old), "ASMAtomicCmpXchgExS64/neg");
3219#ifdef RTASM_HAVE_CMP_XCHG_U128
3220 if (fHaveCmpXchg128)
3221 BENCH(ASMAtomicCmpXchgU128U(&s_u128, u128Tmp1 = RTUINT128_INIT_C(0, 0), u128Tmp2 = RTUINT128_INIT_C(0, 1), &s_u128Old),
3222 "ASMAtomicCmpXchgU128U/neg");
3223#endif
3224 BENCH(ASMAtomicIncU32(&s_u32), "ASMAtomicIncU32");
3225 BENCH(ASMAtomicIncS32(&s_i32), "ASMAtomicIncS32");
3226 BENCH(ASMAtomicDecU32(&s_u32), "ASMAtomicDecU32");
3227 BENCH(ASMAtomicDecS32(&s_i32), "ASMAtomicDecS32");
3228 BENCH(ASMAtomicAddU32(&s_u32, 5), "ASMAtomicAddU32");
3229 BENCH(ASMAtomicAddS32(&s_i32, 5), "ASMAtomicAddS32");
3230 BENCH(ASMAtomicUoIncU32(&s_u32), "ASMAtomicUoIncU32");
3231 BENCH(ASMAtomicUoDecU32(&s_u32), "ASMAtomicUoDecU32");
3232 BENCH(ASMAtomicUoAndU32(&s_u32, 0xffffffff), "ASMAtomicUoAndU32");
3233 BENCH(ASMAtomicUoOrU32(&s_u32, 0xffffffff), "ASMAtomicUoOrU32");
3234#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
3235 BENCH_TSC(ASMSerializeInstructionCpuId(), "ASMSerializeInstructionCpuId");
3236 BENCH_TSC(ASMSerializeInstructionIRet(), "ASMSerializeInstructionIRet");
3237#endif
3238 BENCH(ASMReadFence(), "ASMReadFence");
3239 BENCH(ASMWriteFence(), "ASMWriteFence");
3240 BENCH(ASMMemoryFence(), "ASMMemoryFence");
3241 BENCH(ASMSerializeInstruction(), "ASMSerializeInstruction");
3242 BENCH(ASMNopPause(), "ASMNopPause");
3243
3244 BENCH(ASMBitFirstSetU16(s_u16), "ASMBitFirstSetU16");
3245 BENCH(ASMBitFirstSetU32(s_u32), "ASMBitFirstSetU32");
3246 BENCH(ASMBitFirstSetU64(s_u32), "ASMBitFirstSetU64");
3247 BENCH(ASMBitLastSetU16(s_u16), "ASMBitLastSetU16");
3248 BENCH(ASMBitLastSetU32(s_u32), "ASMBitLastSetU32");
3249 BENCH(ASMBitLastSetU64(s_u32), "ASMBitLastSetU64");
3250 BENCH(ASMCountLeadingZerosU16(s_u16), "ASMCountLeadingZerosU16");
3251 BENCH(ASMCountLeadingZerosU32(s_u32), "ASMCountLeadingZerosU32");
3252 BENCH(ASMCountLeadingZerosU64(s_u64), "ASMCountLeadingZerosU64");
3253 BENCH(ASMCountTrailingZerosU16(s_u16), "ASMCountTrailingZerosU16");
3254 BENCH(ASMCountTrailingZerosU32(s_u32), "ASMCountTrailingZerosU32");
3255 BENCH(ASMCountTrailingZerosU64(s_u64), "ASMCountTrailingZerosU64");
3256
3257 /* The Darwin gcc does not like this ... */
3258#if !defined(RT_OS_DARWIN) && !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
3259 BENCH(s_u8 = ASMGetApicId(), "ASMGetApicId");
3260 BENCH(s_u32 = ASMGetApicIdExt0B(), "ASMGetApicIdExt0B");
3261 BENCH(s_u32 = ASMGetApicIdExt8000001E(), "ASMGetApicIdExt8000001E");
3262#endif
3263#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) || defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32))
3264 BENCH(s_u64 = ASMReadTSC(), "ASMReadTSC");
3265#endif
3266#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
3267 uint32_t uAux;
3268 if ( ASMHasCpuId()
3269 && RTX86IsValidExtRange(ASMCpuId_EAX(0x80000000))
3270 && (ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_RDTSCP) )
3271 {
3272 BENCH_TSC(ASMSerializeInstructionRdTscp(), "ASMSerializeInstructionRdTscp");
3273 BENCH(s_u64 = ASMReadTscWithAux(&uAux), "ASMReadTscWithAux");
3274 }
3275 union
3276 {
3277 uint64_t u64[2];
3278 RTIDTR Unaligned;
3279 struct
3280 {
3281 uint16_t abPadding[3];
3282 RTIDTR Aligned;
3283 } s;
3284 } uBuf;
3285 Assert(((uintptr_t)&uBuf.Unaligned.pIdt & (sizeof(uintptr_t) - 1)) != 0);
3286 BENCH(ASMGetIDTR(&uBuf.Unaligned), "ASMGetIDTR/unaligned");
3287 Assert(((uintptr_t)&uBuf.s.Aligned.pIdt & (sizeof(uintptr_t) - 1)) == 0);
3288 BENCH(ASMGetIDTR(&uBuf.s.Aligned), "ASMGetIDTR/aligned");
3289#endif
3290
3291#undef BENCH
3292}
3293
3294
3295int main(int argc, char **argv)
3296{
3297 RT_NOREF_PV(argc); RT_NOREF_PV(argv);
3298
3299 int rc = RTTestInitAndCreate("tstRTInlineAsm", &g_hTest);
3300 if (rc)
3301 return rc;
3302 RTTestBanner(g_hTest);
3303
3304 /*
3305 * Execute the tests.
3306 */
3307#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
3308 tstASMCpuId();
3309 //bruteForceCpuId();
3310#endif
3311#if 1
3312 tstASMAtomicRead();
3313 tstASMAtomicWrite();
3314 tstASMAtomicXchg();
3315 tstASMAtomicCmpXchg();
3316 tstASMAtomicCmpXchgEx();
3317
3318 tstASMAtomicAdd();
3319 tstASMAtomicDecInc();
3320 tstASMAtomicAndOrXor();
3321
3322 tstASMMemZeroPage();
3323 tstASMMemIsZeroPage(g_hTest);
3324 tstASMMemFirstMismatchingU8(g_hTest);
3325 tstASMMemZero32();
3326 tstASMMemFill32();
3327 tstASMProbe(g_hTest);
3328
3329 tstASMMisc();
3330
3331 tstASMBit();
3332
3333 tstASMMath();
3334
3335 tstASMByteSwap();
3336
3337 tstASMBench();
3338#endif
3339
3340 /*
3341 * Show the result.
3342 */
3343 return RTTestSummaryAndDestroy(g_hTest);
3344}
3345
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette