VirtualBox

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

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

iprt/asm.h: Cleaned up the ASMMemIsAll8/U32 mess and implmeneted the former in assembly. (Found inverted usage due to bad naming in copyUtf8Block, but it is fortunately an unused method.) Replaces the complicated ASMBitFirstSet based scanning in RTSgBufIsZero with a simple call to the new ASMMemIsZero function.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 73.0 KB
Line 
1/* $Id: tstRTInlineAsm.cpp 59747 2016-02-19 23:18:18Z 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 if (!(offNonZero - offStart < cb ? pbRet == &pbBuf2[offNonZero] : pbRet == NULL))
1432 __debugbreak();
1433 RTTESTI_CHECK(offNonZero - offStart < cb ? pbRet == &pbBuf2[offNonZero] : pbRet == NULL);
1434
1435 if (offEnd < PAGE_SIZE)
1436 {
1437 pbBuf1[offEnd] = bSaved1;
1438 pbBuf2[offEnd] = bSaved2;
1439 }
1440 }
1441 }
1442
1443 pbBuf1[offNonZero] = 0;
1444 pbBuf2[offNonZero] = 0xf6;
1445 }
1446
1447 RTTestSubDone(hTest);
1448}
1449
1450
1451void tstASMMemZero32(void)
1452{
1453 RTTestSub(g_hTest, "ASMMemFill32");
1454
1455 struct
1456 {
1457 uint64_t u64Magic1;
1458 uint8_t abPage[PAGE_SIZE - 32];
1459 uint64_t u64Magic2;
1460 } Buf1, Buf2, Buf3;
1461
1462 Buf1.u64Magic1 = UINT64_C(0xffffffffffffffff);
1463 memset(Buf1.abPage, 0x55, sizeof(Buf1.abPage));
1464 Buf1.u64Magic2 = UINT64_C(0xffffffffffffffff);
1465 Buf2.u64Magic1 = UINT64_C(0xffffffffffffffff);
1466 memset(Buf2.abPage, 0x77, sizeof(Buf2.abPage));
1467 Buf2.u64Magic2 = UINT64_C(0xffffffffffffffff);
1468 Buf3.u64Magic1 = UINT64_C(0xffffffffffffffff);
1469 memset(Buf3.abPage, 0x99, sizeof(Buf3.abPage));
1470 Buf3.u64Magic2 = UINT64_C(0xffffffffffffffff);
1471 ASMMemZero32(Buf1.abPage, sizeof(Buf1.abPage));
1472 ASMMemZero32(Buf2.abPage, sizeof(Buf2.abPage));
1473 ASMMemZero32(Buf3.abPage, sizeof(Buf3.abPage));
1474 if ( Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
1475 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
1476 || Buf2.u64Magic1 != UINT64_C(0xffffffffffffffff)
1477 || Buf2.u64Magic2 != UINT64_C(0xffffffffffffffff)
1478 || Buf3.u64Magic1 != UINT64_C(0xffffffffffffffff)
1479 || Buf3.u64Magic2 != UINT64_C(0xffffffffffffffff))
1480 {
1481 RTTestFailed(g_hTest, "ASMMemZero32 violated one/both magic(s)!\n");
1482 }
1483 for (unsigned i = 0; i < RT_ELEMENTS(Buf1.abPage); i++)
1484 if (Buf1.abPage[i])
1485 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear byte at offset %#x!\n", i);
1486 for (unsigned i = 0; i < RT_ELEMENTS(Buf2.abPage); i++)
1487 if (Buf2.abPage[i])
1488 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear byte at offset %#x!\n", i);
1489 for (unsigned i = 0; i < RT_ELEMENTS(Buf3.abPage); i++)
1490 if (Buf3.abPage[i])
1491 RTTestFailed(g_hTest, "ASMMemZero32 didn't clear byte at offset %#x!\n", i);
1492}
1493
1494
1495void tstASMMemFill32(void)
1496{
1497 RTTestSub(g_hTest, "ASMMemFill32");
1498
1499 struct
1500 {
1501 uint64_t u64Magic1;
1502 uint32_t au32Page[PAGE_SIZE / 4];
1503 uint64_t u64Magic2;
1504 } Buf1;
1505 struct
1506 {
1507 uint64_t u64Magic1;
1508 uint32_t au32Page[(PAGE_SIZE / 4) - 3];
1509 uint64_t u64Magic2;
1510 } Buf2;
1511 struct
1512 {
1513 uint64_t u64Magic1;
1514 uint32_t au32Page[(PAGE_SIZE / 4) - 1];
1515 uint64_t u64Magic2;
1516 } Buf3;
1517
1518 Buf1.u64Magic1 = UINT64_C(0xffffffffffffffff);
1519 memset(Buf1.au32Page, 0x55, sizeof(Buf1.au32Page));
1520 Buf1.u64Magic2 = UINT64_C(0xffffffffffffffff);
1521 Buf2.u64Magic1 = UINT64_C(0xffffffffffffffff);
1522 memset(Buf2.au32Page, 0x77, sizeof(Buf2.au32Page));
1523 Buf2.u64Magic2 = UINT64_C(0xffffffffffffffff);
1524 Buf3.u64Magic1 = UINT64_C(0xffffffffffffffff);
1525 memset(Buf3.au32Page, 0x99, sizeof(Buf3.au32Page));
1526 Buf3.u64Magic2 = UINT64_C(0xffffffffffffffff);
1527 ASMMemFill32(Buf1.au32Page, sizeof(Buf1.au32Page), 0xdeadbeef);
1528 ASMMemFill32(Buf2.au32Page, sizeof(Buf2.au32Page), 0xcafeff01);
1529 ASMMemFill32(Buf3.au32Page, sizeof(Buf3.au32Page), 0xf00dd00f);
1530 if ( Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
1531 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
1532 || Buf2.u64Magic1 != UINT64_C(0xffffffffffffffff)
1533 || Buf2.u64Magic2 != UINT64_C(0xffffffffffffffff)
1534 || Buf3.u64Magic1 != UINT64_C(0xffffffffffffffff)
1535 || Buf3.u64Magic2 != UINT64_C(0xffffffffffffffff))
1536 RTTestFailed(g_hTest, "ASMMemFill32 violated one/both magic(s)!\n");
1537 for (unsigned i = 0; i < RT_ELEMENTS(Buf1.au32Page); i++)
1538 if (Buf1.au32Page[i] != 0xdeadbeef)
1539 RTTestFailed(g_hTest, "ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf1.au32Page[i], 0xdeadbeef);
1540 for (unsigned i = 0; i < RT_ELEMENTS(Buf2.au32Page); i++)
1541 if (Buf2.au32Page[i] != 0xcafeff01)
1542 RTTestFailed(g_hTest, "ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf2.au32Page[i], 0xcafeff01);
1543 for (unsigned i = 0; i < RT_ELEMENTS(Buf3.au32Page); i++)
1544 if (Buf3.au32Page[i] != 0xf00dd00f)
1545 RTTestFailed(g_hTest, "ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf3.au32Page[i], 0xf00dd00f);
1546}
1547
1548
1549
1550void tstASMMath(void)
1551{
1552 RTTestSub(g_hTest, "Math");
1553
1554 uint64_t u64 = ASMMult2xU32RetU64(UINT32_C(0x80000000), UINT32_C(0x10000000));
1555 CHECKVAL(u64, UINT64_C(0x0800000000000000), "%#018RX64");
1556
1557 uint32_t u32 = ASMDivU64ByU32RetU32(UINT64_C(0x0800000000000000), UINT32_C(0x10000000));
1558 CHECKVAL(u32, UINT32_C(0x80000000), "%#010RX32");
1559
1560 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x00000001), UINT32_C(0x00000001), UINT32_C(0x00000001));
1561 CHECKVAL(u32, UINT32_C(0x00000001), "%#018RX32");
1562 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x10000000), UINT32_C(0x80000000), UINT32_C(0x20000000));
1563 CHECKVAL(u32, UINT32_C(0x40000000), "%#018RX32");
1564 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x76543210), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1565 CHECKVAL(u32, UINT32_C(0x76543210), "%#018RX32");
1566 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0xffffffff), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1567 CHECKVAL(u32, UINT32_C(0xffffffff), "%#018RX32");
1568 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0xffffffff), UINT32_C(0xfffffff0), UINT32_C(0xffffffff));
1569 CHECKVAL(u32, UINT32_C(0xfffffff0), "%#018RX32");
1570 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x10359583), UINT32_C(0x58734981), UINT32_C(0xf8694045));
1571 CHECKVAL(u32, UINT32_C(0x05c584ce), "%#018RX32");
1572 u32 = ASMMultU32ByU32DivByU32(UINT32_C(0x10359583), UINT32_C(0xf8694045), UINT32_C(0x58734981));
1573 CHECKVAL(u32, UINT32_C(0x2d860795), "%#018RX32");
1574
1575#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
1576 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x0000000000000001), UINT32_C(0x00000001), UINT32_C(0x00000001));
1577 CHECKVAL(u64, UINT64_C(0x0000000000000001), "%#018RX64");
1578 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x0000000100000000), UINT32_C(0x80000000), UINT32_C(0x00000002));
1579 CHECKVAL(u64, UINT64_C(0x4000000000000000), "%#018RX64");
1580 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xfedcba9876543210), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1581 CHECKVAL(u64, UINT64_C(0xfedcba9876543210), "%#018RX64");
1582 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xffffffffffffffff), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1583 CHECKVAL(u64, UINT64_C(0xffffffffffffffff), "%#018RX64");
1584 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xffffffffffffffff), UINT32_C(0xfffffff0), UINT32_C(0xffffffff));
1585 CHECKVAL(u64, UINT64_C(0xfffffff0fffffff0), "%#018RX64");
1586 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x3415934810359583), UINT32_C(0x58734981), UINT32_C(0xf8694045));
1587 CHECKVAL(u64, UINT64_C(0x128b9c3d43184763), "%#018RX64");
1588 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x3415934810359583), UINT32_C(0xf8694045), UINT32_C(0x58734981));
1589 CHECKVAL(u64, UINT64_C(0x924719355cd35a27), "%#018RX64");
1590
1591# if 0 /* bird: question is whether this should trap or not:
1592 *
1593 * frank: Of course it must trap:
1594 *
1595 * 0xfffffff8 * 0x77d7daf8 = 0x77d7daf441412840
1596 *
1597 * During the following division, the quotient must fit into a 32-bit register.
1598 * Therefore the smallest valid divisor is
1599 *
1600 * (0x77d7daf441412840 >> 32) + 1 = 0x77d7daf5
1601 *
1602 * which is definitely greater than 0x3b9aca00.
1603 *
1604 * bird: No, the C version does *not* crash. So, the question is whether there's any
1605 * code depending on it not crashing.
1606 *
1607 * Of course the assembly versions of the code crash right now for the reasons you've
1608 * given, but the 32-bit MSC version does not crash.
1609 *
1610 * frank: The C version does not crash but delivers incorrect results for this case.
1611 * The reason is
1612 *
1613 * u.s.Hi = (unsigned long)(u64Hi / u32C);
1614 *
1615 * Here the division is actually 64-bit by 64-bit but the 64-bit result is truncated
1616 * to 32 bit. If using this (optimized and fast) function we should just be sure that
1617 * the operands are in a valid range.
1618 */
1619 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xfffffff8c65d6731), UINT32_C(0x77d7daf8), UINT32_C(0x3b9aca00));
1620 CHECKVAL(u64, UINT64_C(0x02b8f9a2aa74e3dc), "%#018RX64");
1621# endif
1622#endif /* AMD64 || X86 */
1623
1624 u32 = ASMModU64ByU32RetU32(UINT64_C(0x0ffffff8c65d6731), UINT32_C(0x77d7daf8));
1625 CHECKVAL(u32, UINT32_C(0x3B642451), "%#010RX32");
1626
1627 int32_t i32;
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 i32 = ASMModS64ByS32RetS32(INT64_C(11), INT32_C(-2));
1633 CHECKVAL(i32, INT32_C(1), "%010RI32");
1634
1635 i32 = ASMModS64ByS32RetS32(INT64_C(92233720368547758), INT32_C(2147483647));
1636 CHECKVAL(i32, INT32_C(2104533974), "%010RI32");
1637 i32 = ASMModS64ByS32RetS32(INT64_C(-92233720368547758), INT32_C(2147483647));
1638 CHECKVAL(i32, INT32_C(-2104533974), "%010RI32");
1639}
1640
1641
1642void tstASMByteSwap(void)
1643{
1644 RTTestSub(g_hTest, "ASMByteSwap*");
1645
1646 uint64_t u64In = UINT64_C(0x0011223344556677);
1647 uint64_t u64Out = ASMByteSwapU64(u64In);
1648 CHECKVAL(u64In, UINT64_C(0x0011223344556677), "%#018RX64");
1649 CHECKVAL(u64Out, UINT64_C(0x7766554433221100), "%#018RX64");
1650 u64Out = ASMByteSwapU64(u64Out);
1651 CHECKVAL(u64Out, u64In, "%#018RX64");
1652 u64In = UINT64_C(0x0123456789abcdef);
1653 u64Out = ASMByteSwapU64(u64In);
1654 CHECKVAL(u64In, UINT64_C(0x0123456789abcdef), "%#018RX64");
1655 CHECKVAL(u64Out, UINT64_C(0xefcdab8967452301), "%#018RX64");
1656 u64Out = ASMByteSwapU64(u64Out);
1657 CHECKVAL(u64Out, u64In, "%#018RX64");
1658 u64In = 0;
1659 u64Out = ASMByteSwapU64(u64In);
1660 CHECKVAL(u64Out, u64In, "%#018RX64");
1661 u64In = ~(uint64_t)0;
1662 u64Out = ASMByteSwapU64(u64In);
1663 CHECKVAL(u64Out, u64In, "%#018RX64");
1664
1665 uint32_t u32In = UINT32_C(0x00112233);
1666 uint32_t u32Out = ASMByteSwapU32(u32In);
1667 CHECKVAL(u32In, UINT32_C(0x00112233), "%#010RX32");
1668 CHECKVAL(u32Out, UINT32_C(0x33221100), "%#010RX32");
1669 u32Out = ASMByteSwapU32(u32Out);
1670 CHECKVAL(u32Out, u32In, "%#010RX32");
1671 u32In = UINT32_C(0x12345678);
1672 u32Out = ASMByteSwapU32(u32In);
1673 CHECKVAL(u32In, UINT32_C(0x12345678), "%#010RX32");
1674 CHECKVAL(u32Out, UINT32_C(0x78563412), "%#010RX32");
1675 u32Out = ASMByteSwapU32(u32Out);
1676 CHECKVAL(u32Out, u32In, "%#010RX32");
1677 u32In = 0;
1678 u32Out = ASMByteSwapU32(u32In);
1679 CHECKVAL(u32Out, u32In, "%#010RX32");
1680 u32In = ~(uint32_t)0;
1681 u32Out = ASMByteSwapU32(u32In);
1682 CHECKVAL(u32Out, u32In, "%#010RX32");
1683
1684 uint16_t u16In = UINT16_C(0x0011);
1685 uint16_t u16Out = ASMByteSwapU16(u16In);
1686 CHECKVAL(u16In, UINT16_C(0x0011), "%#06RX16");
1687 CHECKVAL(u16Out, UINT16_C(0x1100), "%#06RX16");
1688 u16Out = ASMByteSwapU16(u16Out);
1689 CHECKVAL(u16Out, u16In, "%#06RX16");
1690 u16In = UINT16_C(0x1234);
1691 u16Out = ASMByteSwapU16(u16In);
1692 CHECKVAL(u16In, UINT16_C(0x1234), "%#06RX16");
1693 CHECKVAL(u16Out, UINT16_C(0x3412), "%#06RX16");
1694 u16Out = ASMByteSwapU16(u16Out);
1695 CHECKVAL(u16Out, u16In, "%#06RX16");
1696 u16In = 0;
1697 u16Out = ASMByteSwapU16(u16In);
1698 CHECKVAL(u16Out, u16In, "%#06RX16");
1699 u16In = ~(uint16_t)0;
1700 u16Out = ASMByteSwapU16(u16In);
1701 CHECKVAL(u16Out, u16In, "%#06RX16");
1702}
1703
1704
1705void tstASMBench(void)
1706{
1707 /*
1708 * Make this static. We don't want to have this located on the stack.
1709 */
1710 static uint8_t volatile s_u8;
1711 static int8_t volatile s_i8;
1712 static uint16_t volatile s_u16;
1713 static int16_t volatile s_i16;
1714 static uint32_t volatile s_u32;
1715 static int32_t volatile s_i32;
1716 static uint64_t volatile s_u64;
1717 static int64_t volatile s_i64;
1718 register unsigned i;
1719 const unsigned cRounds = _2M; /* Must be multiple of 8 */
1720 register uint64_t u64Elapsed;
1721
1722 RTTestSub(g_hTest, "Benchmarking");
1723
1724#if 0 && !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
1725# define BENCH(op, str) \
1726 do { \
1727 RTThreadYield(); \
1728 u64Elapsed = ASMReadTSC(); \
1729 for (i = cRounds; i > 0; i--) \
1730 op; \
1731 u64Elapsed = ASMReadTSC() - u64Elapsed; \
1732 RTTestValue(g_hTest, str, u64Elapsed / cRounds, RTTESTUNIT_TICKS_PER_CALL); \
1733 } while (0)
1734#else
1735# define BENCH(op, str) \
1736 do { \
1737 RTThreadYield(); \
1738 u64Elapsed = RTTimeNanoTS(); \
1739 for (i = cRounds / 8; i > 0; i--) \
1740 { \
1741 op; \
1742 op; \
1743 op; \
1744 op; \
1745 op; \
1746 op; \
1747 op; \
1748 op; \
1749 } \
1750 u64Elapsed = RTTimeNanoTS() - u64Elapsed; \
1751 RTTestValue(g_hTest, str, u64Elapsed / cRounds, RTTESTUNIT_NS_PER_CALL); \
1752 } while (0)
1753#endif
1754#if (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)) && !defined(GCC44_32BIT_PIC)
1755# define BENCH_TSC(op, str) \
1756 do { \
1757 RTThreadYield(); \
1758 u64Elapsed = ASMReadTSC(); \
1759 for (i = cRounds / 8; i > 0; i--) \
1760 { \
1761 op; \
1762 op; \
1763 op; \
1764 op; \
1765 op; \
1766 op; \
1767 op; \
1768 op; \
1769 } \
1770 u64Elapsed = ASMReadTSC() - u64Elapsed; \
1771 RTTestValue(g_hTest, str, u64Elapsed / cRounds, /*RTTESTUNIT_TICKS_PER_CALL*/ RTTESTUNIT_NONE); \
1772 } while (0)
1773#else
1774# define BENCH_TSC(op, str) BENCH(op, str)
1775#endif
1776
1777 BENCH(s_u32 = 0, "s_u32 = 0");
1778 BENCH(ASMAtomicUoReadU8(&s_u8), "ASMAtomicUoReadU8");
1779 BENCH(ASMAtomicUoReadS8(&s_i8), "ASMAtomicUoReadS8");
1780 BENCH(ASMAtomicUoReadU16(&s_u16), "ASMAtomicUoReadU16");
1781 BENCH(ASMAtomicUoReadS16(&s_i16), "ASMAtomicUoReadS16");
1782 BENCH(ASMAtomicUoReadU32(&s_u32), "ASMAtomicUoReadU32");
1783 BENCH(ASMAtomicUoReadS32(&s_i32), "ASMAtomicUoReadS32");
1784 BENCH(ASMAtomicUoReadU64(&s_u64), "ASMAtomicUoReadU64");
1785 BENCH(ASMAtomicUoReadS64(&s_i64), "ASMAtomicUoReadS64");
1786 BENCH(ASMAtomicReadU8(&s_u8), "ASMAtomicReadU8");
1787 BENCH(ASMAtomicReadS8(&s_i8), "ASMAtomicReadS8");
1788 BENCH(ASMAtomicReadU16(&s_u16), "ASMAtomicReadU16");
1789 BENCH(ASMAtomicReadS16(&s_i16), "ASMAtomicReadS16");
1790 BENCH(ASMAtomicReadU32(&s_u32), "ASMAtomicReadU32");
1791 BENCH(ASMAtomicReadS32(&s_i32), "ASMAtomicReadS32");
1792 BENCH(ASMAtomicReadU64(&s_u64), "ASMAtomicReadU64");
1793 BENCH(ASMAtomicReadS64(&s_i64), "ASMAtomicReadS64");
1794 BENCH(ASMAtomicUoWriteU8(&s_u8, 0), "ASMAtomicUoWriteU8");
1795 BENCH(ASMAtomicUoWriteS8(&s_i8, 0), "ASMAtomicUoWriteS8");
1796 BENCH(ASMAtomicUoWriteU16(&s_u16, 0), "ASMAtomicUoWriteU16");
1797 BENCH(ASMAtomicUoWriteS16(&s_i16, 0), "ASMAtomicUoWriteS16");
1798 BENCH(ASMAtomicUoWriteU32(&s_u32, 0), "ASMAtomicUoWriteU32");
1799 BENCH(ASMAtomicUoWriteS32(&s_i32, 0), "ASMAtomicUoWriteS32");
1800 BENCH(ASMAtomicUoWriteU64(&s_u64, 0), "ASMAtomicUoWriteU64");
1801 BENCH(ASMAtomicUoWriteS64(&s_i64, 0), "ASMAtomicUoWriteS64");
1802 BENCH(ASMAtomicWriteU8(&s_u8, 0), "ASMAtomicWriteU8");
1803 BENCH(ASMAtomicWriteS8(&s_i8, 0), "ASMAtomicWriteS8");
1804 BENCH(ASMAtomicWriteU16(&s_u16, 0), "ASMAtomicWriteU16");
1805 BENCH(ASMAtomicWriteS16(&s_i16, 0), "ASMAtomicWriteS16");
1806 BENCH(ASMAtomicWriteU32(&s_u32, 0), "ASMAtomicWriteU32");
1807 BENCH(ASMAtomicWriteS32(&s_i32, 0), "ASMAtomicWriteS32");
1808 BENCH(ASMAtomicWriteU64(&s_u64, 0), "ASMAtomicWriteU64");
1809 BENCH(ASMAtomicWriteS64(&s_i64, 0), "ASMAtomicWriteS64");
1810 BENCH(ASMAtomicXchgU8(&s_u8, 0), "ASMAtomicXchgU8");
1811 BENCH(ASMAtomicXchgS8(&s_i8, 0), "ASMAtomicXchgS8");
1812 BENCH(ASMAtomicXchgU16(&s_u16, 0), "ASMAtomicXchgU16");
1813 BENCH(ASMAtomicXchgS16(&s_i16, 0), "ASMAtomicXchgS16");
1814 BENCH(ASMAtomicXchgU32(&s_u32, 0), "ASMAtomicXchgU32");
1815 BENCH(ASMAtomicXchgS32(&s_i32, 0), "ASMAtomicXchgS32");
1816 BENCH(ASMAtomicXchgU64(&s_u64, 0), "ASMAtomicXchgU64");
1817 BENCH(ASMAtomicXchgS64(&s_i64, 0), "ASMAtomicXchgS64");
1818 BENCH(ASMAtomicCmpXchgU32(&s_u32, 0, 0), "ASMAtomicCmpXchgU32");
1819 BENCH(ASMAtomicCmpXchgS32(&s_i32, 0, 0), "ASMAtomicCmpXchgS32");
1820 BENCH(ASMAtomicCmpXchgU64(&s_u64, 0, 0), "ASMAtomicCmpXchgU64");
1821 BENCH(ASMAtomicCmpXchgS64(&s_i64, 0, 0), "ASMAtomicCmpXchgS64");
1822 BENCH(ASMAtomicCmpXchgU32(&s_u32, 0, 1), "ASMAtomicCmpXchgU32/neg");
1823 BENCH(ASMAtomicCmpXchgS32(&s_i32, 0, 1), "ASMAtomicCmpXchgS32/neg");
1824 BENCH(ASMAtomicCmpXchgU64(&s_u64, 0, 1), "ASMAtomicCmpXchgU64/neg");
1825 BENCH(ASMAtomicCmpXchgS64(&s_i64, 0, 1), "ASMAtomicCmpXchgS64/neg");
1826 BENCH(ASMAtomicIncU32(&s_u32), "ASMAtomicIncU32");
1827 BENCH(ASMAtomicIncS32(&s_i32), "ASMAtomicIncS32");
1828 BENCH(ASMAtomicDecU32(&s_u32), "ASMAtomicDecU32");
1829 BENCH(ASMAtomicDecS32(&s_i32), "ASMAtomicDecS32");
1830 BENCH(ASMAtomicAddU32(&s_u32, 5), "ASMAtomicAddU32");
1831 BENCH(ASMAtomicAddS32(&s_i32, 5), "ASMAtomicAddS32");
1832 BENCH(ASMAtomicUoIncU32(&s_u32), "ASMAtomicUoIncU32");
1833 BENCH(ASMAtomicUoDecU32(&s_u32), "ASMAtomicUoDecU32");
1834 BENCH(ASMAtomicUoAndU32(&s_u32, 0xffffffff), "ASMAtomicUoAndU32");
1835 BENCH(ASMAtomicUoOrU32(&s_u32, 0xffffffff), "ASMAtomicUoOrU32");
1836 BENCH_TSC(ASMSerializeInstructionCpuId(), "ASMSerializeInstructionCpuId");
1837 BENCH_TSC(ASMSerializeInstructionIRet(), "ASMSerializeInstructionIRet");
1838
1839 /* The Darwin gcc does not like this ... */
1840#if !defined(RT_OS_DARWIN) && !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
1841 BENCH(s_u8 = ASMGetApicId(), "ASMGetApicId");
1842#endif
1843#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
1844 uint32_t uAux;
1845 if ( ASMHasCpuId()
1846 && ASMIsValidExtRange(ASMCpuId_EAX(0x80000000))
1847 && (ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_RDTSCP) )
1848 {
1849 BENCH_TSC(ASMSerializeInstructionRdTscp(), "ASMSerializeInstructionRdTscp");
1850 BENCH(s_u64 = ASMReadTscWithAux(&uAux), "ASMReadTscWithAux");
1851 }
1852 BENCH(s_u64 = ASMReadTSC(), "ASMReadTSC");
1853 union
1854 {
1855 uint64_t u64[2];
1856 RTIDTR Unaligned;
1857 struct
1858 {
1859 uint16_t abPadding[3];
1860 RTIDTR Aligned;
1861 } s;
1862 } uBuf;
1863 Assert(((uintptr_t)&uBuf.Unaligned.pIdt & (sizeof(uintptr_t) - 1)) != 0);
1864 BENCH(ASMGetIDTR(&uBuf.Unaligned), "ASMGetIDTR/unaligned");
1865 Assert(((uintptr_t)&uBuf.s.Aligned.pIdt & (sizeof(uintptr_t) - 1)) == 0);
1866 BENCH(ASMGetIDTR(&uBuf.s.Aligned), "ASMGetIDTR/aligned");
1867#endif
1868
1869#undef BENCH
1870}
1871
1872
1873int main(int argc, char *argv[])
1874{
1875 int rc = RTTestInitAndCreate("tstRTInlineAsm", &g_hTest);
1876 if (rc)
1877 return rc;
1878 RTTestBanner(g_hTest);
1879
1880 /*
1881 * Execute the tests.
1882 */
1883#if !defined(GCC44_32BIT_PIC) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
1884 tstASMCpuId();
1885 //bruteForceCpuId();
1886#endif
1887#if 1
1888 tstASMAtomicXchgU8();
1889 tstASMAtomicXchgU16();
1890 tstASMAtomicXchgU32();
1891 tstASMAtomicXchgU64();
1892 tstASMAtomicXchgPtr();
1893 tstASMAtomicCmpXchgU8();
1894 tstASMAtomicCmpXchgU32();
1895 tstASMAtomicCmpXchgU64();
1896 tstASMAtomicCmpXchgExU32();
1897 tstASMAtomicCmpXchgExU64();
1898 tstASMAtomicReadU64();
1899 tstASMAtomicUoReadU64();
1900
1901 tstASMAtomicAddS32();
1902 tstASMAtomicAddS64();
1903 tstASMAtomicDecIncS32();
1904 tstASMAtomicDecIncS64();
1905 tstASMAtomicAndOrU32();
1906 tstASMAtomicAndOrU64();
1907
1908 tstASMAtomicUoIncU32();
1909 tstASMAtomicUoDecU32();
1910 tstASMAtomicUoAndOrU32();
1911
1912 tstASMMemZeroPage();
1913 tstASMMemIsZeroPage(g_hTest);
1914 tstASMMemFirstMismatchingU8(g_hTest);
1915 tstASMMemZero32();
1916 tstASMMemFill32();
1917
1918 tstASMMath();
1919
1920 tstASMByteSwap();
1921
1922 tstASMBench();
1923#endif
1924
1925 /*
1926 * Show the result.
1927 */
1928 return RTTestSummaryAndDestroy(g_hTest);
1929}
1930
Note: See TracBrowser for help on using the repository browser.

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