VirtualBox

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

Last change on this file since 57358 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

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