VirtualBox

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

Last change on this file since 11019 was 10995, checked in by vboxsync, 16 years ago

iprt: Added ASMByteSwapU16/64 and unit test for them + U32.

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