VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstInlineAsm.cpp@ 26517

Last change on this file since 26517 was 25669, checked in by vboxsync, 15 years ago

tstInlineAsm.cpp: test ASMAtomic*Read*

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 46.9 KB
Line 
1/* $Id: tstInlineAsm.cpp 25669 2010-01-06 04:58:02Z vboxsync $ */
2/** @file
3 * IPRT Testcase - inline assembly.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#include <iprt/asm.h>
35#include <iprt/stream.h>
36#include <iprt/string.h>
37#include <iprt/initterm.h>
38#include <iprt/param.h>
39#include <iprt/thread.h>
40#include <iprt/test.h>
41
42
43
44/*******************************************************************************
45* Defined Constants And Macros *
46*******************************************************************************/
47#define CHECKVAL(val, expect, fmt) \
48 do \
49 { \
50 if ((val) != (expect)) \
51 { \
52 RTTestIErrorInc(); \
53 RTPrintf("%s, %d: " #val ": expected " fmt " got " fmt "\n", __FUNCTION__, __LINE__, (expect), (val)); \
54 } \
55 } while (0)
56
57#define CHECKOP(op, expect, fmt, type) \
58 do \
59 { \
60 type val = op; \
61 if (val != (type)(expect)) \
62 { \
63 RTTestIErrorInc(); \
64 RTPrintf("%s, %d: " #op ": expected " fmt " got " fmt "\n", __FUNCTION__, __LINE__, (type)(expect), val); \
65 } \
66 } while (0)
67
68
69#if !defined(PIC) || !defined(RT_ARCH_X86)
70const char *getCacheAss(unsigned u)
71{
72 if (u == 0)
73 return "res0 ";
74 if (u == 1)
75 return "direct";
76 if (u >= 256)
77 return "???";
78
79 char *pszRet;
80 RTStrAPrintf(&pszRet, "%d way", u); /* intentional leak! */
81 return pszRet;
82}
83
84
85const char *getL2CacheAss(unsigned u)
86{
87 switch (u)
88 {
89 case 0: return "off ";
90 case 1: return "direct";
91 case 2: return "2 way ";
92 case 3: return "res3 ";
93 case 4: return "4 way ";
94 case 5: return "res5 ";
95 case 6: return "8 way ";
96 case 7: return "res7 ";
97 case 8: return "16 way";
98 case 9: return "res9 ";
99 case 10: return "res10 ";
100 case 11: return "res11 ";
101 case 12: return "res12 ";
102 case 13: return "res13 ";
103 case 14: return "res14 ";
104 case 15: return "fully ";
105 default:
106 return "????";
107 }
108}
109
110
111/**
112 * Test and dump all possible info from the CPUID instruction.
113 *
114 * @remark Bits shared with the libc cpuid.c program. This all written by me, so no worries.
115 * @todo transform the dumping into a generic runtime function. We'll need it for logging!
116 */
117void tstASMCpuId(void)
118{
119 unsigned iBit;
120 struct
121 {
122 uint32_t uEBX, uEAX, uEDX, uECX;
123 } s;
124 if (!ASMHasCpuId())
125 {
126 RTPrintf("tstInlineAsm: warning! CPU doesn't support CPUID\n");
127 return;
128 }
129
130 /*
131 * Try the 0 function and use that for checking the ASMCpuId_* variants.
132 */
133 ASMCpuId(0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
134
135 uint32_t u32 = ASMCpuId_ECX(0);
136 CHECKVAL(u32, s.uECX, "%x");
137
138 u32 = ASMCpuId_EDX(0);
139 CHECKVAL(u32, s.uEDX, "%x");
140
141 uint32_t uECX2 = s.uECX - 1;
142 uint32_t uEDX2 = s.uEDX - 1;
143 ASMCpuId_ECX_EDX(0, &uECX2, &uEDX2);
144
145 CHECKVAL(uECX2, s.uECX, "%x");
146 CHECKVAL(uEDX2, s.uEDX, "%x");
147
148 /*
149 * Done testing, dump the information.
150 */
151 RTPrintf("tstInlineAsm: CPUID Dump\n");
152 ASMCpuId(0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
153 const uint32_t cFunctions = s.uEAX;
154
155 /* raw dump */
156 RTPrintf("\n"
157 " RAW Standard CPUIDs\n"
158 "Function eax ebx ecx edx\n");
159 for (unsigned iStd = 0; iStd <= cFunctions + 3; iStd++)
160 {
161 ASMCpuId(iStd, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
162 RTPrintf("%08x %08x %08x %08x %08x%s\n",
163 iStd, s.uEAX, s.uEBX, s.uECX, s.uEDX, iStd <= cFunctions ? "" : "*");
164 }
165
166 /*
167 * Understandable output
168 */
169 ASMCpuId(0, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
170 RTPrintf("Name: %.04s%.04s%.04s\n"
171 "Support: 0-%u\n",
172 &s.uEBX, &s.uEDX, &s.uECX, s.uEAX);
173 bool const fIntel = ASMIsIntelCpuEx(s.uEBX, s.uECX, s.uEDX);
174
175 /*
176 * Get Features.
177 */
178 if (cFunctions >= 1)
179 {
180 ASMCpuId(1, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
181 RTPrintf("Family: %#x \tExtended: %#x \tEffective: %#x\n"
182 "Model: %#x \tExtended: %#x \tEffective: %#x\n"
183 "Stepping: %d\n"
184 "APIC ID: %#04x\n"
185 "Logical CPUs: %d\n"
186 "CLFLUSH Size: %d\n"
187 "Brand ID: %#04x\n",
188 (s.uEAX >> 8) & 0xf, (s.uEAX >> 20) & 0x7f, ASMGetCpuFamily(s.uEAX),
189 (s.uEAX >> 4) & 0xf, (s.uEAX >> 16) & 0x0f, ASMGetCpuModel(s.uEAX, fIntel),
190 ASMGetCpuStepping(s.uEAX),
191 (s.uEBX >> 24) & 0xff,
192 (s.uEBX >> 16) & 0xff,
193 (s.uEBX >> 8) & 0xff,
194 (s.uEBX >> 0) & 0xff);
195
196 RTPrintf("Features EDX: ");
197 if (s.uEDX & RT_BIT(0)) RTPrintf(" FPU");
198 if (s.uEDX & RT_BIT(1)) RTPrintf(" VME");
199 if (s.uEDX & RT_BIT(2)) RTPrintf(" DE");
200 if (s.uEDX & RT_BIT(3)) RTPrintf(" PSE");
201 if (s.uEDX & RT_BIT(4)) RTPrintf(" TSC");
202 if (s.uEDX & RT_BIT(5)) RTPrintf(" MSR");
203 if (s.uEDX & RT_BIT(6)) RTPrintf(" PAE");
204 if (s.uEDX & RT_BIT(7)) RTPrintf(" MCE");
205 if (s.uEDX & RT_BIT(8)) RTPrintf(" CX8");
206 if (s.uEDX & RT_BIT(9)) RTPrintf(" APIC");
207 if (s.uEDX & RT_BIT(10)) RTPrintf(" 10");
208 if (s.uEDX & RT_BIT(11)) RTPrintf(" SEP");
209 if (s.uEDX & RT_BIT(12)) RTPrintf(" MTRR");
210 if (s.uEDX & RT_BIT(13)) RTPrintf(" PGE");
211 if (s.uEDX & RT_BIT(14)) RTPrintf(" MCA");
212 if (s.uEDX & RT_BIT(15)) RTPrintf(" CMOV");
213 if (s.uEDX & RT_BIT(16)) RTPrintf(" PAT");
214 if (s.uEDX & RT_BIT(17)) RTPrintf(" PSE36");
215 if (s.uEDX & RT_BIT(18)) RTPrintf(" PSN");
216 if (s.uEDX & RT_BIT(19)) RTPrintf(" CLFSH");
217 if (s.uEDX & RT_BIT(20)) RTPrintf(" 20");
218 if (s.uEDX & RT_BIT(21)) RTPrintf(" DS");
219 if (s.uEDX & RT_BIT(22)) RTPrintf(" ACPI");
220 if (s.uEDX & RT_BIT(23)) RTPrintf(" MMX");
221 if (s.uEDX & RT_BIT(24)) RTPrintf(" FXSR");
222 if (s.uEDX & RT_BIT(25)) RTPrintf(" SSE");
223 if (s.uEDX & RT_BIT(26)) RTPrintf(" SSE2");
224 if (s.uEDX & RT_BIT(27)) RTPrintf(" SS");
225 if (s.uEDX & RT_BIT(28)) RTPrintf(" HTT");
226 if (s.uEDX & RT_BIT(29)) RTPrintf(" 29");
227 if (s.uEDX & RT_BIT(30)) RTPrintf(" 30");
228 if (s.uEDX & RT_BIT(31)) RTPrintf(" 31");
229 RTPrintf("\n");
230
231 /** @todo check intel docs. */
232 RTPrintf("Features ECX: ");
233 if (s.uECX & RT_BIT(0)) RTPrintf(" SSE3");
234 for (iBit = 1; iBit < 13; iBit++)
235 if (s.uECX & RT_BIT(iBit))
236 RTPrintf(" %d", iBit);
237 if (s.uECX & RT_BIT(13)) RTPrintf(" CX16");
238 for (iBit = 14; iBit < 32; iBit++)
239 if (s.uECX & RT_BIT(iBit))
240 RTPrintf(" %d", iBit);
241 RTPrintf("\n");
242 }
243
244 /*
245 * Extended.
246 * Implemented after AMD specs.
247 */
248 /** @todo check out the intel specs. */
249 ASMCpuId(0x80000000, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
250 if (!s.uEAX && !s.uEBX && !s.uECX && !s.uEDX)
251 {
252 RTPrintf("No extended CPUID info? Check the manual on how to detect this...\n");
253 return;
254 }
255 const uint32_t cExtFunctions = s.uEAX | 0x80000000;
256
257 /* raw dump */
258 RTPrintf("\n"
259 " RAW Extended CPUIDs\n"
260 "Function eax ebx ecx edx\n");
261 for (unsigned iExt = 0x80000000; iExt <= cExtFunctions + 3; iExt++)
262 {
263 ASMCpuId(iExt, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
264 RTPrintf("%08x %08x %08x %08x %08x%s\n",
265 iExt, s.uEAX, s.uEBX, s.uECX, s.uEDX, iExt <= cExtFunctions ? "" : "*");
266 }
267
268 /*
269 * Understandable output
270 */
271 ASMCpuId(0x80000000, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
272 RTPrintf("Ext Name: %.4s%.4s%.4s\n"
273 "Ext Supports: 0x80000000-%#010x\n",
274 &s.uEBX, &s.uEDX, &s.uECX, s.uEAX);
275
276 if (cExtFunctions >= 0x80000001)
277 {
278 ASMCpuId(0x80000001, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
279 RTPrintf("Family: %#x \tExtended: %#x \tEffective: %#x\n"
280 "Model: %#x \tExtended: %#x \tEffective: %#x\n"
281 "Stepping: %d\n"
282 "Brand ID: %#05x\n",
283 (s.uEAX >> 8) & 0xf, (s.uEAX >> 20) & 0x7f, ASMGetCpuFamily(s.uEAX),
284 (s.uEAX >> 4) & 0xf, (s.uEAX >> 16) & 0x0f, ASMGetCpuModel(s.uEAX, fIntel),
285 ASMGetCpuStepping(s.uEAX),
286 s.uEBX & 0xfff);
287
288 RTPrintf("Features EDX: ");
289 if (s.uEDX & RT_BIT(0)) RTPrintf(" FPU");
290 if (s.uEDX & RT_BIT(1)) RTPrintf(" VME");
291 if (s.uEDX & RT_BIT(2)) RTPrintf(" DE");
292 if (s.uEDX & RT_BIT(3)) RTPrintf(" PSE");
293 if (s.uEDX & RT_BIT(4)) RTPrintf(" TSC");
294 if (s.uEDX & RT_BIT(5)) RTPrintf(" MSR");
295 if (s.uEDX & RT_BIT(6)) RTPrintf(" PAE");
296 if (s.uEDX & RT_BIT(7)) RTPrintf(" MCE");
297 if (s.uEDX & RT_BIT(8)) RTPrintf(" CMPXCHG8B");
298 if (s.uEDX & RT_BIT(9)) RTPrintf(" APIC");
299 if (s.uEDX & RT_BIT(10)) RTPrintf(" 10");
300 if (s.uEDX & RT_BIT(11)) RTPrintf(" SysCallSysRet");
301 if (s.uEDX & RT_BIT(12)) RTPrintf(" MTRR");
302 if (s.uEDX & RT_BIT(13)) RTPrintf(" PGE");
303 if (s.uEDX & RT_BIT(14)) RTPrintf(" MCA");
304 if (s.uEDX & RT_BIT(15)) RTPrintf(" CMOV");
305 if (s.uEDX & RT_BIT(16)) RTPrintf(" PAT");
306 if (s.uEDX & RT_BIT(17)) RTPrintf(" PSE36");
307 if (s.uEDX & RT_BIT(18)) RTPrintf(" 18");
308 if (s.uEDX & RT_BIT(19)) RTPrintf(" 19");
309 if (s.uEDX & RT_BIT(20)) RTPrintf(" NX");
310 if (s.uEDX & RT_BIT(21)) RTPrintf(" 21");
311 if (s.uEDX & RT_BIT(22)) RTPrintf(" MmxExt");
312 if (s.uEDX & RT_BIT(23)) RTPrintf(" MMX");
313 if (s.uEDX & RT_BIT(24)) RTPrintf(" FXSR");
314 if (s.uEDX & RT_BIT(25)) RTPrintf(" FastFXSR");
315 if (s.uEDX & RT_BIT(26)) RTPrintf(" 26");
316 if (s.uEDX & RT_BIT(27)) RTPrintf(" RDTSCP");
317 if (s.uEDX & RT_BIT(28)) RTPrintf(" 28");
318 if (s.uEDX & RT_BIT(29)) RTPrintf(" LongMode");
319 if (s.uEDX & RT_BIT(30)) RTPrintf(" 3DNowExt");
320 if (s.uEDX & RT_BIT(31)) RTPrintf(" 3DNow");
321 RTPrintf("\n");
322
323 RTPrintf("Features ECX: ");
324 if (s.uECX & RT_BIT(0)) RTPrintf(" LahfSahf");
325 if (s.uECX & RT_BIT(1)) RTPrintf(" CmpLegacy");
326 if (s.uECX & RT_BIT(2)) RTPrintf(" SVM");
327 if (s.uECX & RT_BIT(3)) RTPrintf(" 3");
328 if (s.uECX & RT_BIT(4)) RTPrintf(" AltMovCr8");
329 for (iBit = 5; iBit < 32; iBit++)
330 if (s.uECX & RT_BIT(iBit))
331 RTPrintf(" %d", iBit);
332 RTPrintf("\n");
333 }
334
335 char szString[4*4*3+1] = {0};
336 if (cExtFunctions >= 0x80000002)
337 ASMCpuId(0x80000002, &szString[0 + 0], &szString[0 + 4], &szString[0 + 8], &szString[0 + 12]);
338 if (cExtFunctions >= 0x80000003)
339 ASMCpuId(0x80000003, &szString[16 + 0], &szString[16 + 4], &szString[16 + 8], &szString[16 + 12]);
340 if (cExtFunctions >= 0x80000004)
341 ASMCpuId(0x80000004, &szString[32 + 0], &szString[32 + 4], &szString[32 + 8], &szString[32 + 12]);
342 if (cExtFunctions >= 0x80000002)
343 RTPrintf("Full Name: %s\n", szString);
344
345 if (cExtFunctions >= 0x80000005)
346 {
347 ASMCpuId(0x80000005, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
348 RTPrintf("TLB 2/4M Instr/Uni: %s %3d entries\n"
349 "TLB 2/4M Data: %s %3d entries\n",
350 getCacheAss((s.uEAX >> 8) & 0xff), (s.uEAX >> 0) & 0xff,
351 getCacheAss((s.uEAX >> 24) & 0xff), (s.uEAX >> 16) & 0xff);
352 RTPrintf("TLB 4K Instr/Uni: %s %3d entries\n"
353 "TLB 4K Data: %s %3d entries\n",
354 getCacheAss((s.uEBX >> 8) & 0xff), (s.uEBX >> 0) & 0xff,
355 getCacheAss((s.uEBX >> 24) & 0xff), (s.uEBX >> 16) & 0xff);
356 RTPrintf("L1 Instr Cache Line Size: %d bytes\n"
357 "L1 Instr Cache Lines Per Tag: %d\n"
358 "L1 Instr Cache Associativity: %s\n"
359 "L1 Instr Cache Size: %d KB\n",
360 (s.uEDX >> 0) & 0xff,
361 (s.uEDX >> 8) & 0xff,
362 getCacheAss((s.uEDX >> 16) & 0xff),
363 (s.uEDX >> 24) & 0xff);
364 RTPrintf("L1 Data Cache Line Size: %d bytes\n"
365 "L1 Data Cache Lines Per Tag: %d\n"
366 "L1 Data Cache Associativity: %s\n"
367 "L1 Data Cache Size: %d KB\n",
368 (s.uECX >> 0) & 0xff,
369 (s.uECX >> 8) & 0xff,
370 getCacheAss((s.uECX >> 16) & 0xff),
371 (s.uECX >> 24) & 0xff);
372 }
373
374 if (cExtFunctions >= 0x80000006)
375 {
376 ASMCpuId(0x80000006, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
377 RTPrintf("L2 TLB 2/4M Instr/Uni: %s %4d entries\n"
378 "L2 TLB 2/4M Data: %s %4d entries\n",
379 getL2CacheAss((s.uEAX >> 12) & 0xf), (s.uEAX >> 0) & 0xfff,
380 getL2CacheAss((s.uEAX >> 28) & 0xf), (s.uEAX >> 16) & 0xfff);
381 RTPrintf("L2 TLB 4K Instr/Uni: %s %4d entries\n"
382 "L2 TLB 4K Data: %s %4d entries\n",
383 getL2CacheAss((s.uEBX >> 12) & 0xf), (s.uEBX >> 0) & 0xfff,
384 getL2CacheAss((s.uEBX >> 28) & 0xf), (s.uEBX >> 16) & 0xfff);
385 RTPrintf("L2 Cache Line Size: %d bytes\n"
386 "L2 Cache Lines Per Tag: %d\n"
387 "L2 Cache Associativity: %s\n"
388 "L2 Cache Size: %d KB\n",
389 (s.uEDX >> 0) & 0xff,
390 (s.uEDX >> 8) & 0xf,
391 getL2CacheAss((s.uEDX >> 12) & 0xf),
392 (s.uEDX >> 16) & 0xffff);
393 }
394
395 if (cExtFunctions >= 0x80000007)
396 {
397 ASMCpuId(0x80000007, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
398 RTPrintf("APM Features: ");
399 if (s.uEDX & RT_BIT(0)) RTPrintf(" TS");
400 if (s.uEDX & RT_BIT(1)) RTPrintf(" FID");
401 if (s.uEDX & RT_BIT(2)) RTPrintf(" VID");
402 if (s.uEDX & RT_BIT(3)) RTPrintf(" TTP");
403 if (s.uEDX & RT_BIT(4)) RTPrintf(" TM");
404 if (s.uEDX & RT_BIT(5)) RTPrintf(" STC");
405 if (s.uEDX & RT_BIT(6)) RTPrintf(" 6");
406 if (s.uEDX & RT_BIT(7)) RTPrintf(" 7");
407 if (s.uEDX & RT_BIT(8)) RTPrintf(" TscInvariant");
408 for (iBit = 9; iBit < 32; iBit++)
409 if (s.uEDX & RT_BIT(iBit))
410 RTPrintf(" %d", iBit);
411 RTPrintf("\n");
412 }
413
414 if (cExtFunctions >= 0x80000008)
415 {
416 ASMCpuId(0x80000008, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
417 RTPrintf("Physical Address Width: %d bits\n"
418 "Virtual Address Width: %d bits\n",
419 (s.uEAX >> 0) & 0xff,
420 (s.uEAX >> 8) & 0xff);
421 RTPrintf("Physical Core Count: %d\n",
422 ((s.uECX >> 0) & 0xff) + 1);
423 if ((s.uECX >> 12) & 0xf)
424 RTPrintf("ApicIdCoreIdSize: %d bits\n", (s.uECX >> 12) & 0xf);
425 }
426
427 if (cExtFunctions >= 0x8000000a)
428 {
429 ASMCpuId(0x8000000a, &s.uEAX, &s.uEBX, &s.uECX, &s.uEDX);
430 RTPrintf("SVM Revision: %d (%#x)\n"
431 "Number of Address Space IDs: %d (%#x)\n",
432 s.uEAX & 0xff, s.uEAX & 0xff,
433 s.uEBX, s.uEBX);
434 }
435}
436#endif /* !PIC || !X86 */
437
438
439static void tstASMAtomicXchgU8(void)
440{
441 struct
442 {
443 uint8_t u8Dummy0;
444 uint8_t u8;
445 uint8_t u8Dummy1;
446 } s;
447
448 s.u8 = 0;
449 s.u8Dummy0 = s.u8Dummy1 = 0x42;
450 CHECKOP(ASMAtomicXchgU8(&s.u8, 1), 0, "%#x", uint8_t);
451 CHECKVAL(s.u8, 1, "%#x");
452
453 CHECKOP(ASMAtomicXchgU8(&s.u8, 0), 1, "%#x", uint8_t);
454 CHECKVAL(s.u8, 0, "%#x");
455
456 CHECKOP(ASMAtomicXchgU8(&s.u8, 0xff), 0, "%#x", uint8_t);
457 CHECKVAL(s.u8, 0xff, "%#x");
458
459 CHECKOP(ASMAtomicXchgU8(&s.u8, 0x87), 0xffff, "%#x", uint8_t);
460 CHECKVAL(s.u8, 0x87, "%#x");
461 CHECKVAL(s.u8Dummy0, 0x42, "%#x");
462 CHECKVAL(s.u8Dummy1, 0x42, "%#x");
463}
464
465
466static void tstASMAtomicXchgU16(void)
467{
468 struct
469 {
470 uint16_t u16Dummy0;
471 uint16_t u16;
472 uint16_t u16Dummy1;
473 } s;
474
475 s.u16 = 0;
476 s.u16Dummy0 = s.u16Dummy1 = 0x1234;
477 CHECKOP(ASMAtomicXchgU16(&s.u16, 1), 0, "%#x", uint16_t);
478 CHECKVAL(s.u16, 1, "%#x");
479
480 CHECKOP(ASMAtomicXchgU16(&s.u16, 0), 1, "%#x", uint16_t);
481 CHECKVAL(s.u16, 0, "%#x");
482
483 CHECKOP(ASMAtomicXchgU16(&s.u16, 0xffff), 0, "%#x", uint16_t);
484 CHECKVAL(s.u16, 0xffff, "%#x");
485
486 CHECKOP(ASMAtomicXchgU16(&s.u16, 0x8765), 0xffff, "%#x", uint16_t);
487 CHECKVAL(s.u16, 0x8765, "%#x");
488 CHECKVAL(s.u16Dummy0, 0x1234, "%#x");
489 CHECKVAL(s.u16Dummy1, 0x1234, "%#x");
490}
491
492
493static void tstASMAtomicXchgU32(void)
494{
495 struct
496 {
497 uint32_t u32Dummy0;
498 uint32_t u32;
499 uint32_t u32Dummy1;
500 } s;
501
502 s.u32 = 0;
503 s.u32Dummy0 = s.u32Dummy1 = 0x11223344;
504
505 CHECKOP(ASMAtomicXchgU32(&s.u32, 1), 0, "%#x", uint32_t);
506 CHECKVAL(s.u32, 1, "%#x");
507
508 CHECKOP(ASMAtomicXchgU32(&s.u32, 0), 1, "%#x", uint32_t);
509 CHECKVAL(s.u32, 0, "%#x");
510
511 CHECKOP(ASMAtomicXchgU32(&s.u32, ~0U), 0, "%#x", uint32_t);
512 CHECKVAL(s.u32, ~0U, "%#x");
513
514 CHECKOP(ASMAtomicXchgU32(&s.u32, 0x87654321), ~0U, "%#x", uint32_t);
515 CHECKVAL(s.u32, 0x87654321, "%#x");
516
517 CHECKVAL(s.u32Dummy0, 0x11223344, "%#x");
518 CHECKVAL(s.u32Dummy1, 0x11223344, "%#x");
519}
520
521
522static void tstASMAtomicXchgU64(void)
523{
524 struct
525 {
526 uint64_t u64Dummy0;
527 uint64_t u64;
528 uint64_t u64Dummy1;
529 } s;
530
531 s.u64 = 0;
532 s.u64Dummy0 = s.u64Dummy1 = 0x1122334455667788ULL;
533
534 CHECKOP(ASMAtomicXchgU64(&s.u64, 1), 0ULL, "%#llx", uint64_t);
535 CHECKVAL(s.u64, 1ULL, "%#llx");
536
537 CHECKOP(ASMAtomicXchgU64(&s.u64, 0), 1ULL, "%#llx", uint64_t);
538 CHECKVAL(s.u64, 0ULL, "%#llx");
539
540 CHECKOP(ASMAtomicXchgU64(&s.u64, ~0ULL), 0ULL, "%#llx", uint64_t);
541 CHECKVAL(s.u64, ~0ULL, "%#llx");
542
543 CHECKOP(ASMAtomicXchgU64(&s.u64, 0xfedcba0987654321ULL), ~0ULL, "%#llx", uint64_t);
544 CHECKVAL(s.u64, 0xfedcba0987654321ULL, "%#llx");
545
546 CHECKVAL(s.u64Dummy0, 0x1122334455667788ULL, "%#llx");
547 CHECKVAL(s.u64Dummy1, 0x1122334455667788ULL, "%#llx");
548}
549
550
551static void tstASMAtomicXchgPtr(void)
552{
553 void *pv = NULL;
554
555 CHECKOP(ASMAtomicXchgPtr(&pv, (void *)(~(uintptr_t)0)), NULL, "%p", void *);
556 CHECKVAL(pv, (void *)(~(uintptr_t)0), "%p");
557
558 CHECKOP(ASMAtomicXchgPtr(&pv, (void *)0x87654321), (void *)(~(uintptr_t)0), "%p", void *);
559 CHECKVAL(pv, (void *)0x87654321, "%p");
560
561 CHECKOP(ASMAtomicXchgPtr(&pv, NULL), (void *)0x87654321, "%p", void *);
562 CHECKVAL(pv, NULL, "%p");
563}
564
565
566static void tstASMAtomicCmpXchgU8(void)
567{
568 struct
569 {
570 uint8_t u8Before;
571 uint8_t u8;
572 uint8_t u8After;
573 } u = { 0xcc, 0xff, 0xaa };
574
575 CHECKOP(ASMAtomicCmpXchgU8(&u.u8, 0, 0), false, "%d", bool);
576 CHECKVAL(u.u8, 0xff, "%x"); CHECKVAL(u.u8Before, 0xcc, "%x"); CHECKVAL(u.u8After, 0xaa, "%x");
577
578 CHECKOP(ASMAtomicCmpXchgU8(&u.u8, 0, 0xff), true, "%d", bool);
579 CHECKVAL(u.u8, 0, "%x"); CHECKVAL(u.u8Before, 0xcc, "%x"); CHECKVAL(u.u8After, 0xaa, "%x");
580
581 CHECKOP(ASMAtomicCmpXchgU8(&u.u8, 0x79, 0xff), false, "%d", bool);
582 CHECKVAL(u.u8, 0, "%x"); CHECKVAL(u.u8Before, 0xcc, "%x"); CHECKVAL(u.u8After, 0xaa, "%x");
583
584 CHECKOP(ASMAtomicCmpXchgU8(&u.u8, 0x97, 0), true, "%d", bool);
585 CHECKVAL(u.u8, 0x97, "%x"); CHECKVAL(u.u8Before, 0xcc, "%x"); CHECKVAL(u.u8After, 0xaa, "%x");
586}
587
588
589static void tstASMAtomicCmpXchgU32(void)
590{
591 uint32_t u32 = 0xffffffff;
592
593 CHECKOP(ASMAtomicCmpXchgU32(&u32, 0, 0), false, "%d", bool);
594 CHECKVAL(u32, 0xffffffff, "%x");
595
596 CHECKOP(ASMAtomicCmpXchgU32(&u32, 0, 0xffffffff), true, "%d", bool);
597 CHECKVAL(u32, 0, "%x");
598
599 CHECKOP(ASMAtomicCmpXchgU32(&u32, 0x8008efd, 0xffffffff), false, "%d", bool);
600 CHECKVAL(u32, 0, "%x");
601
602 CHECKOP(ASMAtomicCmpXchgU32(&u32, 0x8008efd, 0), true, "%d", bool);
603 CHECKVAL(u32, 0x8008efd, "%x");
604}
605
606
607static void tstASMAtomicCmpXchgU64(void)
608{
609 uint64_t u64 = 0xffffffffffffffULL;
610
611 CHECKOP(ASMAtomicCmpXchgU64(&u64, 0, 0), false, "%d", bool);
612 CHECKVAL(u64, 0xffffffffffffffULL, "%#llx");
613
614 CHECKOP(ASMAtomicCmpXchgU64(&u64, 0, 0xffffffffffffffULL), true, "%d", bool);
615 CHECKVAL(u64, 0, "%x");
616
617 CHECKOP(ASMAtomicCmpXchgU64(&u64, 0x80040008008efdULL, 0xffffffff), false, "%d", bool);
618 CHECKVAL(u64, 0, "%x");
619
620 CHECKOP(ASMAtomicCmpXchgU64(&u64, 0x80040008008efdULL, 0xffffffff00000000ULL), false, "%d", bool);
621 CHECKVAL(u64, 0, "%x");
622
623 CHECKOP(ASMAtomicCmpXchgU64(&u64, 0x80040008008efdULL, 0), true, "%d", bool);
624 CHECKVAL(u64, 0x80040008008efdULL, "%#llx");
625}
626
627
628static void tstASMAtomicCmpXchgExU32(void)
629{
630 uint32_t u32 = 0xffffffff;
631 uint32_t u32Old = 0x80005111;
632
633 CHECKOP(ASMAtomicCmpXchgExU32(&u32, 0, 0, &u32Old), false, "%d", bool);
634 CHECKVAL(u32, 0xffffffff, "%x");
635 CHECKVAL(u32Old, 0xffffffff, "%x");
636
637 CHECKOP(ASMAtomicCmpXchgExU32(&u32, 0, 0xffffffff, &u32Old), true, "%d", bool);
638 CHECKVAL(u32, 0, "%x");
639 CHECKVAL(u32Old, 0xffffffff, "%x");
640
641 CHECKOP(ASMAtomicCmpXchgExU32(&u32, 0x8008efd, 0xffffffff, &u32Old), false, "%d", bool);
642 CHECKVAL(u32, 0, "%x");
643 CHECKVAL(u32Old, 0, "%x");
644
645 CHECKOP(ASMAtomicCmpXchgExU32(&u32, 0x8008efd, 0, &u32Old), true, "%d", bool);
646 CHECKVAL(u32, 0x8008efd, "%x");
647 CHECKVAL(u32Old, 0, "%x");
648
649 CHECKOP(ASMAtomicCmpXchgExU32(&u32, 0, 0x8008efd, &u32Old), true, "%d", bool);
650 CHECKVAL(u32, 0, "%x");
651 CHECKVAL(u32Old, 0x8008efd, "%x");
652}
653
654
655static void tstASMAtomicCmpXchgExU64(void)
656{
657 uint64_t u64 = 0xffffffffffffffffULL;
658 uint64_t u64Old = 0x8000000051111111ULL;
659
660 CHECKOP(ASMAtomicCmpXchgExU64(&u64, 0, 0, &u64Old), false, "%d", bool);
661 CHECKVAL(u64, 0xffffffffffffffffULL, "%llx");
662 CHECKVAL(u64Old, 0xffffffffffffffffULL, "%llx");
663
664 CHECKOP(ASMAtomicCmpXchgExU64(&u64, 0, 0xffffffffffffffffULL, &u64Old), true, "%d", bool);
665 CHECKVAL(u64, 0ULL, "%llx");
666 CHECKVAL(u64Old, 0xffffffffffffffffULL, "%llx");
667
668 CHECKOP(ASMAtomicCmpXchgExU64(&u64, 0x80040008008efdULL, 0xffffffff, &u64Old), false, "%d", bool);
669 CHECKVAL(u64, 0ULL, "%llx");
670 CHECKVAL(u64Old, 0ULL, "%llx");
671
672 CHECKOP(ASMAtomicCmpXchgExU64(&u64, 0x80040008008efdULL, 0xffffffff00000000ULL, &u64Old), false, "%d", bool);
673 CHECKVAL(u64, 0ULL, "%llx");
674 CHECKVAL(u64Old, 0ULL, "%llx");
675
676 CHECKOP(ASMAtomicCmpXchgExU64(&u64, 0x80040008008efdULL, 0, &u64Old), true, "%d", bool);
677 CHECKVAL(u64, 0x80040008008efdULL, "%llx");
678 CHECKVAL(u64Old, 0ULL, "%llx");
679
680 CHECKOP(ASMAtomicCmpXchgExU64(&u64, 0, 0x80040008008efdULL, &u64Old), true, "%d", bool);
681 CHECKVAL(u64, 0ULL, "%llx");
682 CHECKVAL(u64Old, 0x80040008008efdULL, "%llx");
683}
684
685
686static void tstASMAtomicReadU64(void)
687{
688 uint64_t u64 = 0;
689
690 CHECKOP(ASMAtomicReadU64(&u64), 0ULL, "%#llx", uint64_t);
691 CHECKVAL(u64, 0ULL, "%#llx");
692
693 u64 = ~0ULL;
694 CHECKOP(ASMAtomicReadU64(&u64), ~0ULL, "%#llx", uint64_t);
695 CHECKVAL(u64, ~0ULL, "%#llx");
696
697 u64 = 0xfedcba0987654321ULL;
698 CHECKOP(ASMAtomicReadU64(&u64), 0xfedcba0987654321ULL, "%#llx", uint64_t);
699 CHECKVAL(u64, 0xfedcba0987654321ULL, "%#llx");
700}
701
702
703static void tstASMAtomicUoReadU64(void)
704{
705 uint64_t u64 = 0;
706
707 CHECKOP(ASMAtomicUoReadU64(&u64), 0ULL, "%#llx", uint64_t);
708 CHECKVAL(u64, 0ULL, "%#llx");
709
710 u64 = ~0ULL;
711 CHECKOP(ASMAtomicUoReadU64(&u64), ~0ULL, "%#llx", uint64_t);
712 CHECKVAL(u64, ~0ULL, "%#llx");
713
714 u64 = 0xfedcba0987654321ULL;
715 CHECKOP(ASMAtomicUoReadU64(&u64), 0xfedcba0987654321ULL, "%#llx", uint64_t);
716 CHECKVAL(u64, 0xfedcba0987654321ULL, "%#llx");
717}
718
719
720static void tstASMAtomicAddS32(void)
721{
722 int32_t i32Rc;
723 int32_t i32 = 10;
724#define MYCHECK(op, rc, val) \
725 do { \
726 i32Rc = op; \
727 if (i32Rc != (rc)) \
728 { \
729 RTPrintf("%s, %d: FAILURE: %s -> %d expected %d\n", __FUNCTION__, __LINE__, #op, i32Rc, rc); \
730 RTTestIErrorInc(); \
731 } \
732 if (i32 != (val)) \
733 { \
734 RTPrintf("%s, %d: FAILURE: %s => i32=%d expected %d\n", __FUNCTION__, __LINE__, #op, i32, val); \
735 RTTestIErrorInc(); \
736 } \
737 } while (0)
738 MYCHECK(ASMAtomicAddS32(&i32, 1), 10, 11);
739 MYCHECK(ASMAtomicAddS32(&i32, -2), 11, 9);
740 MYCHECK(ASMAtomicAddS32(&i32, -9), 9, 0);
741 MYCHECK(ASMAtomicAddS32(&i32, -0x7fffffff), 0, -0x7fffffff);
742 MYCHECK(ASMAtomicAddS32(&i32, 0), -0x7fffffff, -0x7fffffff);
743 MYCHECK(ASMAtomicAddS32(&i32, 0x7fffffff), -0x7fffffff, 0);
744 MYCHECK(ASMAtomicAddS32(&i32, 0), 0, 0);
745#undef MYCHECK
746}
747
748
749static void tstASMAtomicDecIncS32(void)
750{
751 int32_t i32Rc;
752 int32_t i32 = 10;
753#define MYCHECK(op, rc) \
754 do { \
755 i32Rc = op; \
756 if (i32Rc != (rc)) \
757 { \
758 RTPrintf("%s, %d: FAILURE: %s -> %d expected %d\n", __FUNCTION__, __LINE__, #op, i32Rc, rc); \
759 RTTestIErrorInc(); \
760 } \
761 if (i32 != (rc)) \
762 { \
763 RTPrintf("%s, %d: FAILURE: %s => i32=%d expected %d\n", __FUNCTION__, __LINE__, #op, i32, rc); \
764 RTTestIErrorInc(); \
765 } \
766 } while (0)
767 MYCHECK(ASMAtomicDecS32(&i32), 9);
768 MYCHECK(ASMAtomicDecS32(&i32), 8);
769 MYCHECK(ASMAtomicDecS32(&i32), 7);
770 MYCHECK(ASMAtomicDecS32(&i32), 6);
771 MYCHECK(ASMAtomicDecS32(&i32), 5);
772 MYCHECK(ASMAtomicDecS32(&i32), 4);
773 MYCHECK(ASMAtomicDecS32(&i32), 3);
774 MYCHECK(ASMAtomicDecS32(&i32), 2);
775 MYCHECK(ASMAtomicDecS32(&i32), 1);
776 MYCHECK(ASMAtomicDecS32(&i32), 0);
777 MYCHECK(ASMAtomicDecS32(&i32), -1);
778 MYCHECK(ASMAtomicDecS32(&i32), -2);
779 MYCHECK(ASMAtomicIncS32(&i32), -1);
780 MYCHECK(ASMAtomicIncS32(&i32), 0);
781 MYCHECK(ASMAtomicIncS32(&i32), 1);
782 MYCHECK(ASMAtomicIncS32(&i32), 2);
783 MYCHECK(ASMAtomicIncS32(&i32), 3);
784 MYCHECK(ASMAtomicDecS32(&i32), 2);
785 MYCHECK(ASMAtomicIncS32(&i32), 3);
786 MYCHECK(ASMAtomicDecS32(&i32), 2);
787 MYCHECK(ASMAtomicIncS32(&i32), 3);
788#undef MYCHECK
789}
790
791
792static void tstASMAtomicAndOrU32(void)
793{
794 uint32_t u32 = 0xffffffff;
795
796 ASMAtomicOrU32(&u32, 0xffffffff);
797 CHECKVAL(u32, 0xffffffff, "%x");
798
799 ASMAtomicAndU32(&u32, 0xffffffff);
800 CHECKVAL(u32, 0xffffffff, "%x");
801
802 ASMAtomicAndU32(&u32, 0x8f8f8f8f);
803 CHECKVAL(u32, 0x8f8f8f8f, "%x");
804
805 ASMAtomicOrU32(&u32, 0x70707070);
806 CHECKVAL(u32, 0xffffffff, "%x");
807
808 ASMAtomicAndU32(&u32, 1);
809 CHECKVAL(u32, 1, "%x");
810
811 ASMAtomicOrU32(&u32, 0x80000000);
812 CHECKVAL(u32, 0x80000001, "%x");
813
814 ASMAtomicAndU32(&u32, 0x80000000);
815 CHECKVAL(u32, 0x80000000, "%x");
816
817 ASMAtomicAndU32(&u32, 0);
818 CHECKVAL(u32, 0, "%x");
819
820 ASMAtomicOrU32(&u32, 0x42424242);
821 CHECKVAL(u32, 0x42424242, "%x");
822}
823
824
825void tstASMMemZeroPage(void)
826{
827 struct
828 {
829 uint64_t u64Magic1;
830 uint8_t abPage[PAGE_SIZE];
831 uint64_t u64Magic2;
832 } Buf1, Buf2, Buf3;
833
834 Buf1.u64Magic1 = UINT64_C(0xffffffffffffffff);
835 memset(Buf1.abPage, 0x55, sizeof(Buf1.abPage));
836 Buf1.u64Magic2 = UINT64_C(0xffffffffffffffff);
837 Buf2.u64Magic1 = UINT64_C(0xffffffffffffffff);
838 memset(Buf2.abPage, 0x77, sizeof(Buf2.abPage));
839 Buf2.u64Magic2 = UINT64_C(0xffffffffffffffff);
840 Buf3.u64Magic1 = UINT64_C(0xffffffffffffffff);
841 memset(Buf3.abPage, 0x99, sizeof(Buf3.abPage));
842 Buf3.u64Magic2 = UINT64_C(0xffffffffffffffff);
843 ASMMemZeroPage(Buf1.abPage);
844 ASMMemZeroPage(Buf2.abPage);
845 ASMMemZeroPage(Buf3.abPage);
846 if ( Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
847 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
848 || Buf2.u64Magic1 != UINT64_C(0xffffffffffffffff)
849 || Buf2.u64Magic2 != UINT64_C(0xffffffffffffffff)
850 || Buf3.u64Magic1 != UINT64_C(0xffffffffffffffff)
851 || Buf3.u64Magic2 != UINT64_C(0xffffffffffffffff))
852 {
853 RTPrintf("tstInlineAsm: ASMMemZeroPage violated one/both magic(s)!\n");
854 RTTestIErrorInc();
855 }
856 for (unsigned i = 0; i < sizeof(Buf1.abPage); i++)
857 if (Buf1.abPage[i])
858 {
859 RTPrintf("tstInlineAsm: ASMMemZeroPage didn't clear byte at offset %#x!\n", i);
860 RTTestIErrorInc();
861 }
862 for (unsigned i = 0; i < sizeof(Buf2.abPage); i++)
863 if (Buf2.abPage[i])
864 {
865 RTPrintf("tstInlineAsm: ASMMemZeroPage didn't clear byte at offset %#x!\n", i);
866 RTTestIErrorInc();
867 }
868 for (unsigned i = 0; i < sizeof(Buf3.abPage); i++)
869 if (Buf3.abPage[i])
870 {
871 RTPrintf("tstInlineAsm: ASMMemZeroPage didn't clear byte at offset %#x!\n", i);
872 RTTestIErrorInc();
873 }
874}
875
876
877void tstASMMemIsZeroPage(RTTEST hTest)
878{
879 RTTestSub(hTest, "ASMMemIsZeroPage");
880
881 void *pvPage1 = RTTestGuardedAllocHead(hTest, PAGE_SIZE);
882 void *pvPage2 = RTTestGuardedAllocTail(hTest, PAGE_SIZE);
883 RTTESTI_CHECK_RETV(pvPage1 && pvPage2);
884
885 memset(pvPage1, 0, PAGE_SIZE);
886 memset(pvPage2, 0, PAGE_SIZE);
887 RTTESTI_CHECK(ASMMemIsZeroPage(pvPage1));
888 RTTESTI_CHECK(ASMMemIsZeroPage(pvPage2));
889
890 memset(pvPage1, 0xff, PAGE_SIZE);
891 memset(pvPage2, 0xff, PAGE_SIZE);
892 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage1));
893 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage2));
894
895 memset(pvPage1, 0, PAGE_SIZE);
896 memset(pvPage2, 0, PAGE_SIZE);
897 for (unsigned off = 0; off < PAGE_SIZE; off++)
898 {
899 ((uint8_t *)pvPage1)[off] = 1;
900 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage1));
901 ((uint8_t *)pvPage1)[off] = 0;
902
903 ((uint8_t *)pvPage2)[off] = 0x80;
904 RTTESTI_CHECK(!ASMMemIsZeroPage(pvPage2));
905 ((uint8_t *)pvPage2)[off] = 0;
906 }
907
908 RTTestSubDone(hTest);
909}
910
911
912void tstASMMemZero32(void)
913{
914 struct
915 {
916 uint64_t u64Magic1;
917 uint8_t abPage[PAGE_SIZE - 32];
918 uint64_t u64Magic2;
919 } Buf1, Buf2, Buf3;
920
921 Buf1.u64Magic1 = UINT64_C(0xffffffffffffffff);
922 memset(Buf1.abPage, 0x55, sizeof(Buf1.abPage));
923 Buf1.u64Magic2 = UINT64_C(0xffffffffffffffff);
924 Buf2.u64Magic1 = UINT64_C(0xffffffffffffffff);
925 memset(Buf2.abPage, 0x77, sizeof(Buf2.abPage));
926 Buf2.u64Magic2 = UINT64_C(0xffffffffffffffff);
927 Buf3.u64Magic1 = UINT64_C(0xffffffffffffffff);
928 memset(Buf3.abPage, 0x99, sizeof(Buf3.abPage));
929 Buf3.u64Magic2 = UINT64_C(0xffffffffffffffff);
930 ASMMemZero32(Buf1.abPage, sizeof(Buf1.abPage));
931 ASMMemZero32(Buf2.abPage, sizeof(Buf2.abPage));
932 ASMMemZero32(Buf3.abPage, sizeof(Buf3.abPage));
933 if ( Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
934 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
935 || Buf2.u64Magic1 != UINT64_C(0xffffffffffffffff)
936 || Buf2.u64Magic2 != UINT64_C(0xffffffffffffffff)
937 || Buf3.u64Magic1 != UINT64_C(0xffffffffffffffff)
938 || Buf3.u64Magic2 != UINT64_C(0xffffffffffffffff))
939 {
940 RTPrintf("tstInlineAsm: ASMMemZero32 violated one/both magic(s)!\n");
941 RTTestIErrorInc();
942 }
943 for (unsigned i = 0; i < RT_ELEMENTS(Buf1.abPage); i++)
944 if (Buf1.abPage[i])
945 {
946 RTPrintf("tstInlineAsm: ASMMemZero32 didn't clear byte at offset %#x!\n", i);
947 RTTestIErrorInc();
948 }
949 for (unsigned i = 0; i < RT_ELEMENTS(Buf2.abPage); i++)
950 if (Buf2.abPage[i])
951 {
952 RTPrintf("tstInlineAsm: ASMMemZero32 didn't clear byte at offset %#x!\n", i);
953 RTTestIErrorInc();
954 }
955 for (unsigned i = 0; i < RT_ELEMENTS(Buf3.abPage); i++)
956 if (Buf3.abPage[i])
957 {
958 RTPrintf("tstInlineAsm: ASMMemZero32 didn't clear byte at offset %#x!\n", i);
959 RTTestIErrorInc();
960 }
961}
962
963
964void tstASMMemFill32(void)
965{
966 struct
967 {
968 uint64_t u64Magic1;
969 uint32_t au32Page[PAGE_SIZE / 4];
970 uint64_t u64Magic2;
971 } Buf1;
972 struct
973 {
974 uint64_t u64Magic1;
975 uint32_t au32Page[(PAGE_SIZE / 4) - 3];
976 uint64_t u64Magic2;
977 } Buf2;
978 struct
979 {
980 uint64_t u64Magic1;
981 uint32_t au32Page[(PAGE_SIZE / 4) - 1];
982 uint64_t u64Magic2;
983 } Buf3;
984
985 Buf1.u64Magic1 = UINT64_C(0xffffffffffffffff);
986 memset(Buf1.au32Page, 0x55, sizeof(Buf1.au32Page));
987 Buf1.u64Magic2 = UINT64_C(0xffffffffffffffff);
988 Buf2.u64Magic1 = UINT64_C(0xffffffffffffffff);
989 memset(Buf2.au32Page, 0x77, sizeof(Buf2.au32Page));
990 Buf2.u64Magic2 = UINT64_C(0xffffffffffffffff);
991 Buf3.u64Magic1 = UINT64_C(0xffffffffffffffff);
992 memset(Buf3.au32Page, 0x99, sizeof(Buf3.au32Page));
993 Buf3.u64Magic2 = UINT64_C(0xffffffffffffffff);
994 ASMMemFill32(Buf1.au32Page, sizeof(Buf1.au32Page), 0xdeadbeef);
995 ASMMemFill32(Buf2.au32Page, sizeof(Buf2.au32Page), 0xcafeff01);
996 ASMMemFill32(Buf3.au32Page, sizeof(Buf3.au32Page), 0xf00dd00f);
997 if ( Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
998 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
999 || Buf2.u64Magic1 != UINT64_C(0xffffffffffffffff)
1000 || Buf2.u64Magic2 != UINT64_C(0xffffffffffffffff)
1001 || Buf3.u64Magic1 != UINT64_C(0xffffffffffffffff)
1002 || Buf3.u64Magic2 != UINT64_C(0xffffffffffffffff))
1003 {
1004 RTPrintf("tstInlineAsm: ASMMemFill32 violated one/both magic(s)!\n");
1005 RTTestIErrorInc();
1006 }
1007 for (unsigned i = 0; i < RT_ELEMENTS(Buf1.au32Page); i++)
1008 if (Buf1.au32Page[i] != 0xdeadbeef)
1009 {
1010 RTPrintf("tstInlineAsm: ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf1.au32Page[i], 0xdeadbeef);
1011 RTTestIErrorInc();
1012 }
1013 for (unsigned i = 0; i < RT_ELEMENTS(Buf2.au32Page); i++)
1014 if (Buf2.au32Page[i] != 0xcafeff01)
1015 {
1016 RTPrintf("tstInlineAsm: ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf2.au32Page[i], 0xcafeff01);
1017 RTTestIErrorInc();
1018 }
1019 for (unsigned i = 0; i < RT_ELEMENTS(Buf3.au32Page); i++)
1020 if (Buf3.au32Page[i] != 0xf00dd00f)
1021 {
1022 RTPrintf("tstInlineAsm: ASMMemFill32 %#x: %#x exepcted %#x\n", i, Buf3.au32Page[i], 0xf00dd00f);
1023 RTTestIErrorInc();
1024 }
1025}
1026
1027
1028
1029void tstASMMath(void)
1030{
1031 uint64_t u64 = ASMMult2xU32RetU64(UINT32_C(0x80000000), UINT32_C(0x10000000));
1032 CHECKVAL(u64, UINT64_C(0x0800000000000000), "%#018RX64");
1033
1034 uint32_t u32 = ASMDivU64ByU32RetU32(UINT64_C(0x0800000000000000), UINT32_C(0x10000000));
1035 CHECKVAL(u32, UINT32_C(0x80000000), "%#010RX32");
1036
1037 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x0000000000000001), UINT32_C(0x00000001), UINT32_C(0x00000001));
1038 CHECKVAL(u64, UINT64_C(0x0000000000000001), "%#018RX64");
1039 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x0000000100000000), UINT32_C(0x80000000), UINT32_C(0x00000002));
1040 CHECKVAL(u64, UINT64_C(0x4000000000000000), "%#018RX64");
1041 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xfedcba9876543210), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1042 CHECKVAL(u64, UINT64_C(0xfedcba9876543210), "%#018RX64");
1043 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xffffffffffffffff), UINT32_C(0xffffffff), UINT32_C(0xffffffff));
1044 CHECKVAL(u64, UINT64_C(0xffffffffffffffff), "%#018RX64");
1045 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xffffffffffffffff), UINT32_C(0xfffffff0), UINT32_C(0xffffffff));
1046 CHECKVAL(u64, UINT64_C(0xfffffff0fffffff0), "%#018RX64");
1047 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x3415934810359583), UINT32_C(0x58734981), UINT32_C(0xf8694045));
1048 CHECKVAL(u64, UINT64_C(0x128b9c3d43184763), "%#018RX64");
1049 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0x3415934810359583), UINT32_C(0xf8694045), UINT32_C(0x58734981));
1050 CHECKVAL(u64, UINT64_C(0x924719355cd35a27), "%#018RX64");
1051
1052#if 0 /* bird: question is whether this should trap or not:
1053 *
1054 * frank: Of course it must trap:
1055 *
1056 * 0xfffffff8 * 0x77d7daf8 = 0x77d7daf441412840
1057 *
1058 * During the following division, the quotient must fit into a 32-bit register.
1059 * Therefore the smallest valid divisor is
1060 *
1061 * (0x77d7daf441412840 >> 32) + 1 = 0x77d7daf5
1062 *
1063 * which is definitely greater than 0x3b9aca00.
1064 *
1065 * bird: No, the C version does *not* crash. So, the question is whether there's any
1066 * code depending on it not crashing.
1067 *
1068 * Of course the assembly versions of the code crash right now for the reasons you've
1069 * given, but the 32-bit MSC version does not crash.
1070 *
1071 * frank: The C version does not crash but delivers incorrect results for this case.
1072 * The reason is
1073 *
1074 * u.s.Hi = (unsigned long)(u64Hi / u32C);
1075 *
1076 * Here the division is actually 64-bit by 64-bit but the 64-bit result is truncated
1077 * to 32 bit. If using this (optimized and fast) function we should just be sure that
1078 * the operands are in a valid range.
1079 */
1080 u64 = ASMMultU64ByU32DivByU32(UINT64_C(0xfffffff8c65d6731), UINT32_C(0x77d7daf8), UINT32_C(0x3b9aca00));
1081 CHECKVAL(u64, UINT64_C(0x02b8f9a2aa74e3dc), "%#018RX64");
1082#endif
1083
1084 u32 = ASMModU64ByU32RetU32(UINT64_C(0x0ffffff8c65d6731), UINT32_C(0x77d7daf8));
1085 CHECKVAL(u32, UINT32_C(0x3B642451), "%#010RX32");
1086
1087 int32_t i32;
1088 i32 = ASMModS64ByS32RetS32(INT64_C(-11), INT32_C(-2));
1089 CHECKVAL(i32, INT32_C(-1), "%010RI32");
1090 i32 = ASMModS64ByS32RetS32(INT64_C(-11), INT32_C(2));
1091 CHECKVAL(i32, INT32_C(-1), "%010RI32");
1092 i32 = ASMModS64ByS32RetS32(INT64_C(11), INT32_C(-2));
1093 CHECKVAL(i32, INT32_C(1), "%010RI32");
1094
1095 i32 = ASMModS64ByS32RetS32(INT64_C(92233720368547758), INT32_C(2147483647));
1096 CHECKVAL(i32, INT32_C(2104533974), "%010RI32");
1097 i32 = ASMModS64ByS32RetS32(INT64_C(-92233720368547758), INT32_C(2147483647));
1098 CHECKVAL(i32, INT32_C(-2104533974), "%010RI32");
1099}
1100
1101
1102void tstASMByteSwap(void)
1103{
1104 RTPrintf("tstInlineASM: TESTING - ASMByteSwap*\n");
1105
1106 uint64_t u64In = UINT64_C(0x0011223344556677);
1107 uint64_t u64Out = ASMByteSwapU64(u64In);
1108 CHECKVAL(u64In, UINT64_C(0x0011223344556677), "%#018RX64");
1109 CHECKVAL(u64Out, UINT64_C(0x7766554433221100), "%#018RX64");
1110 u64Out = ASMByteSwapU64(u64Out);
1111 CHECKVAL(u64Out, u64In, "%#018RX64");
1112 u64In = UINT64_C(0x0123456789abcdef);
1113 u64Out = ASMByteSwapU64(u64In);
1114 CHECKVAL(u64In, UINT64_C(0x0123456789abcdef), "%#018RX64");
1115 CHECKVAL(u64Out, UINT64_C(0xefcdab8967452301), "%#018RX64");
1116 u64Out = ASMByteSwapU64(u64Out);
1117 CHECKVAL(u64Out, u64In, "%#018RX64");
1118 u64In = 0;
1119 u64Out = ASMByteSwapU64(u64In);
1120 CHECKVAL(u64Out, u64In, "%#018RX64");
1121 u64In = ~(uint64_t)0;
1122 u64Out = ASMByteSwapU64(u64In);
1123 CHECKVAL(u64Out, u64In, "%#018RX64");
1124
1125 uint32_t u32In = UINT32_C(0x00112233);
1126 uint32_t u32Out = ASMByteSwapU32(u32In);
1127 CHECKVAL(u32In, UINT32_C(0x00112233), "%#010RX32");
1128 CHECKVAL(u32Out, UINT32_C(0x33221100), "%#010RX32");
1129 u32Out = ASMByteSwapU32(u32Out);
1130 CHECKVAL(u32Out, u32In, "%#010RX32");
1131 u32In = UINT32_C(0x12345678);
1132 u32Out = ASMByteSwapU32(u32In);
1133 CHECKVAL(u32In, UINT32_C(0x12345678), "%#010RX32");
1134 CHECKVAL(u32Out, UINT32_C(0x78563412), "%#010RX32");
1135 u32Out = ASMByteSwapU32(u32Out);
1136 CHECKVAL(u32Out, u32In, "%#010RX32");
1137 u32In = 0;
1138 u32Out = ASMByteSwapU32(u32In);
1139 CHECKVAL(u32Out, u32In, "%#010RX32");
1140 u32In = ~(uint32_t)0;
1141 u32Out = ASMByteSwapU32(u32In);
1142 CHECKVAL(u32Out, u32In, "%#010RX32");
1143
1144 uint16_t u16In = UINT16_C(0x0011);
1145 uint16_t u16Out = ASMByteSwapU16(u16In);
1146 CHECKVAL(u16In, UINT16_C(0x0011), "%#06RX16");
1147 CHECKVAL(u16Out, UINT16_C(0x1100), "%#06RX16");
1148 u16Out = ASMByteSwapU16(u16Out);
1149 CHECKVAL(u16Out, u16In, "%#06RX16");
1150 u16In = UINT16_C(0x1234);
1151 u16Out = ASMByteSwapU16(u16In);
1152 CHECKVAL(u16In, UINT16_C(0x1234), "%#06RX16");
1153 CHECKVAL(u16Out, UINT16_C(0x3412), "%#06RX16");
1154 u16Out = ASMByteSwapU16(u16Out);
1155 CHECKVAL(u16Out, u16In, "%#06RX16");
1156 u16In = 0;
1157 u16Out = ASMByteSwapU16(u16In);
1158 CHECKVAL(u16Out, u16In, "%#06RX16");
1159 u16In = ~(uint16_t)0;
1160 u16Out = ASMByteSwapU16(u16In);
1161 CHECKVAL(u16Out, u16In, "%#06RX16");
1162}
1163
1164
1165void tstASMBench(void)
1166{
1167 /*
1168 * Make this static. We don't want to have this located on the stack.
1169 */
1170 static uint8_t volatile s_u8;
1171 static int8_t volatile s_i8;
1172 static uint16_t volatile s_u16;
1173 static int16_t volatile s_i16;
1174 static uint32_t volatile s_u32;
1175 static int32_t volatile s_i32;
1176 static uint64_t volatile s_u64;
1177 static int64_t volatile s_i64;
1178 register unsigned i;
1179 const unsigned cRounds = 2000000;
1180 register uint64_t u64Elapsed;
1181
1182 RTPrintf("tstInlineASM: Benchmarking:\n");
1183
1184#define BENCH(op, str) \
1185 RTThreadYield(); \
1186 u64Elapsed = ASMReadTSC(); \
1187 for (i = cRounds; i > 0; i--) \
1188 op; \
1189 u64Elapsed = ASMReadTSC() - u64Elapsed; \
1190 RTPrintf(" %-30s %3llu cycles\n", str, u64Elapsed / cRounds);
1191
1192 BENCH(s_u32 = 0, "s_u32 = 0:");
1193 BENCH(ASMAtomicUoReadU8(&s_u8), "ASMAtomicUoReadU8:");
1194 BENCH(ASMAtomicUoReadS8(&s_i8), "ASMAtomicUoReadS8:");
1195 BENCH(ASMAtomicUoReadU16(&s_u16), "ASMAtomicUoReadU16:");
1196 BENCH(ASMAtomicUoReadS16(&s_i16), "ASMAtomicUoReadS16:");
1197 BENCH(ASMAtomicUoReadU32(&s_u32), "ASMAtomicUoReadU32:");
1198 BENCH(ASMAtomicUoReadS32(&s_i32), "ASMAtomicUoReadS32:");
1199 BENCH(ASMAtomicUoReadU64(&s_u64), "ASMAtomicUoReadU64:");
1200 BENCH(ASMAtomicUoReadS64(&s_i64), "ASMAtomicUoReadS64:");
1201 BENCH(ASMAtomicReadU8(&s_u8), "ASMAtomicReadU8:");
1202 BENCH(ASMAtomicReadS8(&s_i8), "ASMAtomicReadS8:");
1203 BENCH(ASMAtomicReadU16(&s_u16), "ASMAtomicReadU16:");
1204 BENCH(ASMAtomicReadS16(&s_i16), "ASMAtomicReadS16:");
1205 BENCH(ASMAtomicReadU32(&s_u32), "ASMAtomicReadU32:");
1206 BENCH(ASMAtomicReadS32(&s_i32), "ASMAtomicReadS32:");
1207 BENCH(ASMAtomicReadU64(&s_u64), "ASMAtomicReadU64:");
1208 BENCH(ASMAtomicReadS64(&s_i64), "ASMAtomicReadS64:");
1209 BENCH(ASMAtomicUoWriteU8(&s_u8, 0), "ASMAtomicUoWriteU8:");
1210 BENCH(ASMAtomicUoWriteS8(&s_i8, 0), "ASMAtomicUoWriteS8:");
1211 BENCH(ASMAtomicUoWriteU16(&s_u16, 0), "ASMAtomicUoWriteU16:");
1212 BENCH(ASMAtomicUoWriteS16(&s_i16, 0), "ASMAtomicUoWriteS16:");
1213 BENCH(ASMAtomicUoWriteU32(&s_u32, 0), "ASMAtomicUoWriteU32:");
1214 BENCH(ASMAtomicUoWriteS32(&s_i32, 0), "ASMAtomicUoWriteS32:");
1215 BENCH(ASMAtomicUoWriteU64(&s_u64, 0), "ASMAtomicUoWriteU64:");
1216 BENCH(ASMAtomicUoWriteS64(&s_i64, 0), "ASMAtomicUoWriteS64:");
1217 BENCH(ASMAtomicWriteU8(&s_u8, 0), "ASMAtomicWriteU8:");
1218 BENCH(ASMAtomicWriteS8(&s_i8, 0), "ASMAtomicWriteS8:");
1219 BENCH(ASMAtomicWriteU16(&s_u16, 0), "ASMAtomicWriteU16:");
1220 BENCH(ASMAtomicWriteS16(&s_i16, 0), "ASMAtomicWriteS16:");
1221 BENCH(ASMAtomicWriteU32(&s_u32, 0), "ASMAtomicWriteU32:");
1222 BENCH(ASMAtomicWriteS32(&s_i32, 0), "ASMAtomicWriteS32:");
1223 BENCH(ASMAtomicWriteU64(&s_u64, 0), "ASMAtomicWriteU64:");
1224 BENCH(ASMAtomicWriteS64(&s_i64, 0), "ASMAtomicWriteS64:");
1225 BENCH(ASMAtomicXchgU8(&s_u8, 0), "ASMAtomicXchgU8:");
1226 BENCH(ASMAtomicXchgS8(&s_i8, 0), "ASMAtomicXchgS8:");
1227 BENCH(ASMAtomicXchgU16(&s_u16, 0), "ASMAtomicXchgU16:");
1228 BENCH(ASMAtomicXchgS16(&s_i16, 0), "ASMAtomicXchgS16:");
1229 BENCH(ASMAtomicXchgU32(&s_u32, 0), "ASMAtomicXchgU32:");
1230 BENCH(ASMAtomicXchgS32(&s_i32, 0), "ASMAtomicXchgS32:");
1231 BENCH(ASMAtomicXchgU64(&s_u64, 0), "ASMAtomicXchgU64:");
1232 BENCH(ASMAtomicXchgS64(&s_i64, 0), "ASMAtomicXchgS64:");
1233 BENCH(ASMAtomicCmpXchgU32(&s_u32, 0, 0), "ASMAtomicCmpXchgU32:");
1234 BENCH(ASMAtomicCmpXchgS32(&s_i32, 0, 0), "ASMAtomicCmpXchgS32:");
1235 BENCH(ASMAtomicCmpXchgU64(&s_u64, 0, 0), "ASMAtomicCmpXchgU64:");
1236 BENCH(ASMAtomicCmpXchgS64(&s_i64, 0, 0), "ASMAtomicCmpXchgS64:");
1237 BENCH(ASMAtomicCmpXchgU32(&s_u32, 0, 1), "ASMAtomicCmpXchgU32/neg:");
1238 BENCH(ASMAtomicCmpXchgS32(&s_i32, 0, 1), "ASMAtomicCmpXchgS32/neg:");
1239 BENCH(ASMAtomicCmpXchgU64(&s_u64, 0, 1), "ASMAtomicCmpXchgU64/neg:");
1240 BENCH(ASMAtomicCmpXchgS64(&s_i64, 0, 1), "ASMAtomicCmpXchgS64/neg:");
1241 BENCH(ASMAtomicIncU32(&s_u32), "ASMAtomicIncU32:");
1242 BENCH(ASMAtomicIncS32(&s_i32), "ASMAtomicIncS32:");
1243 BENCH(ASMAtomicDecU32(&s_u32), "ASMAtomicDecU32:");
1244 BENCH(ASMAtomicDecS32(&s_i32), "ASMAtomicDecS32:");
1245 BENCH(ASMAtomicAddU32(&s_u32, 5), "ASMAtomicAddU32:");
1246 BENCH(ASMAtomicAddS32(&s_i32, 5), "ASMAtomicAddS32:");
1247
1248 RTPrintf("Done.\n");
1249
1250#undef BENCH
1251}
1252
1253
1254int main(int argc, char *argv[])
1255{
1256 RTTEST hTest;
1257 int rc = RTTestInitAndCreate("tstInlineAsm", &hTest);
1258 if (rc)
1259 return rc;
1260 RTTestBanner(hTest);
1261
1262 /*
1263 * Execute the tests.
1264 */
1265#if !defined(PIC) || !defined(RT_ARCH_X86)
1266 tstASMCpuId();
1267#endif
1268 tstASMAtomicXchgU8();
1269 tstASMAtomicXchgU16();
1270 tstASMAtomicXchgU32();
1271 tstASMAtomicXchgU64();
1272 tstASMAtomicXchgPtr();
1273 tstASMAtomicCmpXchgU8();
1274 tstASMAtomicCmpXchgU32();
1275 tstASMAtomicCmpXchgU64();
1276 tstASMAtomicCmpXchgExU32();
1277 tstASMAtomicCmpXchgExU64();
1278 tstASMAtomicReadU64();
1279 tstASMAtomicUoReadU64();
1280 tstASMAtomicAddS32();
1281 tstASMAtomicDecIncS32();
1282 tstASMAtomicAndOrU32();
1283 tstASMMemZeroPage();
1284 tstASMMemIsZeroPage(hTest);
1285 tstASMMemZero32();
1286 tstASMMemFill32();
1287 tstASMMath();
1288 tstASMByteSwap();
1289 tstASMBench();
1290
1291 /*
1292 * Show the result.
1293 */
1294 return RTTestSummaryAndDestroy(hTest);
1295}
1296
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