VirtualBox

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

Last change on this file since 109113 was 108718, checked in by vboxsync, 2 months ago

Runtime/testcase/tstRTInlineAsm.cpp: Enforce alignment of s_u128 at a 16 byte boundary as at least some versions of clang fail to do so automatically causing a crash in the testcase on darwin.amd64 at least

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

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