VirtualBox

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

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

IPRT: build fixes

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