VirtualBox

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

Last change on this file since 57023 was 56290, checked in by vboxsync, 10 years ago

IPRT: Updated (C) year.

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