VirtualBox

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

Last change on this file since 49038 was 48935, checked in by vboxsync, 11 years ago

Runtime: Whitespace and svn:keyword cleanups by scm.

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