VirtualBox

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

Last change on this file since 29015 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

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