VirtualBox

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

Last change on this file since 79325 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 74.8 KB
Line 
1/* $Id: tstRTInlineAsm.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * IPRT Testcase - inline assembly.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/asm.h>
32#include <iprt/asm-math.h>
33
34/* See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44018. Only gcc version 4.4
35 * is affected. No harm for the VBox code: If the cpuid code compiles, it works
36 * fine. */
37#if defined(__GNUC__) && defined(RT_ARCH_X86) && defined(__PIC__)
38# if __GNUC__ == 4 && __GNUC_MINOR__ == 4
39# define GCC44_32BIT_PIC
40# endif
41#endif
42
43#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
44# include <iprt/asm-amd64-x86.h>
45# include <iprt/x86.h>
46#else
47# include <iprt/time.h>
48#endif
49#include <iprt/rand.h>
50#include <iprt/stream.h>
51#include <iprt/string.h>
52#include <iprt/param.h>
53#include <iprt/thread.h>
54#include <iprt/test.h>
55#include <iprt/time.h>
56
57
58
59/*********************************************************************************************************************************
60* Defined Constants And Macros *
61*********************************************************************************************************************************/
62#define CHECKVAL(val, expect, fmt) \
63 do \
64 { \
65 if ((val) != (expect)) \
66 { \
67 RTTestFailed(g_hTest, "%s, %d: " #val ": expected " fmt " got " fmt "\n", __FUNCTION__, __LINE__, (expect), (val)); \
68 } \
69 } while (0)
70
71#define CHECKOP(op, expect, fmt, type) \
72 do \
73 { \
74 type val = op; \
75 if (val != (type)(expect)) \
76 { \
77 RTTestFailed(g_hTest, "%s, %d: " #op ": expected " fmt " got " fmt "\n", __FUNCTION__, __LINE__, (type)(expect), val); \
78 } \
79 } while (0)
80
81/**
82 * Calls a worker function with different worker variable storage types.
83 */
84#define DO_SIMPLE_TEST(name, type) \
85 do \
86 { \
87 RTTestISub(#name); \
88 type StackVar; \
89 tst ## name ## Worker(&StackVar); \
90 \
91 type *pVar = (type *)RTTestGuardedAllocHead(g_hTest, sizeof(type)); \
92 RTTEST_CHECK_BREAK(g_hTest, pVar); \
93 tst ## name ## Worker(pVar); \
94 RTTestGuardedFree(g_hTest, pVar); \
95 \
96 pVar = (type *)RTTestGuardedAllocTail(g_hTest, sizeof(type)); \
97 RTTEST_CHECK_BREAK(g_hTest, pVar); \
98 tst ## name ## Worker(pVar); \
99 RTTestGuardedFree(g_hTest, pVar); \
100 } while (0)
101
102
103/*********************************************************************************************************************************
104* Global Variables *
105*********************************************************************************************************************************/
106/** The test instance. */
107static RTTEST g_hTest;
108
109
110
111#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
112
113const char *getCacheAss(unsigned u)
114{
115 if (u == 0)
116 return "res0 ";
117 if (u == 1)
118 return "direct";
119 if (u >= 256)
120 return "???";
121
122 char *pszRet;
123 RTStrAPrintf(&pszRet, "%d way", u); /* intentional leak! */
124 return pszRet;
125}
126
127
128const char *getL2CacheAss(unsigned u)
129{
130 switch (u)
131 {
132 case 0: return "off ";
133 case 1: return "direct";
134 case 2: return "2 way ";
135 case 3: return "res3 ";
136 case 4: return "4 way ";
137 case 5: return "res5 ";
138 case 6: return "8 way ";
139 case 7: return "res7 ";
140 case 8: return "16 way";
141 case 9: return "res9 ";
142 case 10: return "res10 ";
143 case 11: return "res11 ";
144 case 12: return "res12 ";
145 case 13: return "res13 ";
146 case 14: return "res14 ";
147 case 15: return "fully ";
148 default:
149 return "????";
150 }
151}
152
153
154/**
155 * Test and dump all possible info from the CPUID instruction.
156 *
157 * @remark Bits shared with the libc cpuid.c program. This all written by me, so no worries.
158 * @todo transform the dumping into a generic runtime function. We'll need it for logging!
159 */
160void tstASMCpuId(void)
161{
162 RTTestISub("ASMCpuId");
163
164 unsigned iBit;
165 struct
166 {
167 uint32_t uEBX, uEAX, uEDX, uECX;
168 } s;
169 if (!ASMHasCpuId())
170 {
171 RTTestIPrintf(RTTESTLVL_ALWAYS, "warning! CPU doesn't support CPUID\n");
172 return;
173 }
174
175 /*
176 * Try the 0 function and use that for checking the ASMCpuId_* variants.
177 */
178 ASMCpuId(0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
179
180 uint32_t u32;
181
182 u32 = ASMCpuId_EAX(0);
183 CHECKVAL(u32, s.uEAX, "%x");
184 u32 = ASMCpuId_EBX(0);
185 CHECKVAL(u32, s.uEBX, "%x");
186 u32 = ASMCpuId_ECX(0);
187 CHECKVAL(u32, s.uECX, "%x");
188 u32 = ASMCpuId_EDX(0);
189 CHECKVAL(u32, s.uEDX, "%x");
190
191 uint32_t uECX2 = s.uECX - 1;
192 uint32_t uEDX2 = s.uEDX - 1;
193 ASMCpuId_ECX_EDX(0, &uECX2, &uEDX2);
194 CHECKVAL(uECX2, s.uECX, "%x");
195 CHECKVAL(uEDX2, s.uEDX, "%x");
196
197 uint32_t uEAX2 = s.uEAX - 1;
198 uint32_t uEBX2 = s.uEBX - 1;
199 uECX2 = s.uECX - 1;
200 uEDX2 = s.uEDX - 1;
201 ASMCpuIdExSlow(0, 0, 0, 0, &uEAX2, &uEBX2, &uECX2, &uEDX2);
202 CHECKVAL(uEAX2, s.uEAX, "%x");
203 CHECKVAL(uEBX2, s.uEBX, "%x");
204 CHECKVAL(uECX2, s.uECX, "%x");
205 CHECKVAL(uEDX2, s.uEDX, "%x");
206
207 /*
208 * Done testing, dump the information.
209 */
210 RTTestIPrintf(RTTESTLVL_ALWAYS, "CPUID Dump\n");
211 ASMCpuId(0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
212 const uint32_t cFunctions = s.uEAX;
213
214 /* raw dump */
215 RTTestIPrintf(RTTESTLVL_ALWAYS,
216 "\n"
217 " RAW Standard CPUIDs\n"
218 "Function eax ebx ecx edx\n");
219 for (unsigned iStd = 0; iStd <= cFunctions + 3; iStd++)
220 {
221 ASMCpuId_Idx_ECX(iStd, 0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
222 RTTestIPrintf(RTTESTLVL_ALWAYS, "%08x %08x %08x %08x %08x%s\n",
223 iStd, s.uEAX, s.uEBX, s.uECX, s.uEDX, iStd <= cFunctions ? "" : "*");
224
225 /* Some leafs output depend on the initial value of ECX.
226 * The same seems to apply to invalid standard functions */
227 if (iStd > cFunctions)
228 continue;
229 if (iStd == 0x04) /* Deterministic Cache Parameters Leaf */
230 for (uint32_t uECX = 1; s.uEAX & 0x1f; uECX++)
231 {
232 ASMCpuId_Idx_ECX(iStd, uECX, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
233 RTTestIPrintf(RTTESTLVL_ALWAYS, " [%02x] %08x %08x %08x %08x\n", uECX, s.uEAX, s.uEBX, s.uECX, s.uEDX);
234 RTTESTI_CHECK_BREAK(uECX < 128);
235 }
236 else if (iStd == 0x07) /* Structured Extended Feature Flags */
237 {
238 uint32_t uMax = s.uEAX;
239 for (uint32_t uECX = 1; uECX < uMax; uECX++)
240 {
241 ASMCpuId_Idx_ECX(iStd, uECX, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
242 RTTestIPrintf(RTTESTLVL_ALWAYS, " [%02x] %08x %08x %08x %08x\n", uECX, s.uEAX, s.uEBX, s.uECX, s.uEDX);
243 RTTESTI_CHECK_BREAK(uECX < 128);
244 }
245 }
246 else if (iStd == 0x0b) /* Extended Topology Enumeration Leafs */
247 for (uint32_t uECX = 1; (s.uEAX & 0x1f) && (s.uEBX & 0xffff); uECX++)
248 {
249 ASMCpuId_Idx_ECX(iStd, uECX, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
250 RTTestIPrintf(RTTESTLVL_ALWAYS, " [%02x] %08x %08x %08x %08x\n", uECX, s.uEAX, s.uEBX, s.uECX, s.uEDX);
251 RTTESTI_CHECK_BREAK(uECX < 128);
252 }
253 else if (iStd == 0x0d) /* Extended State Enumeration Leafs */
254 for (uint32_t uECX = 1; s.uEAX != 0 || s.uEBX != 0 || s.uECX != 0 || s.uEDX != 0; uECX++)
255 {
256 ASMCpuId_Idx_ECX(iStd, uECX, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
257 RTTestIPrintf(RTTESTLVL_ALWAYS, " [%02x] %08x %08x %08x %08x\n", uECX, s.uEAX, s.uEBX, s.uECX, s.uEDX);
258 RTTESTI_CHECK_BREAK(uECX < 128);
259 }
260 else if ( iStd == 0x0f /* Platform quality of service monitoring (PQM) */
261 || iStd == 0x10 /* Platform quality of service enforcement (PQE) */
262 || iStd == 0x12 /* SGX Enumeration */
263 || iStd == 0x14 /* Processor Trace Enumeration */
264 || iStd == 0x17 /* SoC Vendor Attribute Enumeration */
265 || iStd == 0x18 /* Deterministic Address Translation Parameters */)
266 {
267 /** @todo */
268 }
269 else
270 {
271 u32 = ASMCpuId_EAX(iStd);
272 CHECKVAL(u32, s.uEAX, "%x");
273
274 uint32_t u32EbxMask = UINT32_MAX;
275 if (iStd == 1)
276 u32EbxMask = UINT32_C(0x00ffffff); /* Omit the local apic ID in case we're rescheduled. */
277 u32 = ASMCpuId_EBX(iStd);
278 CHECKVAL(u32 & u32EbxMask, s.uEBX & u32EbxMask, "%x");
279
280 u32 = ASMCpuId_ECX(iStd);
281 CHECKVAL(u32, s.uECX, "%x");
282 u32 = ASMCpuId_EDX(iStd);
283 CHECKVAL(u32, s.uEDX, "%x");
284
285 uECX2 = s.uECX - 1;
286 uEDX2 = s.uEDX - 1;
287 ASMCpuId_ECX_EDX(iStd, &uECX2, &uEDX2);
288 CHECKVAL(uECX2, s.uECX, "%x");
289 CHECKVAL(uEDX2, s.uEDX, "%x");
290
291 uEAX2 = s.uEAX - 1;
292 uEBX2 = s.uEBX - 1;
293 uECX2 = s.uECX - 1;
294 uEDX2 = s.uEDX - 1;
295 ASMCpuId(iStd, &uEAX2, &uEBX2, &uECX2, &uEDX2);
296 CHECKVAL(uEAX2, s.uEAX, "%x");
297 CHECKVAL(uEBX2 & u32EbxMask, s.uEBX & u32EbxMask, "%x");
298 CHECKVAL(uECX2, s.uECX, "%x");
299 CHECKVAL(uEDX2, s.uEDX, "%x");
300 }
301 }
302
303 /*
304 * Understandable output
305 */
306 ASMCpuId(0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
307 RTTestIPrintf(RTTESTLVL_ALWAYS,
308 "Name: %.04s%.04s%.04s\n"
309 "Support: 0-%u\n",
310 &s.uEBX, &s.uEDX, &s.uECX, s.uEAX);
311 bool const fIntel = ASMIsIntelCpuEx(s.uEBX, s.uECX, s.uEDX);
312
313 /*
314 * Get Features.
315 */
316 if (cFunctions >= 1)
317 {
318 static const char * const s_apszTypes[4] = { "primary", "overdrive", "MP", "reserved" };
319 ASMCpuId(1, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
320 RTTestIPrintf(RTTESTLVL_ALWAYS,
321 "Family: %#x \tExtended: %#x \tEffective: %#x\n"
322 "Model: %#x \tExtended: %#x \tEffective: %#x\n"
323 "Stepping: %d\n"
324 "Type: %d (%s)\n"
325 "APIC ID: %#04x\n"
326 "Logical CPUs: %d\n"
327 "CLFLUSH Size: %d\n"
328 "Brand ID: %#04x\n",
329 (s.uEAX >> 8) & 0xf, (s.uEAX >> 20) & 0x7f, ASMGetCpuFamily(s.uEAX),
330 (s.uEAX >> 4) & 0xf, (s.uEAX >> 16) & 0x0f, ASMGetCpuModel(s.uEAX, fIntel),
331 ASMGetCpuStepping(s.uEAX),
332 (s.uEAX >> 12) & 0x3, s_apszTypes[(s.uEAX >> 12) & 0x3],
333 (s.uEBX >> 24) & 0xff,
334 (s.uEBX >> 16) & 0xff,
335 (s.uEBX >> 8) & 0xff,
336 (s.uEBX >> 0) & 0xff);
337
338 RTTestIPrintf(RTTESTLVL_ALWAYS, "Features EDX: ");
339 if (s.uEDX & RT_BIT(0)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FPU");
340 if (s.uEDX & RT_BIT(1)) RTTestIPrintf(RTTESTLVL_ALWAYS, " VME");
341 if (s.uEDX & RT_BIT(2)) RTTestIPrintf(RTTESTLVL_ALWAYS, " DE");
342 if (s.uEDX & RT_BIT(3)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PSE");
343 if (s.uEDX & RT_BIT(4)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TSC");
344 if (s.uEDX & RT_BIT(5)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MSR");
345 if (s.uEDX & RT_BIT(6)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PAE");
346 if (s.uEDX & RT_BIT(7)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MCE");
347 if (s.uEDX & RT_BIT(8)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CX8");
348 if (s.uEDX & RT_BIT(9)) RTTestIPrintf(RTTESTLVL_ALWAYS, " APIC");
349 if (s.uEDX & RT_BIT(10)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 10");
350 if (s.uEDX & RT_BIT(11)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SEP");
351 if (s.uEDX & RT_BIT(12)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MTRR");
352 if (s.uEDX & RT_BIT(13)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PGE");
353 if (s.uEDX & RT_BIT(14)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MCA");
354 if (s.uEDX & RT_BIT(15)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CMOV");
355 if (s.uEDX & RT_BIT(16)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PAT");
356 if (s.uEDX & RT_BIT(17)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PSE36");
357 if (s.uEDX & RT_BIT(18)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PSN");
358 if (s.uEDX & RT_BIT(19)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CLFSH");
359 if (s.uEDX & RT_BIT(20)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 20");
360 if (s.uEDX & RT_BIT(21)) RTTestIPrintf(RTTESTLVL_ALWAYS, " DS");
361 if (s.uEDX & RT_BIT(22)) RTTestIPrintf(RTTESTLVL_ALWAYS, " ACPI");
362 if (s.uEDX & RT_BIT(23)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MMX");
363 if (s.uEDX & RT_BIT(24)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FXSR");
364 if (s.uEDX & RT_BIT(25)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SSE");
365 if (s.uEDX & RT_BIT(26)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SSE2");
366 if (s.uEDX & RT_BIT(27)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SS");
367 if (s.uEDX & RT_BIT(28)) RTTestIPrintf(RTTESTLVL_ALWAYS, " HTT");
368 if (s.uEDX & RT_BIT(29)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 29");
369 if (s.uEDX & RT_BIT(30)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 30");
370 if (s.uEDX & RT_BIT(31)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 31");
371 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
372
373 /** @todo check intel docs. */
374 RTTestIPrintf(RTTESTLVL_ALWAYS, "Features ECX: ");
375 if (s.uECX & RT_BIT(0)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SSE3");
376 for (iBit = 1; iBit < 13; iBit++)
377 if (s.uECX & RT_BIT(iBit))
378 RTTestIPrintf(RTTESTLVL_ALWAYS, " %d", iBit);
379 if (s.uECX & RT_BIT(13)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CX16");
380 for (iBit = 14; iBit < 32; iBit++)
381 if (s.uECX & RT_BIT(iBit))
382 RTTestIPrintf(RTTESTLVL_ALWAYS, " %d", iBit);
383 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
384 }
385
386 /*
387 * Extended.
388 * Implemented after AMD specs.
389 */
390 /** @todo check out the intel specs. */
391 ASMCpuId(0x80000000, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
392 if (!s.uEAX && !s.uEBX && !s.uECX && !s.uEDX)
393 {
394 RTTestIPrintf(RTTESTLVL_ALWAYS, "No extended CPUID info? Check the manual on how to detect this...\n");
395 return;
396 }
397 const uint32_t cExtFunctions = s.uEAX | 0x80000000;
398
399 /* raw dump */
400 RTTestIPrintf(RTTESTLVL_ALWAYS,
401 "\n"
402 " RAW Extended CPUIDs\n"
403 "Function eax ebx ecx edx\n");
404 for (unsigned iExt = 0x80000000; iExt <= cExtFunctions + 3; iExt++)
405 {
406 ASMCpuId(iExt, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
407 RTTestIPrintf(RTTESTLVL_ALWAYS, "%08x %08x %08x %08x %08x%s\n",
408 iExt, s.uEAX, s.uEBX, s.uECX, s.uEDX, iExt <= cExtFunctions ? "" : "*");
409
410 if (iExt > cExtFunctions)
411 continue; /* Invalid extended functions seems change the value if ECX changes */
412 if (iExt == 0x8000001d)
413 continue; /* Takes cache level in ecx. */
414
415 u32 = ASMCpuId_EAX(iExt);
416 CHECKVAL(u32, s.uEAX, "%x");
417 u32 = ASMCpuId_EBX(iExt);
418 CHECKVAL(u32, s.uEBX, "%x");
419 u32 = ASMCpuId_ECX(iExt);
420 CHECKVAL(u32, s.uECX, "%x");
421 u32 = ASMCpuId_EDX(iExt);
422 CHECKVAL(u32, s.uEDX, "%x");
423
424 uECX2 = s.uECX - 1;
425 uEDX2 = s.uEDX - 1;
426 ASMCpuId_ECX_EDX(iExt, &uECX2, &uEDX2);
427 CHECKVAL(uECX2, s.uECX, "%x");
428 CHECKVAL(uEDX2, s.uEDX, "%x");
429
430 uEAX2 = s.uEAX - 1;
431 uEBX2 = s.uEBX - 1;
432 uECX2 = s.uECX - 1;
433 uEDX2 = s.uEDX - 1;
434 ASMCpuId(iExt, &uEAX2, &uEBX2, &uECX2, &uEDX2);
435 CHECKVAL(uEAX2, s.uEAX, "%x");
436 CHECKVAL(uEBX2, s.uEBX, "%x");
437 CHECKVAL(uECX2, s.uECX, "%x");
438 CHECKVAL(uEDX2, s.uEDX, "%x");
439 }
440
441 /*
442 * Understandable output
443 */
444 ASMCpuId(0x80000000, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
445 RTTestIPrintf(RTTESTLVL_ALWAYS,
446 "Ext Name: %.4s%.4s%.4s\n"
447 "Ext Supports: 0x80000000-%#010x\n",
448 &s.uEBX, &s.uEDX, &s.uECX, s.uEAX);
449
450 if (cExtFunctions >= 0x80000001)
451 {
452 ASMCpuId(0x80000001, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
453 RTTestIPrintf(RTTESTLVL_ALWAYS,
454 "Family: %#x \tExtended: %#x \tEffective: %#x\n"
455 "Model: %#x \tExtended: %#x \tEffective: %#x\n"
456 "Stepping: %d\n"
457 "Brand ID: %#05x\n",
458 (s.uEAX >> 8) & 0xf, (s.uEAX >> 20) & 0x7f, ASMGetCpuFamily(s.uEAX),
459 (s.uEAX >> 4) & 0xf, (s.uEAX >> 16) & 0x0f, ASMGetCpuModel(s.uEAX, fIntel),
460 ASMGetCpuStepping(s.uEAX),
461 s.uEBX & 0xfff);
462
463 RTTestIPrintf(RTTESTLVL_ALWAYS, "Features EDX: ");
464 if (s.uEDX & RT_BIT(0)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FPU");
465 if (s.uEDX & RT_BIT(1)) RTTestIPrintf(RTTESTLVL_ALWAYS, " VME");
466 if (s.uEDX & RT_BIT(2)) RTTestIPrintf(RTTESTLVL_ALWAYS, " DE");
467 if (s.uEDX & RT_BIT(3)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PSE");
468 if (s.uEDX & RT_BIT(4)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TSC");
469 if (s.uEDX & RT_BIT(5)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MSR");
470 if (s.uEDX & RT_BIT(6)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PAE");
471 if (s.uEDX & RT_BIT(7)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MCE");
472 if (s.uEDX & RT_BIT(8)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CMPXCHG8B");
473 if (s.uEDX & RT_BIT(9)) RTTestIPrintf(RTTESTLVL_ALWAYS, " APIC");
474 if (s.uEDX & RT_BIT(10)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 10");
475 if (s.uEDX & RT_BIT(11)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SysCallSysRet");
476 if (s.uEDX & RT_BIT(12)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MTRR");
477 if (s.uEDX & RT_BIT(13)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PGE");
478 if (s.uEDX & RT_BIT(14)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MCA");
479 if (s.uEDX & RT_BIT(15)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CMOV");
480 if (s.uEDX & RT_BIT(16)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PAT");
481 if (s.uEDX & RT_BIT(17)) RTTestIPrintf(RTTESTLVL_ALWAYS, " PSE36");
482 if (s.uEDX & RT_BIT(18)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 18");
483 if (s.uEDX & RT_BIT(19)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 19");
484 if (s.uEDX & RT_BIT(20)) RTTestIPrintf(RTTESTLVL_ALWAYS, " NX");
485 if (s.uEDX & RT_BIT(21)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 21");
486 if (s.uEDX & RT_BIT(22)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MmxExt");
487 if (s.uEDX & RT_BIT(23)) RTTestIPrintf(RTTESTLVL_ALWAYS, " MMX");
488 if (s.uEDX & RT_BIT(24)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FXSR");
489 if (s.uEDX & RT_BIT(25)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FastFXSR");
490 if (s.uEDX & RT_BIT(26)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 26");
491 if (s.uEDX & RT_BIT(27)) RTTestIPrintf(RTTESTLVL_ALWAYS, " RDTSCP");
492 if (s.uEDX & RT_BIT(28)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 28");
493 if (s.uEDX & RT_BIT(29)) RTTestIPrintf(RTTESTLVL_ALWAYS, " LongMode");
494 if (s.uEDX & RT_BIT(30)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 3DNowExt");
495 if (s.uEDX & RT_BIT(31)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 3DNow");
496 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
497
498 RTTestIPrintf(RTTESTLVL_ALWAYS, "Features ECX: ");
499 if (s.uECX & RT_BIT(0)) RTTestIPrintf(RTTESTLVL_ALWAYS, " LahfSahf");
500 if (s.uECX & RT_BIT(1)) RTTestIPrintf(RTTESTLVL_ALWAYS, " CmpLegacy");
501 if (s.uECX & RT_BIT(2)) RTTestIPrintf(RTTESTLVL_ALWAYS, " SVM");
502 if (s.uECX & RT_BIT(3)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 3");
503 if (s.uECX & RT_BIT(4)) RTTestIPrintf(RTTESTLVL_ALWAYS, " AltMovCr8");
504 for (iBit = 5; iBit < 32; iBit++)
505 if (s.uECX & RT_BIT(iBit))
506 RTTestIPrintf(RTTESTLVL_ALWAYS, " %d", iBit);
507 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
508 }
509
510 char szString[4*4*3+1] = {0};
511 if (cExtFunctions >= 0x80000002)
512 ASMCpuId(0x80000002, &szString[0 + 0], &szString[0 + 4], &szString[0 + 8], &szString[0 + 12]);
513 if (cExtFunctions >= 0x80000003)
514 ASMCpuId(0x80000003, &szString[16 + 0], &szString[16 + 4], &szString[16 + 8], &szString[16 + 12]);
515 if (cExtFunctions >= 0x80000004)
516 ASMCpuId(0x80000004, &szString[32 + 0], &szString[32 + 4], &szString[32 + 8], &szString[32 + 12]);
517 if (cExtFunctions >= 0x80000002)
518 RTTestIPrintf(RTTESTLVL_ALWAYS, "Full Name: %s\n", szString);
519
520 if (cExtFunctions >= 0x80000005)
521 {
522 ASMCpuId(0x80000005, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
523 RTTestIPrintf(RTTESTLVL_ALWAYS,
524 "TLB 2/4M Instr/Uni: %s %3d entries\n"
525 "TLB 2/4M Data: %s %3d entries\n",
526 getCacheAss((s.uEAX >> 8) & 0xff), (s.uEAX >> 0) & 0xff,
527 getCacheAss((s.uEAX >> 24) & 0xff), (s.uEAX >> 16) & 0xff);
528 RTTestIPrintf(RTTESTLVL_ALWAYS,
529 "TLB 4K Instr/Uni: %s %3d entries\n"
530 "TLB 4K Data: %s %3d entries\n",
531 getCacheAss((s.uEBX >> 8) & 0xff), (s.uEBX >> 0) & 0xff,
532 getCacheAss((s.uEBX >> 24) & 0xff), (s.uEBX >> 16) & 0xff);
533 RTTestIPrintf(RTTESTLVL_ALWAYS,
534 "L1 Instr Cache Line Size: %d bytes\n"
535 "L1 Instr Cache Lines Per Tag: %d\n"
536 "L1 Instr Cache Associativity: %s\n"
537 "L1 Instr Cache Size: %d KB\n",
538 (s.uEDX >> 0) & 0xff,
539 (s.uEDX >> 8) & 0xff,
540 getCacheAss((s.uEDX >> 16) & 0xff),
541 (s.uEDX >> 24) & 0xff);
542 RTTestIPrintf(RTTESTLVL_ALWAYS,
543 "L1 Data Cache Line Size: %d bytes\n"
544 "L1 Data Cache Lines Per Tag: %d\n"
545 "L1 Data Cache Associativity: %s\n"
546 "L1 Data Cache Size: %d KB\n",
547 (s.uECX >> 0) & 0xff,
548 (s.uECX >> 8) & 0xff,
549 getCacheAss((s.uECX >> 16) & 0xff),
550 (s.uECX >> 24) & 0xff);
551 }
552
553 if (cExtFunctions >= 0x80000006)
554 {
555 ASMCpuId(0x80000006, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
556 RTTestIPrintf(RTTESTLVL_ALWAYS,
557 "L2 TLB 2/4M Instr/Uni: %s %4d entries\n"
558 "L2 TLB 2/4M Data: %s %4d entries\n",
559 getL2CacheAss((s.uEAX >> 12) & 0xf), (s.uEAX >> 0) & 0xfff,
560 getL2CacheAss((s.uEAX >> 28) & 0xf), (s.uEAX >> 16) & 0xfff);
561 RTTestIPrintf(RTTESTLVL_ALWAYS,
562 "L2 TLB 4K Instr/Uni: %s %4d entries\n"
563 "L2 TLB 4K Data: %s %4d entries\n",
564 getL2CacheAss((s.uEBX >> 12) & 0xf), (s.uEBX >> 0) & 0xfff,
565 getL2CacheAss((s.uEBX >> 28) & 0xf), (s.uEBX >> 16) & 0xfff);
566 RTTestIPrintf(RTTESTLVL_ALWAYS,
567 "L2 Cache Line Size: %d bytes\n"
568 "L2 Cache Lines Per Tag: %d\n"
569 "L2 Cache Associativity: %s\n"
570 "L2 Cache Size: %d KB\n",
571 (s.uEDX >> 0) & 0xff,
572 (s.uEDX >> 8) & 0xf,
573 getL2CacheAss((s.uEDX >> 12) & 0xf),
574 (s.uEDX >> 16) & 0xffff);
575 }
576
577 if (cExtFunctions >= 0x80000007)
578 {
579 ASMCpuId(0x80000007, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
580 RTTestIPrintf(RTTESTLVL_ALWAYS, "APM Features: ");
581 if (s.uEDX & RT_BIT(0)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TS");
582 if (s.uEDX & RT_BIT(1)) RTTestIPrintf(RTTESTLVL_ALWAYS, " FID");
583 if (s.uEDX & RT_BIT(2)) RTTestIPrintf(RTTESTLVL_ALWAYS, " VID");
584 if (s.uEDX & RT_BIT(3)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TTP");
585 if (s.uEDX & RT_BIT(4)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TM");
586 if (s.uEDX & RT_BIT(5)) RTTestIPrintf(RTTESTLVL_ALWAYS, " STC");
587 if (s.uEDX & RT_BIT(6)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 6");
588 if (s.uEDX & RT_BIT(7)) RTTestIPrintf(RTTESTLVL_ALWAYS, " 7");
589 if (s.uEDX & RT_BIT(8)) RTTestIPrintf(RTTESTLVL_ALWAYS, " TscInvariant");
590 for (iBit = 9; iBit < 32; iBit++)
591 if (s.uEDX & RT_BIT(iBit))
592 RTTestIPrintf(RTTESTLVL_ALWAYS, " %d", iBit);
593 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
594 }
595
596 if (cExtFunctions >= 0x80000008)
597 {
598 ASMCpuId(0x80000008, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
599 RTTestIPrintf(RTTESTLVL_ALWAYS,
600 "Physical Address Width: %d bits\n"
601 "Virtual Address Width: %d bits\n"
602 "Guest Physical Address Width: %d bits\n",
603 (s.uEAX >> 0) & 0xff,
604 (s.uEAX >> 8) & 0xff,
605 (s.uEAX >> 16) & 0xff);
606 RTTestIPrintf(RTTESTLVL_ALWAYS,
607 "Physical Core Count: %d\n",
608 ((s.uECX >> 0) & 0xff) + 1);
609 if ((s.uECX >> 12) & 0xf)
610 RTTestIPrintf(RTTESTLVL_ALWAYS, "ApicIdCoreIdSize: %d bits\n", (s.uECX >> 12) & 0xf);
611 }
612
613 if (cExtFunctions >= 0x8000000a)
614 {
615 ASMCpuId(0x8000000a, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
616 RTTestIPrintf(RTTESTLVL_ALWAYS,
617 "SVM Revision: %d (%#x)\n"
618 "Number of Address Space IDs: %d (%#x)\n",
619 s.uEAX & 0xff, s.uEAX & 0xff,
620 s.uEBX, s.uEBX);
621 }
622}
623
624# if 0
625static void bruteForceCpuId(void)
626{
627 RTTestISub("brute force CPUID leafs");
628 uint32_t auPrevValues[4] = { 0, 0, 0, 0};
629 uint32_t uLeaf = 0;
630 do
631 {
632 uint32_t auValues[4];
633 ASMCpuIdExSlow(uLeaf, 0, 0, 0, &auValues[0], &auValues[1], &auValues[2], &auValues[3]);
634 if ( (auValues[0] != auPrevValues[0] && auValues[0] != uLeaf)
635 || (auValues[1] != auPrevValues[1] && auValues[1] != 0)
636 || (auValues[2] != auPrevValues[2] && auValues[2] != 0)
637 || (auValues[3] != auPrevValues[3] && auValues[3] != 0)
638 || (uLeaf & (UINT32_C(0x08000000) - UINT32_C(1))) == 0)
639 {
640 RTTestIPrintf(RTTESTLVL_ALWAYS,
641 "%08x: %08x %08x %08x %08x\n", uLeaf,
642 auValues[0], auValues[1], auValues[2], auValues[3]);
643 }
644 auPrevValues[0] = auValues[0];
645 auPrevValues[1] = auValues[1];
646 auPrevValues[2] = auValues[2];
647 auPrevValues[3] = auValues[3];
648
649 //uint32_t uSubLeaf = 0;
650 //do
651 //{
652 //
653 //
654 //} while (false);
655 } while (uLeaf++ < UINT32_MAX);
656}
657# endif
658
659#endif /* AMD64 || X86 */
660
661DECLINLINE(void) tstASMAtomicXchgU8Worker(uint8_t volatile *pu8)
662{
663 *pu8 = 0;
664 CHECKOP(ASMAtomicXchgU8(pu8, 1), 0, "%#x", uint8_t);
665 CHECKVAL(*pu8, 1, "%#x");
666
667 CHECKOP(ASMAtomicXchgU8(pu8, 0), 1, "%#x", uint8_t);
668 CHECKVAL(*pu8, 0, "%#x");
669
670 CHECKOP(ASMAtomicXchgU8(pu8, UINT8_C(0xff)), 0, "%#x", uint8_t);
671 CHECKVAL(*pu8, 0xff, "%#x");
672
673 CHECKOP(ASMAtomicXchgU8(pu8, UINT8_C(0x87)), UINT8_C(0xff), "%#x", uint8_t);
674 CHECKVAL(*pu8, 0x87, "%#x");
675}
676
677
678static void tstASMAtomicXchgU8(void)
679{
680 DO_SIMPLE_TEST(ASMAtomicXchgU8, uint8_t);
681}
682
683
684DECLINLINE(void) tstASMAtomicXchgU16Worker(uint16_t volatile *pu16)
685{
686 *pu16 = 0;
687
688 CHECKOP(ASMAtomicXchgU16(pu16, 1), 0, "%#x", uint16_t);
689 CHECKVAL(*pu16, 1, "%#x");
690
691 CHECKOP(ASMAtomicXchgU16(pu16, 0), 1, "%#x", uint16_t);
692 CHECKVAL(*pu16, 0, "%#x");
693
694 CHECKOP(ASMAtomicXchgU16(pu16, 0xffff), 0, "%#x", uint16_t);
695 CHECKVAL(*pu16, 0xffff, "%#x");
696
697 CHECKOP(ASMAtomicXchgU16(pu16, 0x8765), 0xffff, "%#x", uint16_t);
698 CHECKVAL(*pu16, 0x8765, "%#x");
699}
700
701
702static void tstASMAtomicXchgU16(void)
703{
704 DO_SIMPLE_TEST(ASMAtomicXchgU16, uint16_t);
705}
706
707
708DECLINLINE(void) tstASMAtomicXchgU32Worker(uint32_t volatile *pu32)
709{
710 *pu32 = 0;
711
712 CHECKOP(ASMAtomicXchgU32(pu32, 1), 0, "%#x", uint32_t);
713 CHECKVAL(*pu32, 1, "%#x");
714
715 CHECKOP(ASMAtomicXchgU32(pu32, 0), 1, "%#x", uint32_t);
716 CHECKVAL(*pu32, 0, "%#x");
717
718 CHECKOP(ASMAtomicXchgU32(pu32, ~UINT32_C(0)), 0, "%#x", uint32_t);
719 CHECKVAL(*pu32, ~UINT32_C(0), "%#x");
720
721 CHECKOP(ASMAtomicXchgU32(pu32, 0x87654321), ~UINT32_C(0), "%#x", uint32_t);
722 CHECKVAL(*pu32, 0x87654321, "%#x");
723}
724
725
726static void tstASMAtomicXchgU32(void)
727{
728 DO_SIMPLE_TEST(ASMAtomicXchgU32, uint32_t);
729}
730
731
732DECLINLINE(void) tstASMAtomicXchgU64Worker(uint64_t volatile *pu64)
733{
734 *pu64 = 0;
735
736 CHECKOP(ASMAtomicXchgU64(pu64, 1), UINT64_C(0), "%#llx", uint64_t);
737 CHECKVAL(*pu64, UINT64_C(1), "%#llx");
738
739 CHECKOP(ASMAtomicXchgU64(pu64, 0), UINT64_C(1), "%#llx", uint64_t);
740 CHECKVAL(*pu64, UINT64_C(0), "%#llx");
741
742 CHECKOP(ASMAtomicXchgU64(pu64, ~UINT64_C(0)), UINT64_C(0), "%#llx", uint64_t);
743 CHECKVAL(*pu64, ~UINT64_C(0), "%#llx");
744
745 CHECKOP(ASMAtomicXchgU64(pu64, UINT64_C(0xfedcba0987654321)), ~UINT64_C(0), "%#llx", uint64_t);
746 CHECKVAL(*pu64, UINT64_C(0xfedcba0987654321), "%#llx");
747}
748
749
750static void tstASMAtomicXchgU64(void)
751{
752 DO_SIMPLE_TEST(ASMAtomicXchgU64, uint64_t);
753}
754
755
756DECLINLINE(void) tstASMAtomicXchgPtrWorker(void * volatile *ppv)
757{
758 *ppv = NULL;
759
760 CHECKOP(ASMAtomicXchgPtr(ppv, (void *)(~(uintptr_t)0)), NULL, "%p", void *);
761 CHECKVAL(*ppv, (void *)(~(uintptr_t)0), "%p");
762
763 CHECKOP(ASMAtomicXchgPtr(ppv, (void *)(uintptr_t)0x87654321), (void *)(~(uintptr_t)0), "%p", void *);
764 CHECKVAL(*ppv, (void *)(uintptr_t)0x87654321, "%p");
765
766 CHECKOP(ASMAtomicXchgPtr(ppv, NULL), (void *)(uintptr_t)0x87654321, "%p", void *);
767 CHECKVAL(*ppv, NULL, "%p");
768}
769
770
771static void tstASMAtomicXchgPtr(void)
772{
773 DO_SIMPLE_TEST(ASMAtomicXchgPtr, void *);
774}
775
776
777DECLINLINE(void) tstASMAtomicCmpXchgU8Worker(uint8_t volatile *pu8)
778{
779 *pu8 = 0xff;
780
781 CHECKOP(ASMAtomicCmpXchgU8(pu8, 0, 0), false, "%d", bool);
782 CHECKVAL(*pu8, 0xff, "%x");
783
784 CHECKOP(ASMAtomicCmpXchgU8(pu8, 0, 0xff), true, "%d", bool);
785 CHECKVAL(*pu8, 0, "%x");
786
787 CHECKOP(ASMAtomicCmpXchgU8(pu8, 0x79, 0xff), false, "%d", bool);
788 CHECKVAL(*pu8, 0, "%x");
789
790 CHECKOP(ASMAtomicCmpXchgU8(pu8, 0x97, 0), true, "%d", bool);
791 CHECKVAL(*pu8, 0x97, "%x");
792}
793
794
795static void tstASMAtomicCmpXchgU8(void)
796{
797 DO_SIMPLE_TEST(ASMAtomicCmpXchgU8, uint8_t);
798}
799
800
801DECLINLINE(void) tstASMAtomicCmpXchgU32Worker(uint32_t volatile *pu32)
802{
803 *pu32 = UINT32_C(0xffffffff);
804
805 CHECKOP(ASMAtomicCmpXchgU32(pu32, 0, 0), false, "%d", bool);
806 CHECKVAL(*pu32, UINT32_C(0xffffffff), "%x");
807
808 CHECKOP(ASMAtomicCmpXchgU32(pu32, 0, UINT32_C(0xffffffff)), true, "%d", bool);
809 CHECKVAL(*pu32, 0, "%x");
810
811 CHECKOP(ASMAtomicCmpXchgU32(pu32, UINT32_C(0x8008efd), UINT32_C(0xffffffff)), false, "%d", bool);
812 CHECKVAL(*pu32, 0, "%x");
813
814 CHECKOP(ASMAtomicCmpXchgU32(pu32, UINT32_C(0x8008efd), 0), true, "%d", bool);
815 CHECKVAL(*pu32, UINT32_C(0x8008efd), "%x");
816}
817
818
819static void tstASMAtomicCmpXchgU32(void)
820{
821 DO_SIMPLE_TEST(ASMAtomicCmpXchgU32, uint32_t);
822}
823
824
825
826DECLINLINE(void) tstASMAtomicCmpXchgU64Worker(uint64_t volatile *pu64)
827{
828 *pu64 = UINT64_C(0xffffffffffffff);
829
830 CHECKOP(ASMAtomicCmpXchgU64(pu64, 0, 0), false, "%d", bool);
831 CHECKVAL(*pu64, UINT64_C(0xffffffffffffff), "%#llx");
832
833 CHECKOP(ASMAtomicCmpXchgU64(pu64, 0, UINT64_C(0xffffffffffffff)), true, "%d", bool);
834 CHECKVAL(*pu64, 0, "%x");
835
836 CHECKOP(ASMAtomicCmpXchgU64(pu64, UINT64_C(0x80040008008efd), UINT64_C(0xffffffff)), false, "%d", bool);
837 CHECKVAL(*pu64, 0, "%x");
838
839 CHECKOP(ASMAtomicCmpXchgU64(pu64, UINT64_C(0x80040008008efd), UINT64_C(0xffffffff00000000)), false, "%d", bool);
840 CHECKVAL(*pu64, 0, "%x");
841
842 CHECKOP(ASMAtomicCmpXchgU64(pu64, UINT64_C(0x80040008008efd), 0), true, "%d", bool);
843 CHECKVAL(*pu64, UINT64_C(0x80040008008efd), "%#llx");
844}
845
846
847static void tstASMAtomicCmpXchgU64(void)
848{
849 DO_SIMPLE_TEST(ASMAtomicCmpXchgU64, uint64_t);
850}
851
852
853DECLINLINE(void) tstASMAtomicCmpXchgExU32Worker(uint32_t volatile *pu32)
854{
855 *pu32 = UINT32_C(0xffffffff);
856 uint32_t u32Old = UINT32_C(0x80005111);
857
858 CHECKOP(ASMAtomicCmpXchgExU32(pu32, 0, 0, &u32Old), false, "%d", bool);
859 CHECKVAL(*pu32, UINT32_C(0xffffffff), "%x");
860 CHECKVAL(u32Old, UINT32_C(0xffffffff), "%x");
861
862 CHECKOP(ASMAtomicCmpXchgExU32(pu32, 0, UINT32_C(0xffffffff), &u32Old), true, "%d", bool);
863 CHECKVAL(*pu32, 0, "%x");
864 CHECKVAL(u32Old, UINT32_C(0xffffffff), "%x");
865
866 CHECKOP(ASMAtomicCmpXchgExU32(pu32, UINT32_C(0x8008efd), UINT32_C(0xffffffff), &u32Old), false, "%d", bool);
867 CHECKVAL(*pu32, 0, "%x");
868 CHECKVAL(u32Old, 0, "%x");
869
870 CHECKOP(ASMAtomicCmpXchgExU32(pu32, UINT32_C(0x8008efd), 0, &u32Old), true, "%d", bool);
871 CHECKVAL(*pu32, UINT32_C(0x8008efd), "%x");
872 CHECKVAL(u32Old, 0, "%x");
873
874 CHECKOP(ASMAtomicCmpXchgExU32(pu32, 0, UINT32_C(0x8008efd), &u32Old), true, "%d", bool);
875 CHECKVAL(*pu32, 0, "%x");
876 CHECKVAL(u32Old, UINT32_C(0x8008efd), "%x");
877}
878
879
880static void tstASMAtomicCmpXchgExU32(void)
881{
882 DO_SIMPLE_TEST(ASMAtomicCmpXchgExU32, uint32_t);
883}
884
885
886DECLINLINE(void) tstASMAtomicCmpXchgExU64Worker(uint64_t volatile *pu64)
887{
888 *pu64 = UINT64_C(0xffffffffffffffff);
889 uint64_t u64Old = UINT64_C(0x8000000051111111);
890
891 CHECKOP(ASMAtomicCmpXchgExU64(pu64, 0, 0, &u64Old), false, "%d", bool);
892 CHECKVAL(*pu64, UINT64_C(0xffffffffffffffff), "%llx");
893 CHECKVAL(u64Old, UINT64_C(0xffffffffffffffff), "%llx");
894
895 CHECKOP(ASMAtomicCmpXchgExU64(pu64, 0, UINT64_C(0xffffffffffffffff), &u64Old), true, "%d", bool);
896 CHECKVAL(*pu64, UINT64_C(0), "%llx");
897 CHECKVAL(u64Old, UINT64_C(0xffffffffffffffff), "%llx");
898
899 CHECKOP(ASMAtomicCmpXchgExU64(pu64, UINT64_C(0x80040008008efd), 0xffffffff, &u64Old), false, "%d", bool);
900 CHECKVAL(*pu64, UINT64_C(0), "%llx");
901 CHECKVAL(u64Old, UINT64_C(0), "%llx");
902
903 CHECKOP(ASMAtomicCmpXchgExU64(pu64, UINT64_C(0x80040008008efd), UINT64_C(0xffffffff00000000), &u64Old), false, "%d", bool);
904 CHECKVAL(*pu64, UINT64_C(0), "%llx");
905 CHECKVAL(u64Old, UINT64_C(0), "%llx");
906
907 CHECKOP(ASMAtomicCmpXchgExU64(pu64, UINT64_C(0x80040008008efd), 0, &u64Old), true, "%d", bool);
908 CHECKVAL(*pu64, UINT64_C(0x80040008008efd), "%llx");
909 CHECKVAL(u64Old, UINT64_C(0), "%llx");
910
911 CHECKOP(ASMAtomicCmpXchgExU64(pu64, 0, UINT64_C(0x80040008008efd), &u64Old), true, "%d", bool);
912 CHECKVAL(*pu64, UINT64_C(0), "%llx");
913 CHECKVAL(u64Old, UINT64_C(0x80040008008efd), "%llx");
914}
915
916
917static void tstASMAtomicCmpXchgExU64(void)
918{
919 DO_SIMPLE_TEST(ASMAtomicCmpXchgExU64, uint64_t);
920}
921
922
923DECLINLINE(void) tstASMAtomicReadU64Worker(uint64_t volatile *pu64)
924{
925 *pu64 = 0;
926
927 CHECKOP(ASMAtomicReadU64(pu64), UINT64_C(0), "%#llx", uint64_t);
928 CHECKVAL(*pu64, UINT64_C(0), "%#llx");
929
930 *pu64 = ~UINT64_C(0);
931 CHECKOP(ASMAtomicReadU64(pu64), ~UINT64_C(0), "%#llx", uint64_t);
932 CHECKVAL(*pu64, ~UINT64_C(0), "%#llx");
933
934 *pu64 = UINT64_C(0xfedcba0987654321);
935 CHECKOP(ASMAtomicReadU64(pu64), UINT64_C(0xfedcba0987654321), "%#llx", uint64_t);
936 CHECKVAL(*pu64, UINT64_C(0xfedcba0987654321), "%#llx");
937}
938
939
940static void tstASMAtomicReadU64(void)
941{
942 DO_SIMPLE_TEST(ASMAtomicReadU64, uint64_t);
943}
944
945
946DECLINLINE(void) tstASMAtomicUoReadU64Worker(uint64_t volatile *pu64)
947{
948 *pu64 = 0;
949
950 CHECKOP(ASMAtomicUoReadU64(pu64), UINT64_C(0), "%#llx", uint64_t);
951 CHECKVAL(*pu64, UINT64_C(0), "%#llx");
952
953 *pu64 = ~UINT64_C(0);
954 CHECKOP(ASMAtomicUoReadU64(pu64), ~UINT64_C(0), "%#llx", uint64_t);
955 CHECKVAL(*pu64, ~UINT64_C(0), "%#llx");
956
957 *pu64 = UINT64_C(0xfedcba0987654321);
958 CHECKOP(ASMAtomicUoReadU64(pu64), UINT64_C(0xfedcba0987654321), "%#llx", uint64_t);
959 CHECKVAL(*pu64, UINT64_C(0xfedcba0987654321), "%#llx");
960}
961
962
963static void tstASMAtomicUoReadU64(void)
964{
965 DO_SIMPLE_TEST(ASMAtomicUoReadU64, uint64_t);
966}
967
968
969DECLINLINE(void) tstASMAtomicAddS32Worker(int32_t *pi32)
970{
971 int32_t i32Rc;
972 *pi32 = 10;
973#define MYCHECK(op, rc, val) \
974 do { \
975 i32Rc = op; \
976 if (i32Rc != (rc)) \
977 RTTestFailed(g_hTest, "%s, %d: FAILURE: %s -> %d expected %d\n", __FUNCTION__, __LINE__, #op, i32Rc, rc); \
978 if (*pi32 != (val)) \
979 RTTestFailed(g_hTest, "%s, %d: FAILURE: %s => *pi32=%d expected %d\n", __FUNCTION__, __LINE__, #op, *pi32, val); \
980 } while (0)
981 MYCHECK(ASMAtomicAddS32(pi32, 1), 10, 11);
982 MYCHECK(ASMAtomicAddS32(pi32, -2), 11, 9);
983 MYCHECK(ASMAtomicAddS32(pi32, -9), 9, 0);
984 MYCHECK(ASMAtomicAddS32(pi32, -0x7fffffff), 0, -0x7fffffff);
985 MYCHECK(ASMAtomicAddS32(pi32, 0), -0x7fffffff, -0x7fffffff);
986 MYCHECK(ASMAtomicAddS32(pi32, 0x7fffffff), -0x7fffffff, 0);
987 MYCHECK(ASMAtomicAddS32(pi32, 0), 0, 0);
988#undef MYCHECK
989}
990
991
992static void tstASMAtomicAddS32(void)
993{
994 DO_SIMPLE_TEST(ASMAtomicAddS32, int32_t);
995}
996
997
998DECLINLINE(void) tstASMAtomicUoIncU32Worker(uint32_t volatile *pu32)
999{
1000 *pu32 = 0;
1001
1002 CHECKOP(ASMAtomicUoIncU32(pu32), UINT32_C(1), "%#x", uint32_t);
1003 CHECKVAL(*pu32, UINT32_C(1), "%#x");
1004
1005 *pu32 = ~UINT32_C(0);
1006 CHECKOP(ASMAtomicUoIncU32(pu32), 0, "%#x", uint32_t);
1007 CHECKVAL(*pu32, 0, "%#x");
1008
1009 *pu32 = UINT32_C(0x7fffffff);
1010 CHECKOP(ASMAtomicUoIncU32(pu32), UINT32_C(0x80000000), "%#x", uint32_t);
1011 CHECKVAL(*pu32, UINT32_C(0x80000000), "%#x");
1012}
1013
1014
1015static void tstASMAtomicUoIncU32(void)
1016{
1017 DO_SIMPLE_TEST(ASMAtomicUoIncU32, uint32_t);
1018}
1019
1020
1021DECLINLINE(void) tstASMAtomicUoDecU32Worker(uint32_t volatile *pu32)
1022{
1023 *pu32 = 0;
1024
1025 CHECKOP(ASMAtomicUoDecU32(pu32), ~UINT32_C(0), "%#x", uint32_t);
1026 CHECKVAL(*pu32, ~UINT32_C(0), "%#x");
1027
1028 *pu32 = ~UINT32_C(0);
1029 CHECKOP(ASMAtomicUoDecU32(pu32), UINT32_C(0xfffffffe), "%#x", uint32_t);
1030 CHECKVAL(*pu32, UINT32_C(0xfffffffe), "%#x");
1031
1032 *pu32 = UINT32_C(0x80000000);
1033 CHECKOP(ASMAtomicUoDecU32(pu32), UINT32_C(0x7fffffff), "%#x", uint32_t);
1034 CHECKVAL(*pu32, UINT32_C(0x7fffffff), "%#x");
1035}
1036
1037
1038static void tstASMAtomicUoDecU32(void)
1039{
1040 DO_SIMPLE_TEST(ASMAtomicUoDecU32, uint32_t);
1041}
1042
1043
1044DECLINLINE(void) tstASMAtomicAddS64Worker(int64_t volatile *pi64)
1045{
1046 int64_t i64Rc;
1047 *pi64 = 10;
1048#define MYCHECK(op, rc, val) \
1049 do { \
1050 i64Rc = op; \
1051 if (i64Rc != (rc)) \
1052 RTTestFailed(g_hTest, "%s, %d: FAILURE: %s -> %llx expected %llx\n", __FUNCTION__, __LINE__, #op, i64Rc, (int64_t)rc); \
1053 if (*pi64 != (val)) \
1054 RTTestFailed(g_hTest, "%s, %d: FAILURE: %s => *pi64=%llx expected %llx\n", __FUNCTION__, __LINE__, #op, *pi64, (int64_t)(val)); \
1055 } while (0)
1056 MYCHECK(ASMAtomicAddS64(pi64, 1), 10, 11);
1057 MYCHECK(ASMAtomicAddS64(pi64, -2), 11, 9);
1058 MYCHECK(ASMAtomicAddS64(pi64, -9), 9, 0);
1059 MYCHECK(ASMAtomicAddS64(pi64, -INT64_MAX), 0, -INT64_MAX);
1060 MYCHECK(ASMAtomicAddS64(pi64, 0), -INT64_MAX, -INT64_MAX);
1061 MYCHECK(ASMAtomicAddS64(pi64, -1), -INT64_MAX, INT64_MIN);
1062 MYCHECK(ASMAtomicAddS64(pi64, INT64_MAX), INT64_MIN, -1);
1063 MYCHECK(ASMAtomicAddS64(pi64, 1), -1, 0);
1064 MYCHECK(ASMAtomicAddS64(pi64, 0), 0, 0);
1065#undef MYCHECK
1066}
1067
1068
1069static void tstASMAtomicAddS64(void)
1070{
1071 DO_SIMPLE_TEST(ASMAtomicAddS64, int64_t);
1072}
1073
1074
1075DECLINLINE(void) tstASMAtomicDecIncS32Worker(int32_t volatile *pi32)
1076{
1077 int32_t i32Rc;
1078 *pi32 = 10;
1079#define MYCHECK(op, rc) \
1080 do { \
1081 i32Rc = op; \
1082 if (i32Rc != (rc)) \
1083 RTTestFailed(g_hTest, "%s, %d: FAILURE: %s -> %d expected %d\n", __FUNCTION__, __LINE__, #op, i32Rc, rc); \
1084 if (*pi32 != (rc)) \
1085 RTTestFailed(g_hTest, "%s, %d: FAILURE: %s => *pi32=%d expected %d\n", __FUNCTION__, __LINE__, #op, *pi32, rc); \
1086 } while (0)
1087 MYCHECK(ASMAtomicDecS32(pi32), 9);
1088 MYCHECK(ASMAtomicDecS32(pi32), 8);
1089 MYCHECK(ASMAtomicDecS32(pi32), 7);
1090 MYCHECK(ASMAtomicDecS32(pi32), 6);
1091 MYCHECK(ASMAtomicDecS32(pi32), 5);
1092 MYCHECK(ASMAtomicDecS32(pi32), 4);
1093 MYCHECK(ASMAtomicDecS32(pi32), 3);
1094 MYCHECK(ASMAtomicDecS32(pi32), 2);
1095 MYCHECK(ASMAtomicDecS32(pi32), 1);
1096 MYCHECK(ASMAtomicDecS32(pi32), 0);
1097 MYCHECK(ASMAtomicDecS32(pi32), -1);
1098 MYCHECK(ASMAtomicDecS32(pi32), -2);
1099 MYCHECK(ASMAtomicIncS32(pi32), -1);
1100 MYCHECK(ASMAtomicIncS32(pi32), 0);
1101 MYCHECK(ASMAtomicIncS32(pi32), 1);
1102 MYCHECK(ASMAtomicIncS32(pi32), 2);
1103 MYCHECK(ASMAtomicIncS32(pi32), 3);
1104 MYCHECK(ASMAtomicDecS32(pi32), 2);
1105 MYCHECK(ASMAtomicIncS32(pi32), 3);
1106 MYCHECK(ASMAtomicDecS32(pi32), 2);
1107 MYCHECK(ASMAtomicIncS32(pi32), 3);
1108#undef MYCHECK
1109}
1110
1111
1112static void tstASMAtomicDecIncS32(void)
1113{
1114 DO_SIMPLE_TEST(ASMAtomicDecIncS32, int32_t);
1115}
1116
1117
1118DECLINLINE(void) tstASMAtomicDecIncS64Worker(int64_t volatile *pi64)
1119{
1120 int64_t i64Rc;
1121 *pi64 = 10;
1122#define MYCHECK(op, rc) \
1123 do { \
1124 i64Rc = op; \
1125 if (i64Rc != (rc)) \
1126 RTTestFailed(g_hTest, "%s, %d: FAILURE: %s -> %lld expected %lld\n", __FUNCTION__, __LINE__, #op, i64Rc, rc); \
1127 if (*pi64 != (rc)) \
1128 RTTestFailed(g_hTest, "%s, %d: FAILURE: %s => *pi64=%lld expected %lld\n", __FUNCTION__, __LINE__, #op, *pi64, rc); \
1129 } while (0)
1130 MYCHECK(ASMAtomicDecS64(pi64), 9);
1131 MYCHECK(ASMAtomicDecS64(pi64), 8);
1132 MYCHECK(ASMAtomicDecS64(pi64), 7);
1133 MYCHECK(ASMAtomicDecS64(pi64), 6);
1134 MYCHECK(ASMAtomicDecS64(pi64), 5);
1135 MYCHECK(ASMAtomicDecS64(pi64), 4);
1136 MYCHECK(ASMAtomicDecS64(pi64), 3);
1137 MYCHECK(ASMAtomicDecS64(pi64), 2);
1138 MYCHECK(ASMAtomicDecS64(pi64), 1);
1139 MYCHECK(ASMAtomicDecS64(pi64), 0);
1140 MYCHECK(ASMAtomicDecS64(pi64), -1);
1141 MYCHECK(ASMAtomicDecS64(pi64), -2);
1142 MYCHECK(ASMAtomicIncS64(pi64), -1);
1143 MYCHECK(ASMAtomicIncS64(pi64), 0);
1144 MYCHECK(ASMAtomicIncS64(pi64), 1);
1145 MYCHECK(ASMAtomicIncS64(pi64), 2);
1146 MYCHECK(ASMAtomicIncS64(pi64), 3);
1147 MYCHECK(ASMAtomicDecS64(pi64), 2);
1148 MYCHECK(ASMAtomicIncS64(pi64), 3);
1149 MYCHECK(ASMAtomicDecS64(pi64), 2);
1150 MYCHECK(ASMAtomicIncS64(pi64), 3);
1151#undef MYCHECK
1152}
1153
1154
1155static void tstASMAtomicDecIncS64(void)
1156{
1157 DO_SIMPLE_TEST(ASMAtomicDecIncS64, int64_t);
1158}
1159
1160
1161DECLINLINE(void) tstASMAtomicAndOrU32Worker(uint32_t volatile *pu32)
1162{
1163 *pu32 = UINT32_C(0xffffffff);
1164
1165 ASMAtomicOrU32(pu32, UINT32_C(0xffffffff));
1166 CHECKVAL(*pu32, UINT32_C(0xffffffff), "%x");
1167
1168 ASMAtomicAndU32(pu32, UINT32_C(0xffffffff));
1169 CHECKVAL(*pu32, UINT32_C(0xffffffff), "%x");
1170
1171 ASMAtomicAndU32(pu32, UINT32_C(0x8f8f8f8f));
1172 CHECKVAL(*pu32, UINT32_C(0x8f8f8f8f), "%x");
1173
1174 ASMAtomicOrU32(pu32, UINT32_C(0x70707070));
1175 CHECKVAL(*pu32, UINT32_C(0xffffffff), "%x");
1176
1177 ASMAtomicAndU32(pu32, UINT32_C(1));
1178 CHECKVAL(*pu32, UINT32_C(1), "%x");
1179
1180 ASMAtomicOrU32(pu32, UINT32_C(0x80000000));
1181 CHECKVAL(*pu32, UINT32_C(0x80000001), "%x");
1182
1183 ASMAtomicAndU32(pu32, UINT32_C(0x80000000));
1184 CHECKVAL(*pu32, UINT32_C(0x80000000), "%x");
1185
1186 ASMAtomicAndU32(pu32, UINT32_C(0));
1187 CHECKVAL(*pu32, UINT32_C(0), "%x");
1188
1189 ASMAtomicOrU32(pu32, UINT32_C(0x42424242));
1190 CHECKVAL(*pu32, UINT32_C(0x42424242), "%x");
1191}
1192
1193
1194static void tstASMAtomicAndOrU32(void)
1195{
1196 DO_SIMPLE_TEST(ASMAtomicAndOrU32, uint32_t);
1197}
1198
1199
1200DECLINLINE(void) tstASMAtomicAndOrU64Worker(uint64_t volatile *pu64)
1201{
1202 *pu64 = UINT64_C(0xffffffff);
1203
1204 ASMAtomicOrU64(pu64, UINT64_C(0xffffffff));
1205 CHECKVAL(*pu64, UINT64_C(0xffffffff), "%x");
1206
1207 ASMAtomicAndU64(pu64, UINT64_C(0xffffffff));
1208 CHECKVAL(*pu64, UINT64_C(0xffffffff), "%x");
1209
1210 ASMAtomicAndU64(pu64, UINT64_C(0x8f8f8f8f));
1211 CHECKVAL(*pu64, UINT64_C(0x8f8f8f8f), "%x");
1212
1213 ASMAtomicOrU64(pu64, UINT64_C(0x70707070));
1214 CHECKVAL(*pu64, UINT64_C(0xffffffff), "%x");
1215
1216 ASMAtomicAndU64(pu64, UINT64_C(1));
1217 CHECKVAL(*pu64, UINT64_C(1), "%x");
1218
1219 ASMAtomicOrU64(pu64, UINT64_C(0x80000000));
1220 CHECKVAL(*pu64, UINT64_C(0x80000001), "%x");
1221
1222 ASMAtomicAndU64(pu64, UINT64_C(0x80000000));
1223 CHECKVAL(*pu64, UINT64_C(0x80000000), "%x");
1224
1225 ASMAtomicAndU64(pu64, UINT64_C(0));
1226 CHECKVAL(*pu64, UINT64_C(0), "%x");
1227
1228 ASMAtomicOrU64(pu64, UINT64_C(0x42424242));
1229 CHECKVAL(*pu64, UINT64_C(0x42424242), "%x");
1230
1231 // Same as above, but now 64-bit wide.
1232 ASMAtomicAndU64(pu64, UINT64_C(0));
1233 CHECKVAL(*pu64, UINT64_C(0), "%x");
1234
1235 ASMAtomicOrU64(pu64, UINT64_C(0xffffffffffffffff));
1236 CHECKVAL(*pu64, UINT64_C(0xffffffffffffffff), "%x");
1237
1238 ASMAtomicAndU64(pu64, UINT64_C(0xffffffffffffffff));
1239 CHECKVAL(*pu64, UINT64_C(0xffffffffffffffff), "%x");
1240
1241 ASMAtomicAndU64(pu64, UINT64_C(0x8f8f8f8f8f8f8f8f));
1242 CHECKVAL(*pu64, UINT64_C(0x8f8f8f8f8f8f8f8f), "%x");
1243
1244 ASMAtomicOrU64(pu64, UINT64_C(0x7070707070707070));
1245 CHECKVAL(*pu64, UINT64_C(0xffffffffffffffff), "%x");
1246
1247 ASMAtomicAndU64(pu64, UINT64_C(1));
1248 CHECKVAL(*pu64, UINT64_C(1), "%x");
1249
1250 ASMAtomicOrU64(pu64, UINT64_C(0x8000000000000000));
1251 CHECKVAL(*pu64, UINT64_C(0x8000000000000001), "%x");
1252
1253 ASMAtomicAndU64(pu64, UINT64_C(0x8000000000000000));
1254 CHECKVAL(*pu64, UINT64_C(0x8000000000000000), "%x");
1255
1256 ASMAtomicAndU64(pu64, UINT64_C(0));
1257 CHECKVAL(*pu64, UINT64_C(0), "%x");
1258
1259 ASMAtomicOrU64(pu64, UINT64_C(0x4242424242424242));
1260 CHECKVAL(*pu64, UINT64_C(0x4242424242424242), "%x");
1261}
1262
1263
1264static void tstASMAtomicAndOrU64(void)
1265{
1266 DO_SIMPLE_TEST(ASMAtomicAndOrU64, uint64_t);
1267}
1268
1269
1270DECLINLINE(void) tstASMAtomicUoAndOrU32Worker(uint32_t volatile *pu32)
1271{
1272 *pu32 = UINT32_C(0xffffffff);
1273
1274 ASMAtomicUoOrU32(pu32, UINT32_C(0xffffffff));
1275 CHECKVAL(*pu32, UINT32_C(0xffffffff), "%#x");
1276
1277 ASMAtomicUoAndU32(pu32, UINT32_C(0xffffffff));
1278 CHECKVAL(*pu32, UINT32_C(0xffffffff), "%#x");
1279
1280 ASMAtomicUoAndU32(pu32, UINT32_C(0x8f8f8f8f));
1281 CHECKVAL(*pu32, UINT32_C(0x8f8f8f8f), "%#x");
1282
1283 ASMAtomicUoOrU32(pu32, UINT32_C(0x70707070));
1284 CHECKVAL(*pu32, UINT32_C(0xffffffff), "%#x");
1285
1286 ASMAtomicUoAndU32(pu32, UINT32_C(1));
1287 CHECKVAL(*pu32, UINT32_C(1), "%#x");
1288
1289 ASMAtomicUoOrU32(pu32, UINT32_C(0x80000000));
1290 CHECKVAL(*pu32, UINT32_C(0x80000001), "%#x");
1291
1292 ASMAtomicUoAndU32(pu32, UINT32_C(0x80000000));
1293 CHECKVAL(*pu32, UINT32_C(0x80000000), "%#x");
1294
1295 ASMAtomicUoAndU32(pu32, UINT32_C(0));
1296 CHECKVAL(*pu32, UINT32_C(0), "%#x");
1297
1298 ASMAtomicUoOrU32(pu32, UINT32_C(0x42424242));
1299 CHECKVAL(*pu32, UINT32_C(0x42424242), "%#x");
1300}
1301
1302
1303static void tstASMAtomicUoAndOrU32(void)
1304{
1305 DO_SIMPLE_TEST(ASMAtomicUoAndOrU32, uint32_t);
1306}
1307
1308
1309typedef struct
1310{
1311 uint8_t ab[PAGE_SIZE];
1312} TSTPAGE;
1313
1314
1315DECLINLINE(void) tstASMMemZeroPageWorker(TSTPAGE *pPage)
1316{
1317 for (unsigned j = 0; j < 16; j++)
1318 {
1319 memset(pPage, 0x11 * j, sizeof(*pPage));
1320 ASMMemZeroPage(pPage);
1321 for (unsigned i = 0; i < sizeof(pPage->ab); i++)
1322 if (pPage->ab[i])
1323 RTTestFailed(g_hTest, "ASMMemZeroPage didn't clear byte at offset %#x!\n", i);
1324 }
1325}
1326
1327
1328static void tstASMMemZeroPage(void)
1329{
1330 DO_SIMPLE_TEST(ASMMemZeroPage, TSTPAGE);
1331}
1332
1333
1334void tstASMMemIsZeroPage(RTTEST hTest)
1335{
1336 RTTestSub(hTest, "ASMMemIsZeroPage");
1337
1338 void *pvPage1 = RTTestGuardedAllocHead(hTest, PAGE_SIZE);
1339 void *pvPage2 = RTTestGuardedAllocTail(hTest, PAGE_SIZE);
1340 RTTESTI_CHECK_RETV(pvPage1 && pvPage2);
1341
1342 memset(pvPage1, 0, PAGE_SIZE);
1343 memset(pvPage2, 0, PAGE_SIZE);
1344 RTTESTI_CHECK(ASMMemIsZeroPage(pvPage1));
1345 RTTESTI_CHECK(ASMMemIsZeroPage(pvPage2));
1346
1347 memset(pvPage1, 0xff, PAGE_SIZE);
1348 memset(pvPage2, 0xff, PAGE_SIZE);
1349 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage1));
1350 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage2));
1351
1352 memset(pvPage1, 0, PAGE_SIZE);
1353 memset(pvPage2, 0, PAGE_SIZE);
1354 for (unsigned off = 0; off < PAGE_SIZE; off++)
1355 {
1356 ((uint8_t *)pvPage1)[off] = 1;
1357 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage1));
1358 ((uint8_t *)pvPage1)[off] = 0;
1359
1360 ((uint8_t *)pvPage2)[off] = 0x80;
1361 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage2));
1362 ((uint8_t *)pvPage2)[off] = 0;
1363 }
1364
1365 RTTestSubDone(hTest);
1366}
1367
1368
1369void tstASMMemFirstMismatchingU8(RTTEST hTest)
1370{
1371 RTTestSub(hTest, "ASMMemFirstMismatchingU8");
1372
1373 uint8_t *pbPage1 = (uint8_t *)RTTestGuardedAllocHead(hTest, PAGE_SIZE);
1374 uint8_t *pbPage2 = (uint8_t *)RTTestGuardedAllocTail(hTest, PAGE_SIZE);
1375 RTTESTI_CHECK_RETV(pbPage1 && pbPage2);
1376
1377 memset(pbPage1, 0, PAGE_SIZE);
1378 memset(pbPage2, 0, PAGE_SIZE);
1379 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, PAGE_SIZE, 0) == NULL);
1380 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, PAGE_SIZE, 0) == NULL);
1381 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, PAGE_SIZE, 1) == pbPage1);
1382 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, PAGE_SIZE, 1) == pbPage2);
1383 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, PAGE_SIZE, 0x87) == pbPage1);
1384 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, PAGE_SIZE, 0x87) == pbPage2);
1385 RTTESTI_CHECK(ASMMemIsZero(pbPage1, PAGE_SIZE));
1386 RTTESTI_CHECK(ASMMemIsZero(pbPage2, PAGE_SIZE));
1387 RTTESTI_CHECK(ASMMemIsAllU8(pbPage1, PAGE_SIZE, 0));
1388 RTTESTI_CHECK(ASMMemIsAllU8(pbPage2, PAGE_SIZE, 0));
1389 RTTESTI_CHECK(!ASMMemIsAllU8(pbPage1, PAGE_SIZE, 0x34));
1390 RTTESTI_CHECK(!ASMMemIsAllU8(pbPage2, PAGE_SIZE, 0x88));
1391 unsigned cbSub = 32;
1392 while (cbSub-- > 0)
1393 {
1394 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage1[PAGE_SIZE - cbSub], cbSub, 0) == NULL);
1395 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage2[PAGE_SIZE - cbSub], cbSub, 0) == NULL);
1396 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, cbSub, 0) == NULL);
1397 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, cbSub, 0) == NULL);
1398
1399 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage1[PAGE_SIZE - cbSub], cbSub, 0x34) == &pbPage1[PAGE_SIZE - cbSub] || !cbSub);
1400 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage2[PAGE_SIZE - cbSub], cbSub, 0x99) == &pbPage2[PAGE_SIZE - cbSub] || !cbSub);
1401 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, cbSub, 0x42) == pbPage1 || !cbSub);
1402 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, cbSub, 0x88) == pbPage2 || !cbSub);
1403 }
1404
1405 memset(pbPage1, 0xff, PAGE_SIZE);
1406 memset(pbPage2, 0xff, PAGE_SIZE);
1407 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, PAGE_SIZE, 0xff) == NULL);
1408 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, PAGE_SIZE, 0xff) == NULL);
1409 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, PAGE_SIZE, 0xfe) == pbPage1);
1410 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, PAGE_SIZE, 0xfe) == pbPage2);
1411 RTTESTI_CHECK(!ASMMemIsZero(pbPage1, PAGE_SIZE));
1412 RTTESTI_CHECK(!ASMMemIsZero(pbPage2, PAGE_SIZE));
1413 RTTESTI_CHECK(ASMMemIsAllU8(pbPage1, PAGE_SIZE, 0xff));
1414 RTTESTI_CHECK(ASMMemIsAllU8(pbPage2, PAGE_SIZE, 0xff));
1415 RTTESTI_CHECK(!ASMMemIsAllU8(pbPage1, PAGE_SIZE, 0));
1416 RTTESTI_CHECK(!ASMMemIsAllU8(pbPage2, PAGE_SIZE, 0));
1417 cbSub = 32;
1418 while (cbSub-- > 0)
1419 {
1420 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage1[PAGE_SIZE - cbSub], cbSub, 0xff) == NULL);
1421 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage2[PAGE_SIZE - cbSub], cbSub, 0xff) == NULL);
1422 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, cbSub, 0xff) == NULL);
1423 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, cbSub, 0xff) == NULL);
1424
1425 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage1[PAGE_SIZE - cbSub], cbSub, 0xfe) == &pbPage1[PAGE_SIZE - cbSub] || !cbSub);
1426 RTTESTI_CHECK(ASMMemFirstMismatchingU8(&pbPage2[PAGE_SIZE - cbSub], cbSub, 0xfe) == &pbPage2[PAGE_SIZE - cbSub] || !cbSub);
1427 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage1, cbSub, 0xfe) == pbPage1 || !cbSub);
1428 RTTESTI_CHECK(ASMMemFirstMismatchingU8(pbPage2, cbSub, 0xfe) == pbPage2 || !cbSub);
1429 }
1430
1431
1432 /*
1433 * Various alignments and sizes.
1434 */
1435 uint8_t const bFiller1 = 0x00;
1436 uint8_t const bFiller2 = 0xf6;
1437 size_t const cbBuf = 128;
1438 uint8_t *pbBuf1 = pbPage1;
1439 uint8_t *pbBuf2 = &pbPage2[PAGE_SIZE - cbBuf]; /* Put it up against the tail guard */
1440 memset(pbPage1, ~bFiller1, PAGE_SIZE);
1441 memset(pbPage2, ~bFiller2, PAGE_SIZE);
1442 memset(pbBuf1, bFiller1, cbBuf);
1443 memset(pbBuf2, bFiller2, cbBuf);
1444 for (size_t offNonZero = 0; offNonZero < cbBuf; offNonZero++)
1445 {
1446 uint8_t bRand = (uint8_t)RTRandU32();
1447 pbBuf1[offNonZero] = bRand | 1;
1448 pbBuf2[offNonZero] = (0x80 | bRand) ^ 0xf6;
1449
1450 for (size_t offStart = 0; offStart < 32; offStart++)
1451 {
1452 size_t const cbMax = cbBuf - offStart;
1453 for (size_t cb = 0; cb < cbMax; cb++)
1454 {
1455 size_t const offEnd = offStart + cb;
1456 uint8_t bSaved1, bSaved2;
1457 if (offEnd < PAGE_SIZE)
1458 {
1459 bSaved1 = pbBuf1[offEnd];
1460 bSaved2 = pbBuf2[offEnd];
1461 pbBuf1[offEnd] = 0xff;
1462 pbBuf2[offEnd] = 0xff;
1463 }
1464#ifdef _MSC_VER /* simple stupid compiler warnings */
1465 else
1466 bSaved1 = bSaved2 = 0;
1467#endif
1468
1469 uint8_t *pbRet = (uint8_t *)ASMMemFirstMismatchingU8(pbBuf1 + offStart, cb, bFiller1);
1470 RTTESTI_CHECK(offNonZero - offStart < cb ? pbRet == &pbBuf1[offNonZero] : pbRet == NULL);
1471
1472 pbRet = (uint8_t *)ASMMemFirstMismatchingU8(pbBuf2 + offStart, cb, bFiller2);
1473 RTTESTI_CHECK(offNonZero - offStart < cb ? pbRet == &pbBuf2[offNonZero] : pbRet == NULL);
1474
1475 if (offEnd < PAGE_SIZE)
1476 {
1477 pbBuf1[offEnd] = bSaved1;
1478 pbBuf2[offEnd] = bSaved2;
1479 }
1480 }
1481 }
1482
1483 pbBuf1[offNonZero] = 0;
1484 pbBuf2[offNonZero] = 0xf6;
1485 }
1486
1487 RTTestSubDone(hTest);
1488}
1489
1490
1491void tstASMMemZero32(void)
1492{
1493 RTTestSub(g_hTest, "ASMMemFill32");
1494
1495 struct
1496 {
1497 uint64_t u64Magic1;
1498 uint8_t abPage[PAGE_SIZE - 32];
1499 uint64_t u64Magic2;
1500 } Buf1, Buf2, Buf3;
1501
1502 Buf1.u64Magic1 = UINT64_C(0xffffffffffffffff);
1503 memset(Buf1.abPage, 0x55, sizeof(Buf1.abPage));
1504 Buf1.u64Magic2 = UINT64_C(0xffffffffffffffff);
1505 Buf2.u64Magic1 = UINT64_C(0xffffffffffffffff);
1506 memset(Buf2.abPage, 0x77, sizeof(Buf2.abPage));
1507 Buf2.u64Magic2 = UINT64_C(0xffffffffffffffff);
1508 Buf3.u64Magic1 = UINT64_C(0xffffffffffffffff);
1509 memset(Buf3.abPage, 0x99, sizeof(Buf3.abPage));
1510 Buf3.u64Magic2 = UINT64_C(0xffffffffffffffff);
1511 ASMMemZero32(Buf1.abPage, sizeof(Buf1.abPage));
1512 ASMMemZero32(Buf2.abPage, sizeof(Buf2.abPage));
1513 ASMMemZero32(Buf3.abPage, sizeof(Buf3.abPage));
1514 if ( Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
1515 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
1516 || Buf2.u64Magic1 != UINT64_C(0xffffffffffffffff)
1517 || Buf2.u64Magic2 != UINT64_C(0xffffffffffffffff)
1518 || Buf3.u64Magic1 != UINT64_C(0xffffffffffffffff)
1519 || Buf3.u64Magic2 != UINT64_C(0xffffffffffffffff))
1520 {
1521 RTTestFailed(g_hTest, "ASMMemZero32 violated one/both magic(s)!\n");
1522 }
1523 for (unsigned i = 0; i < RT_ELEMENTS(Buf1.abPage); i++)
1524 if (Buf1.abPage[i])
1525 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear byte at offset %#x!\n", i);
1526 for (unsigned i = 0; i < RT_ELEMENTS(Buf2.abPage); i++)
1527 if (Buf2.abPage[i])
1528 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear byte at offset %#x!\n", i);
1529 for (unsigned i = 0; i < RT_ELEMENTS(Buf3.abPage); i++)
1530 if (Buf3.abPage[i])
1531 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear byte at offset %#x!\n", i);
1532}
1533
1534
1535void tstASMMemFill32(void)
1536{
1537 RTTestSub(g_hTest, "ASMMemFill32");
1538
1539 struct
1540 {
1541 uint64_t u64Magic1;
1542 uint32_t au32Page[PAGE_SIZE / 4];
1543 uint64_t u64Magic2;
1544 } Buf1;
1545 struct
1546 {
1547 uint64_t u64Magic1;
1548 uint32_t au32Page[(PAGE_SIZE / 4) - 3];
1549 uint64_t u64Magic2;
1550 } Buf2;
1551 struct
1552 {
1553 uint64_t u64Magic1;
1554 uint32_t au32Page[(PAGE_SIZE / 4) - 1];
1555 uint64_t u64Magic2;
1556 } Buf3;
1557
1558 Buf1.u64Magic1 = UINT64_C(0xffffffffffffffff);
1559 memset(Buf1.au32Page, 0x55, sizeof(Buf1.au32Page));
1560 Buf1.u64Magic2 = UINT64_C(0xffffffffffffffff);
1561 Buf2.u64Magic1 = UINT64_C(0xffffffffffffffff);
1562 memset(Buf2.au32Page, 0x77, sizeof(Buf2.au32Page));
1563 Buf2.u64Magic2 = UINT64_C(0xffffffffffffffff);
1564 Buf3.u64Magic1 = UINT64_C(0xffffffffffffffff);
1565 memset(Buf3.au32Page, 0x99, sizeof(Buf3.au32Page));
1566 Buf3.u64Magic2 = UINT64_C(0xffffffffffffffff);
1567 ASMMemFill32(Buf1.au32Page, sizeof(Buf1.au32Page), 0xdeadbeef);
1568 ASMMemFill32(Buf2.au32Page, sizeof(Buf2.au32Page), 0xcafeff01);
1569 ASMMemFill32(Buf3.au32Page, sizeof(Buf3.au32Page), 0xf00dd00f);
1570 if ( Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
1571 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
1572 || Buf2.u64Magic1 != UINT64_C(0xffffffffffffffff)
1573 || Buf2.u64Magic2 != UINT64_C(0xffffffffffffffff)
1574 || Buf3.u64Magic1 != UINT64_C(0xffffffffffffffff)
1575 || Buf3.u64Magic2 != UINT64_C(0xffffffffffffffff))
1576 RTTestFailed(g_hTest, "ASMMemFill32 violated one/both magic(s)!\n");
1577 for (unsigned i = 0; i < RT_ELEMENTS(Buf1.au32Page); i++)
1578 if (Buf1.au32Page[i] != 0xdeadbeef)
1579 RTTestFailed(g_hTest, "ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf1.au32Page[i], 0xdeadbeef);
1580 for (unsigned i = 0; i < RT_ELEMENTS(Buf2.au32Page); i++)
1581 if (Buf2.au32Page[i] != 0xcafeff01)
1582 RTTestFailed(g_hTest, "ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf2.au32Page[i], 0xcafeff01);
1583 for (unsigned i = 0; i < RT_ELEMENTS(Buf3.au32Page); i++)
1584 if (Buf3.au32Page[i] != 0xf00dd00f)
1585 RTTestFailed(g_hTest, "ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf3.au32Page[i], 0xf00dd00f);
1586}
1587
1588
1589
1590void tstASMMath(void)
1591{
1592 RTTestSub(g_hTest, "Math");
1593
1594 uint64_t u64 = ASMMult2xU32RetU64(UINT32_C(0x80000000), UINT32_C(0x10000000));
1595 CHECKVAL(u64, UINT64_C(0x0800000000000000), "%#018RX64");
1596
1597 uint32_t u32 = ASMDivU64ByU32RetU32(UINT64_C(0x0800000000000000), UINT32_C(0x10000000));
1598 CHECKVAL(u32, UINT32_C(0x80000000), "%#010RX32");
1599
1600 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x00000001), UINT32_C(0x00000001), UINT32_C(0x00000001));
1601 CHECKVAL(u32, UINT32_C(0x00000001), "%#018RX32");
1602 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x10000000), UINT32_C(0x80000000), UINT32_C(0x20000000));
1603 CHECKVAL(u32, UINT32_C(0x40000000), "%#018RX32");
1604 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x76543210), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1605 CHECKVAL(u32, UINT32_C(0x76543210), "%#018RX32");
1606 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0xffffffff), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1607 CHECKVAL(u32, UINT32_C(0xffffffff), "%#018RX32");
1608 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0xffffffff), UINT32_C(0xfffffff0), UINT32_C(0xffffffff));
1609 CHECKVAL(u32, UINT32_C(0xfffffff0), "%#018RX32");
1610 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x10359583), UINT32_C(0x58734981), UINT32_C(0xf8694045));
1611 CHECKVAL(u32, UINT32_C(0x05c584ce), "%#018RX32");
1612 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x10359583), UINT32_C(0xf8694045), UINT32_C(0x58734981));
1613 CHECKVAL(u32, UINT32_C(0x2d860795), "%#018RX32");
1614
1615#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
1616 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x0000000000000001), UINT32_C(0x00000001), UINT32_C(0x00000001));
1617 CHECKVAL(u64, UINT64_C(0x0000000000000001), "%#018RX64");
1618 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x0000000100000000), UINT32_C(0x80000000), UINT32_C(0x00000002));
1619 CHECKVAL(u64, UINT64_C(0x4000000000000000), "%#018RX64");
1620 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xfedcba9876543210), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1621 CHECKVAL(u64, UINT64_C(0xfedcba9876543210), "%#018RX64");
1622 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xffffffffffffffff), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1623 CHECKVAL(u64, UINT64_C(0xffffffffffffffff), "%#018RX64");
1624 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xffffffffffffffff), UINT32_C(0xfffffff0), UINT32_C(0xffffffff));
1625 CHECKVAL(u64, UINT64_C(0xfffffff0fffffff0), "%#018RX64");
1626 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x3415934810359583), UINT32_C(0x58734981), UINT32_C(0xf8694045));
1627 CHECKVAL(u64, UINT64_C(0x128b9c3d43184763), "%#018RX64");
1628 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x3415934810359583), UINT32_C(0xf8694045), UINT32_C(0x58734981));
1629 CHECKVAL(u64, UINT64_C(0x924719355cd35a27), "%#018RX64");
1630
1631# if 0 /* bird: question is whether this should trap or not:
1632 *
1633 * frank: Of course it must trap:
1634 *
1635 * 0xfffffff8 * 0x77d7daf8 = 0x77d7daf441412840
1636 *
1637 * During the following division, the quotient must fit into a 32-bit register.
1638 * Therefore the smallest valid divisor is
1639 *
1640 * (0x77d7daf441412840 >> 32) + 1 = 0x77d7daf5
1641 *
1642 * which is definitely greater than 0x3b9aca00.
1643 *
1644 * bird: No, the C version does *not* crash. So, the question is whether there's any
1645 * code depending on it not crashing.
1646 *
1647 * Of course the assembly versions of the code crash right now for the reasons you've
1648 * given, but the 32-bit MSC version does not crash.
1649 *
1650 * frank: The C version does not crash but delivers incorrect results for this case.
1651 * The reason is
1652 *
1653 * u.s.Hi = (unsigned long)(u64Hi / u32C);
1654 *
1655 * Here the division is actually 64-bit by 64-bit but the 64-bit result is truncated
1656 * to 32 bit. If using this (optimized and fast) function we should just be sure that
1657 * the operands are in a valid range.
1658 */
1659 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xfffffff8c65d6731), UINT32_C(0x77d7daf8), UINT32_C(0x3b9aca00));
1660 CHECKVAL(u64, UINT64_C(0x02b8f9a2aa74e3dc), "%#018RX64");
1661# endif
1662#endif /* AMD64 || X86 */
1663
1664 u32 = ASMModU64ByU32RetU32(UINT64_C(0x0ffffff8c65d6731), UINT32_C(0x77d7daf8));
1665 CHECKVAL(u32, UINT32_C(0x3B642451), "%#010RX32");
1666
1667 int32_t i32;
1668 i32 = ASMModS64ByS32RetS32(INT64_C(-11), INT32_C(-2));
1669 CHECKVAL(i32, INT32_C(-1), "%010RI32");
1670 i32 = ASMModS64ByS32RetS32(INT64_C(-11), INT32_C(2));
1671 CHECKVAL(i32, INT32_C(-1), "%010RI32");
1672 i32 = ASMModS64ByS32RetS32(INT64_C(11), INT32_C(-2));
1673 CHECKVAL(i32, INT32_C(1), "%010RI32");
1674
1675 i32 = ASMModS64ByS32RetS32(INT64_C(92233720368547758), INT32_C(2147483647));
1676 CHECKVAL(i32, INT32_C(2104533974), "%010RI32");
1677 i32 = ASMModS64ByS32RetS32(INT64_C(-92233720368547758), INT32_C(2147483647));
1678 CHECKVAL(i32, INT32_C(-2104533974), "%010RI32");
1679}
1680
1681
1682void tstASMByteSwap(void)
1683{
1684 RTTestSub(g_hTest, "ASMByteSwap*");
1685
1686 uint64_t u64In = UINT64_C(0x0011223344556677);
1687 uint64_t u64Out = ASMByteSwapU64(u64In);
1688 CHECKVAL(u64In, UINT64_C(0x0011223344556677), "%#018RX64");
1689 CHECKVAL(u64Out, UINT64_C(0x7766554433221100), "%#018RX64");
1690 u64Out = ASMByteSwapU64(u64Out);
1691 CHECKVAL(u64Out, u64In, "%#018RX64");
1692 u64In = UINT64_C(0x0123456789abcdef);
1693 u64Out = ASMByteSwapU64(u64In);
1694 CHECKVAL(u64In, UINT64_C(0x0123456789abcdef), "%#018RX64");
1695 CHECKVAL(u64Out, UINT64_C(0xefcdab8967452301), "%#018RX64");
1696 u64Out = ASMByteSwapU64(u64Out);
1697 CHECKVAL(u64Out, u64In, "%#018RX64");
1698 u64In = 0;
1699 u64Out = ASMByteSwapU64(u64In);
1700 CHECKVAL(u64Out, u64In, "%#018RX64");
1701 u64In = UINT64_MAX;
1702 u64Out = ASMByteSwapU64(u64In);
1703 CHECKVAL(u64Out, u64In, "%#018RX64");
1704
1705 uint32_t u32In = UINT32_C(0x00112233);
1706 uint32_t u32Out = ASMByteSwapU32(u32In);
1707 CHECKVAL(u32In, UINT32_C(0x00112233), "%#010RX32");
1708 CHECKVAL(u32Out, UINT32_C(0x33221100), "%#010RX32");
1709 u32Out = ASMByteSwapU32(u32Out);
1710 CHECKVAL(u32Out, u32In, "%#010RX32");
1711 u32In = UINT32_C(0x12345678);
1712 u32Out = ASMByteSwapU32(u32In);
1713 CHECKVAL(u32In, UINT32_C(0x12345678), "%#010RX32");
1714 CHECKVAL(u32Out, UINT32_C(0x78563412), "%#010RX32");
1715 u32Out = ASMByteSwapU32(u32Out);
1716 CHECKVAL(u32Out, u32In, "%#010RX32");
1717 u32In = 0;
1718 u32Out = ASMByteSwapU32(u32In);
1719 CHECKVAL(u32Out, u32In, "%#010RX32");
1720 u32In = UINT32_MAX;
1721 u32Out = ASMByteSwapU32(u32In);
1722 CHECKVAL(u32Out, u32In, "%#010RX32");
1723
1724 uint16_t u16In = UINT16_C(0x0011);
1725 uint16_t u16Out = ASMByteSwapU16(u16In);
1726 CHECKVAL(u16In, UINT16_C(0x0011), "%#06RX16");
1727 CHECKVAL(u16Out, UINT16_C(0x1100), "%#06RX16");
1728 u16Out = ASMByteSwapU16(u16Out);
1729 CHECKVAL(u16Out, u16In, "%#06RX16");
1730 u16In = UINT16_C(0x1234);
1731 u16Out = ASMByteSwapU16(u16In);
1732 CHECKVAL(u16In, UINT16_C(0x1234), "%#06RX16");
1733 CHECKVAL(u16Out, UINT16_C(0x3412), "%#06RX16");
1734 u16Out = ASMByteSwapU16(u16Out);
1735 CHECKVAL(u16Out, u16In, "%#06RX16");
1736 u16In = 0;
1737 u16Out = ASMByteSwapU16(u16In);
1738 CHECKVAL(u16Out, u16In, "%#06RX16");
1739 u16In = UINT16_MAX;
1740 u16Out = ASMByteSwapU16(u16In);
1741 CHECKVAL(u16Out, u16In, "%#06RX16");
1742}
1743
1744
1745void tstASMBench(void)
1746{
1747 /*
1748 * Make this static. We don't want to have this located on the stack.
1749 */
1750 static uint8_t volatile s_u8;
1751 static int8_t volatile s_i8;
1752 static uint16_t volatile s_u16;
1753 static int16_t volatile s_i16;
1754 static uint32_t volatile s_u32;
1755 static int32_t volatile s_i32;
1756 static uint64_t volatile s_u64;
1757 static int64_t volatile s_i64;
1758 register unsigned i;
1759 const unsigned cRounds = _2M; /* Must be multiple of 8 */
1760 register uint64_t u64Elapsed;
1761
1762 RTTestSub(g_hTest, "Benchmarking");
1763
1764#if 0 && !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
1765# define BENCH(op, str) \
1766 do { \
1767 RTThreadYield(); \
1768 u64Elapsed = ASMReadTSC(); \
1769 for (i = cRounds; i > 0; i--) \
1770 op; \
1771 u64Elapsed = ASMReadTSC() - u64Elapsed; \
1772 RTTestValue(g_hTest, str, u64Elapsed / cRounds, RTTESTUNIT_TICKS_PER_CALL); \
1773 } while (0)
1774#else
1775# define BENCH(op, str) \
1776 do { \
1777 RTThreadYield(); \
1778 u64Elapsed = RTTimeNanoTS(); \
1779 for (i = cRounds / 8; i > 0; i--) \
1780 { \
1781 op; \
1782 op; \
1783 op; \
1784 op; \
1785 op; \
1786 op; \
1787 op; \
1788 op; \
1789 } \
1790 u64Elapsed = RTTimeNanoTS() - u64Elapsed; \
1791 RTTestValue(g_hTest, str, u64Elapsed / cRounds, RTTESTUNIT_NS_PER_CALL); \
1792 } while (0)
1793#endif
1794#if (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)) && !defined(GCC44_32BIT_PIC)
1795# define BENCH_TSC(op, str) \
1796 do { \
1797 RTThreadYield(); \
1798 u64Elapsed = ASMReadTSC(); \
1799 for (i = cRounds / 8; i > 0; i--) \
1800 { \
1801 op; \
1802 op; \
1803 op; \
1804 op; \
1805 op; \
1806 op; \
1807 op; \
1808 op; \
1809 } \
1810 u64Elapsed = ASMReadTSC() - u64Elapsed; \
1811 RTTestValue(g_hTest, str, u64Elapsed / cRounds, /*RTTESTUNIT_TICKS_PER_CALL*/ RTTESTUNIT_NONE); \
1812 } while (0)
1813#else
1814# define BENCH_TSC(op, str) BENCH(op, str)
1815#endif
1816
1817 BENCH(s_u32 = 0, "s_u32 = 0");
1818 BENCH(ASMAtomicUoReadU8(&s_u8), "ASMAtomicUoReadU8");
1819 BENCH(ASMAtomicUoReadS8(&s_i8), "ASMAtomicUoReadS8");
1820 BENCH(ASMAtomicUoReadU16(&s_u16), "ASMAtomicUoReadU16");
1821 BENCH(ASMAtomicUoReadS16(&s_i16), "ASMAtomicUoReadS16");
1822 BENCH(ASMAtomicUoReadU32(&s_u32), "ASMAtomicUoReadU32");
1823 BENCH(ASMAtomicUoReadS32(&s_i32), "ASMAtomicUoReadS32");
1824 BENCH(ASMAtomicUoReadU64(&s_u64), "ASMAtomicUoReadU64");
1825 BENCH(ASMAtomicUoReadS64(&s_i64), "ASMAtomicUoReadS64");
1826 BENCH(ASMAtomicReadU8(&s_u8), "ASMAtomicReadU8");
1827 BENCH(ASMAtomicReadS8(&s_i8), "ASMAtomicReadS8");
1828 BENCH(ASMAtomicReadU16(&s_u16), "ASMAtomicReadU16");
1829 BENCH(ASMAtomicReadS16(&s_i16), "ASMAtomicReadS16");
1830 BENCH(ASMAtomicReadU32(&s_u32), "ASMAtomicReadU32");
1831 BENCH(ASMAtomicReadS32(&s_i32), "ASMAtomicReadS32");
1832 BENCH(ASMAtomicReadU64(&s_u64), "ASMAtomicReadU64");
1833 BENCH(ASMAtomicReadS64(&s_i64), "ASMAtomicReadS64");
1834 BENCH(ASMAtomicUoWriteU8(&s_u8, 0), "ASMAtomicUoWriteU8");
1835 BENCH(ASMAtomicUoWriteS8(&s_i8, 0), "ASMAtomicUoWriteS8");
1836 BENCH(ASMAtomicUoWriteU16(&s_u16, 0), "ASMAtomicUoWriteU16");
1837 BENCH(ASMAtomicUoWriteS16(&s_i16, 0), "ASMAtomicUoWriteS16");
1838 BENCH(ASMAtomicUoWriteU32(&s_u32, 0), "ASMAtomicUoWriteU32");
1839 BENCH(ASMAtomicUoWriteS32(&s_i32, 0), "ASMAtomicUoWriteS32");
1840 BENCH(ASMAtomicUoWriteU64(&s_u64, 0), "ASMAtomicUoWriteU64");
1841 BENCH(ASMAtomicUoWriteS64(&s_i64, 0), "ASMAtomicUoWriteS64");
1842 BENCH(ASMAtomicWriteU8(&s_u8, 0), "ASMAtomicWriteU8");
1843 BENCH(ASMAtomicWriteS8(&s_i8, 0), "ASMAtomicWriteS8");
1844 BENCH(ASMAtomicWriteU16(&s_u16, 0), "ASMAtomicWriteU16");
1845 BENCH(ASMAtomicWriteS16(&s_i16, 0), "ASMAtomicWriteS16");
1846 BENCH(ASMAtomicWriteU32(&s_u32, 0), "ASMAtomicWriteU32");
1847 BENCH(ASMAtomicWriteS32(&s_i32, 0), "ASMAtomicWriteS32");
1848 BENCH(ASMAtomicWriteU64(&s_u64, 0), "ASMAtomicWriteU64");
1849 BENCH(ASMAtomicWriteS64(&s_i64, 0), "ASMAtomicWriteS64");
1850 BENCH(ASMAtomicXchgU8(&s_u8, 0), "ASMAtomicXchgU8");
1851 BENCH(ASMAtomicXchgS8(&s_i8, 0), "ASMAtomicXchgS8");
1852 BENCH(ASMAtomicXchgU16(&s_u16, 0), "ASMAtomicXchgU16");
1853 BENCH(ASMAtomicXchgS16(&s_i16, 0), "ASMAtomicXchgS16");
1854 BENCH(ASMAtomicXchgU32(&s_u32, 0), "ASMAtomicXchgU32");
1855 BENCH(ASMAtomicXchgS32(&s_i32, 0), "ASMAtomicXchgS32");
1856 BENCH(ASMAtomicXchgU64(&s_u64, 0), "ASMAtomicXchgU64");
1857 BENCH(ASMAtomicXchgS64(&s_i64, 0), "ASMAtomicXchgS64");
1858 BENCH(ASMAtomicCmpXchgU32(&s_u32, 0, 0), "ASMAtomicCmpXchgU32");
1859 BENCH(ASMAtomicCmpXchgS32(&s_i32, 0, 0), "ASMAtomicCmpXchgS32");
1860 BENCH(ASMAtomicCmpXchgU64(&s_u64, 0, 0), "ASMAtomicCmpXchgU64");
1861 BENCH(ASMAtomicCmpXchgS64(&s_i64, 0, 0), "ASMAtomicCmpXchgS64");
1862 BENCH(ASMAtomicCmpXchgU32(&s_u32, 0, 1), "ASMAtomicCmpXchgU32/neg");
1863 BENCH(ASMAtomicCmpXchgS32(&s_i32, 0, 1), "ASMAtomicCmpXchgS32/neg");
1864 BENCH(ASMAtomicCmpXchgU64(&s_u64, 0, 1), "ASMAtomicCmpXchgU64/neg");
1865 BENCH(ASMAtomicCmpXchgS64(&s_i64, 0, 1), "ASMAtomicCmpXchgS64/neg");
1866 BENCH(ASMAtomicIncU32(&s_u32), "ASMAtomicIncU32");
1867 BENCH(ASMAtomicIncS32(&s_i32), "ASMAtomicIncS32");
1868 BENCH(ASMAtomicDecU32(&s_u32), "ASMAtomicDecU32");
1869 BENCH(ASMAtomicDecS32(&s_i32), "ASMAtomicDecS32");
1870 BENCH(ASMAtomicAddU32(&s_u32, 5), "ASMAtomicAddU32");
1871 BENCH(ASMAtomicAddS32(&s_i32, 5), "ASMAtomicAddS32");
1872 BENCH(ASMAtomicUoIncU32(&s_u32), "ASMAtomicUoIncU32");
1873 BENCH(ASMAtomicUoDecU32(&s_u32), "ASMAtomicUoDecU32");
1874 BENCH(ASMAtomicUoAndU32(&s_u32, 0xffffffff), "ASMAtomicUoAndU32");
1875 BENCH(ASMAtomicUoOrU32(&s_u32, 0xffffffff), "ASMAtomicUoOrU32");
1876#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
1877 BENCH_TSC(ASMSerializeInstructionCpuId(), "ASMSerializeInstructionCpuId");
1878 BENCH_TSC(ASMSerializeInstructionIRet(), "ASMSerializeInstructionIRet");
1879#endif
1880
1881 /* The Darwin gcc does not like this ... */
1882#if !defined(RT_OS_DARWIN) && !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
1883 BENCH(s_u8 = ASMGetApicId(), "ASMGetApicId");
1884#endif
1885#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
1886 uint32_t uAux;
1887 if ( ASMHasCpuId()
1888 && ASMIsValidExtRange(ASMCpuId_EAX(0x80000000))
1889 && (ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_RDTSCP) )
1890 {
1891 BENCH_TSC(ASMSerializeInstructionRdTscp(), "ASMSerializeInstructionRdTscp");
1892 BENCH(s_u64 = ASMReadTscWithAux(&uAux), "ASMReadTscWithAux");
1893 }
1894 BENCH(s_u64 = ASMReadTSC(), "ASMReadTSC");
1895 union
1896 {
1897 uint64_t u64[2];
1898 RTIDTR Unaligned;
1899 struct
1900 {
1901 uint16_t abPadding[3];
1902 RTIDTR Aligned;
1903 } s;
1904 } uBuf;
1905 Assert(((uintptr_t)&uBuf.Unaligned.pIdt & (sizeof(uintptr_t) - 1)) != 0);
1906 BENCH(ASMGetIDTR(&uBuf.Unaligned), "ASMGetIDTR/unaligned");
1907 Assert(((uintptr_t)&uBuf.s.Aligned.pIdt & (sizeof(uintptr_t) - 1)) == 0);
1908 BENCH(ASMGetIDTR(&uBuf.s.Aligned), "ASMGetIDTR/aligned");
1909#endif
1910
1911#undef BENCH
1912}
1913
1914
1915int main(int argc, char **argv)
1916{
1917 RT_NOREF_PV(argc); RT_NOREF_PV(argv);
1918
1919 int rc = RTTestInitAndCreate("tstRTInlineAsm", &g_hTest);
1920 if (rc)
1921 return rc;
1922 RTTestBanner(g_hTest);
1923
1924 /*
1925 * Execute the tests.
1926 */
1927#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
1928 tstASMCpuId();
1929 //bruteForceCpuId();
1930#endif
1931#if 1
1932 tstASMAtomicXchgU8();
1933 tstASMAtomicXchgU16();
1934 tstASMAtomicXchgU32();
1935 tstASMAtomicXchgU64();
1936 tstASMAtomicXchgPtr();
1937 tstASMAtomicCmpXchgU8();
1938 tstASMAtomicCmpXchgU32();
1939 tstASMAtomicCmpXchgU64();
1940 tstASMAtomicCmpXchgExU32();
1941 tstASMAtomicCmpXchgExU64();
1942 tstASMAtomicReadU64();
1943 tstASMAtomicUoReadU64();
1944
1945 tstASMAtomicAddS32();
1946 tstASMAtomicAddS64();
1947 tstASMAtomicDecIncS32();
1948 tstASMAtomicDecIncS64();
1949 tstASMAtomicAndOrU32();
1950 tstASMAtomicAndOrU64();
1951
1952 tstASMAtomicUoIncU32();
1953 tstASMAtomicUoDecU32();
1954 tstASMAtomicUoAndOrU32();
1955
1956 tstASMMemZeroPage();
1957 tstASMMemIsZeroPage(g_hTest);
1958 tstASMMemFirstMismatchingU8(g_hTest);
1959 tstASMMemZero32();
1960 tstASMMemFill32();
1961
1962 tstASMMath();
1963
1964 tstASMByteSwap();
1965
1966 tstASMBench();
1967#endif
1968
1969 /*
1970 * Show the result.
1971 */
1972 return RTTestSummaryAndDestroy(g_hTest);
1973}
1974
Note: See TracBrowser for help on using the repository browser.

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