VirtualBox

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

Last change on this file since 19948 was 14831, checked in by vboxsync, 16 years ago

whole bunch: avoid runtime.h, include individual headers indead.

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