VirtualBox

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

Last change on this file since 584 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 27.3 KB
Line 
1/* $Id: tstInlineAsm.cpp 1 1970-01-01 00:00:00Z vboxsync $ */
2/** @file
3 * InnoTek Portable Runtime Testcase - inline assembly.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#include <iprt/asm.h>
26#include <iprt/stream.h>
27#include <iprt/string.h>
28#include <iprt/runtime.h>
29#include <iprt/param.h>
30
31
32/*******************************************************************************
33* Global Variables *
34*******************************************************************************/
35/** Global error count. */
36static unsigned g_cErrors;
37
38
39/*******************************************************************************
40* Defined Constants And Macros *
41*******************************************************************************/
42#define CHECKVAL(val, expect, fmt) \
43 do \
44 { \
45 if ((val) != (expect)) \
46 { \
47 g_cErrors++; \
48 RTPrintf("%s, %d: " #val ": expected " fmt " got " fmt "\n", __FUNCTION__, __LINE__, (expect), (val)); \
49 } \
50 } while (0)
51
52#define CHECKOP(op, expect, fmt, type) \
53 do \
54 { \
55 type val = op; \
56 if (val != (type)(expect)) \
57 { \
58 g_cErrors++; \
59 RTPrintf("%s, %d: " #op ": expected " fmt " got " fmt "\n", __FUNCTION__, __LINE__, (type)(expect), val); \
60 } \
61 } while (0)
62
63
64#ifndef PIC
65const char *getCacheAss(unsigned u)
66{
67 if (u == 0)
68 return "res0 ";
69 if (u == 1)
70 return "direct";
71 if (u >= 256)
72 return "???";
73
74 char *pszRet;
75 RTStrAPrintf(&pszRet, "%d way", u); /* intentional leak! */
76 return pszRet;
77}
78
79
80const char *getL2CacheAss(unsigned u)
81{
82 switch (u)
83 {
84 case 0: return "off ";
85 case 1: return "direct";
86 case 2: return "2 way ";
87 case 3: return "res3 ";
88 case 4: return "4 way ";
89 case 5: return "res5 ";
90 case 6: return "8 way ";
91 case 7: return "res7 ";
92 case 8: return "16 way";
93 case 9: return "res9 ";
94 case 10: return "res10 ";
95 case 11: return "res11 ";
96 case 12: return "res12 ";
97 case 13: return "res13 ";
98 case 14: return "res14 ";
99 case 15: return "fully ";
100 default:
101 return "????";
102 }
103}
104
105
106/**
107 * Test and dump all possible info from the CPUID instruction.
108 *
109 * @remark Bits shared with the libc cpuid.c program. This all written by me, so no worries.
110 * @todo transform the dumping into a generic runtime function. We'll need it for logging!
111 */
112void tstASMCpuId(void)
113{
114 unsigned iBit;
115 uint32_t uEAX, uEBX, uECX, uEDX;
116 if (!ASMHasCpuId())
117 {
118 RTPrintf("tstInlineAsm: warning! CPU doesn't support CPUID\n");
119 return;
120 }
121
122 /*
123 * Try the 0 function and use that for checking the ASMCpuId_* variants.
124 */
125 ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
126
127 uint32_t u32 = ASMCpuId_ECX(0);
128 CHECKVAL(u32, uECX, "%x");
129
130 u32 = ASMCpuId_EDX(0);
131 CHECKVAL(u32, uEDX, "%x");
132
133 uint32_t uECX2 = uECX - 1;
134 uint32_t uEDX2 = uEDX - 1;
135 ASMCpuId_ECX_EDX(0, &uECX2, &uEDX2);
136
137 CHECKVAL(uECX2, uECX, "%x");
138 CHECKVAL(uEDX2, uEDX, "%x");
139
140 /*
141 * Done testing, dump the information.
142 */
143 RTPrintf("tstInlineAsm: CPUID Dump\n");
144 ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
145 const uint32_t cFunctions = uEAX;
146
147 /* raw dump */
148 RTPrintf("\n"
149 " RAW Standard CPUIDs\n"
150 "Function eax ebx ecx edx\n");
151 for (unsigned iStd = 0; iStd <= cFunctions + 3; iStd++)
152 {
153 ASMCpuId(iStd, &uEAX, &uEBX, &uECX, &uEDX);
154 RTPrintf("%08x %08x %08x %08x %08x%s\n",
155 iStd, uEAX, uEBX, uECX, uEDX, iStd <= cFunctions ? "" : "*");
156 }
157
158 /*
159 * Understandable output
160 */
161 ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
162 RTPrintf("Name: %.04s%.04s%.04s\n"
163 "Support: 0-%u\n",
164 &uEBX, &uEDX, &uECX, uEAX);
165
166 /*
167 * Get Features.
168 */
169 if (cFunctions >= 1)
170 {
171 ASMCpuId(1, &uEAX, &uEBX, &uECX, &uEDX);
172 RTPrintf("Family: %d \tExtended: %d \tEffectiv: %d\n"
173 "Model: %d \tExtended: %d \tEffectiv: %d\n"
174 "Stepping: %d\n"
175 "APIC ID: %#04x\n"
176 "Logical CPUs: %d\n"
177 "CLFLUSH Size: %d\n"
178 "Brand ID: %#04x\n",
179 (uEAX >> 8) & 0xf, (uEAX >> 20) & 0x7f, ((uEAX >> 8) & 0xf) + (((uEAX >> 8) & 0xf) == 0xf ? (uEAX >> 20) & 0x7f : 0),
180 (uEAX >> 4) & 0xf, (uEAX >> 16) & 0x0f, ((uEAX >> 4) & 0xf) | (((uEAX >> 4) & 0xf) == 0xf ? (uEAX >> 16) & 0x0f : 0),
181 (uEAX >> 0) & 0xf,
182 (uEBX >> 24) & 0xff,
183 (uEBX >> 16) & 0xff,
184 (uEBX >> 8) & 0xff,
185 (uEBX >> 0) & 0xff);
186
187 RTPrintf("Features EDX: ");
188 if (uEDX & BIT(0)) RTPrintf(" FPU");
189 if (uEDX & BIT(1)) RTPrintf(" VME");
190 if (uEDX & BIT(2)) RTPrintf(" DE");
191 if (uEDX & BIT(3)) RTPrintf(" PSE");
192 if (uEDX & BIT(4)) RTPrintf(" TSC");
193 if (uEDX & BIT(5)) RTPrintf(" MSR");
194 if (uEDX & BIT(6)) RTPrintf(" PAE");
195 if (uEDX & BIT(7)) RTPrintf(" MCE");
196 if (uEDX & BIT(8)) RTPrintf(" CX8");
197 if (uEDX & BIT(9)) RTPrintf(" APIC");
198 if (uEDX & BIT(10)) RTPrintf(" 10");
199 if (uEDX & BIT(11)) RTPrintf(" SEP");
200 if (uEDX & BIT(12)) RTPrintf(" MTRR");
201 if (uEDX & BIT(13)) RTPrintf(" PGE");
202 if (uEDX & BIT(14)) RTPrintf(" MCA");
203 if (uEDX & BIT(15)) RTPrintf(" CMOV");
204 if (uEDX & BIT(16)) RTPrintf(" PAT");
205 if (uEDX & BIT(17)) RTPrintf(" PSE36");
206 if (uEDX & BIT(18)) RTPrintf(" PSN");
207 if (uEDX & BIT(19)) RTPrintf(" CLFSH");
208 if (uEDX & BIT(20)) RTPrintf(" 20");
209 if (uEDX & BIT(21)) RTPrintf(" DS");
210 if (uEDX & BIT(22)) RTPrintf(" ACPI");
211 if (uEDX & BIT(23)) RTPrintf(" MMX");
212 if (uEDX & BIT(24)) RTPrintf(" FXSR");
213 if (uEDX & BIT(25)) RTPrintf(" SSE");
214 if (uEDX & BIT(26)) RTPrintf(" SSE2");
215 if (uEDX & BIT(27)) RTPrintf(" SS");
216 if (uEDX & BIT(28)) RTPrintf(" HTT");
217 if (uEDX & BIT(29)) RTPrintf(" 29");
218 if (uEDX & BIT(30)) RTPrintf(" 30");
219 if (uEDX & BIT(31)) RTPrintf(" 31");
220 RTPrintf("\n");
221
222 /** @todo check intel docs. */
223 RTPrintf("Features ECX: ");
224 if (uECX & BIT(0)) RTPrintf(" SSE3");
225 for (iBit = 1; iBit < 13; iBit++)
226 if (uECX & BIT(iBit))
227 RTPrintf(" %d", iBit);
228 if (uECX & BIT(13)) RTPrintf(" CX16");
229 for (iBit = 14; iBit < 32; iBit++)
230 if (uECX & BIT(iBit))
231 RTPrintf(" %d", iBit);
232 RTPrintf("\n");
233 }
234
235 /*
236 * Extended.
237 * Implemented after AMD specs.
238 */
239 /** @todo check out the intel specs. */
240 ASMCpuId(0x80000000, &uEAX, &uEBX, &uECX, &uEDX);
241 if (!uEAX && !uEBX && !uECX && !uEDX)
242 {
243 RTPrintf("No extended CPUID info? Check the manual on how to detect this...\n");
244 return;
245 }
246 const uint32_t cExtFunctions = uEAX | 0x80000000;
247
248 /* raw dump */
249 RTPrintf("\n"
250 " RAW Extended CPUIDs\n"
251 "Function eax ebx ecx edx\n");
252 for (unsigned iExt = 0x80000000; iExt <= cExtFunctions + 3; iExt++)
253 {
254 ASMCpuId(iExt, &uEAX, &uEBX, &uECX, &uEDX);
255 RTPrintf("%08x %08x %08x %08x %08x%s\n",
256 iExt, uEAX, uEBX, uECX, uEDX, iExt <= cExtFunctions ? "" : "*");
257 }
258
259 /*
260 * Understandable output
261 */
262 ASMCpuId(0x80000000, &uEAX, &uEBX, &uECX, &uEDX);
263 RTPrintf("Ext Name: %.4s%.4s%.4s\n"
264 "Ext Supports: 0x80000000-%#010x\n",
265 &uEBX, &uEDX, &uECX, uEAX);
266
267 if (cExtFunctions >= 0x80000001)
268 {
269 ASMCpuId(0x80000001, &uEAX, &uEBX, &uECX, &uEDX);
270 RTPrintf("Family: %d \tExtended: %d \tEffectiv: %d\n"
271 "Model: %d \tExtended: %d \tEffectiv: %d\n"
272 "Stepping: %d\n"
273 "Brand ID: %#05x\n",
274 (uEAX >> 8) & 0xf, (uEAX >> 20) & 0x7f, ((uEAX >> 8) & 0xf) + (((uEAX >> 8) & 0xf) == 0xf ? (uEAX >> 20) & 0x7f : 0),
275 (uEAX >> 4) & 0xf, (uEAX >> 16) & 0x0f, ((uEAX >> 4) & 0xf) | (((uEAX >> 4) & 0xf) == 0xf ? (uEAX >> 16) & 0x0f : 0),
276 (uEAX >> 0) & 0xf,
277 uEBX & 0xfff);
278
279 RTPrintf("Features EDX: ");
280 if (uEDX & BIT(0)) RTPrintf(" FPU");
281 if (uEDX & BIT(1)) RTPrintf(" VME");
282 if (uEDX & BIT(2)) RTPrintf(" DE");
283 if (uEDX & BIT(3)) RTPrintf(" PSE");
284 if (uEDX & BIT(4)) RTPrintf(" TSC");
285 if (uEDX & BIT(5)) RTPrintf(" MSR");
286 if (uEDX & BIT(6)) RTPrintf(" PAE");
287 if (uEDX & BIT(7)) RTPrintf(" MCE");
288 if (uEDX & BIT(8)) RTPrintf(" CX8");
289 if (uEDX & BIT(9)) RTPrintf(" APIC");
290 if (uEDX & BIT(10)) RTPrintf(" 10");
291 if (uEDX & BIT(11)) RTPrintf(" SCR");
292 if (uEDX & BIT(12)) RTPrintf(" MTRR");
293 if (uEDX & BIT(13)) RTPrintf(" PGE");
294 if (uEDX & BIT(14)) RTPrintf(" MCA");
295 if (uEDX & BIT(15)) RTPrintf(" CMOV");
296 if (uEDX & BIT(16)) RTPrintf(" PAT");
297 if (uEDX & BIT(17)) RTPrintf(" PSE36");
298 if (uEDX & BIT(18)) RTPrintf(" 18");
299 if (uEDX & BIT(19)) RTPrintf(" 19");
300 if (uEDX & BIT(20)) RTPrintf(" NX");
301 if (uEDX & BIT(21)) RTPrintf(" 21");
302 if (uEDX & BIT(22)) RTPrintf(" ExtMMX");
303 if (uEDX & BIT(23)) RTPrintf(" MMX");
304 if (uEDX & BIT(24)) RTPrintf(" FXSR");
305 if (uEDX & BIT(25)) RTPrintf(" FastFXSR");
306 if (uEDX & BIT(26)) RTPrintf(" 26");
307 if (uEDX & BIT(27)) RTPrintf(" RDTSCP");
308 if (uEDX & BIT(28)) RTPrintf(" 29");
309 if (uEDX & BIT(29)) RTPrintf(" LongMode");
310 if (uEDX & BIT(30)) RTPrintf(" Ext3DNow");
311 if (uEDX & BIT(31)) RTPrintf(" 3DNow");
312 RTPrintf("\n");
313
314 /** @todo Check intel docs. */
315 RTPrintf("Features ECX: ");
316 if (uECX & BIT(0)) RTPrintf(" LAHF/SAHF");
317 if (uECX & BIT(1)) RTPrintf(" CMPL");
318 if (uECX & BIT(2)) RTPrintf(" 2");
319 if (uECX & BIT(3)) RTPrintf(" 3");
320 if (uECX & BIT(4)) RTPrintf(" CR8L");
321 for (iBit = 5; iBit < 32; iBit++)
322 if (uECX & BIT(iBit))
323 RTPrintf(" %d", iBit);
324 RTPrintf("\n");
325 }
326
327 char szString[4*4*3+1] = {0};
328 if (cExtFunctions >= 0x80000002)
329 ASMCpuId(0x80000002, &szString[0 + 0], &szString[0 + 4], &szString[0 + 8], &szString[0 + 12]);
330 if (cExtFunctions >= 0x80000003)
331 ASMCpuId(0x80000003, &szString[16 + 0], &szString[16 + 4], &szString[16 + 8], &szString[16 + 12]);
332 if (cExtFunctions >= 0x80000004)
333 ASMCpuId(0x80000004, &szString[32 + 0], &szString[32 + 4], &szString[32 + 8], &szString[32 + 12]);
334 if (cExtFunctions >= 0x80000002)
335 RTPrintf("Full Name: %s\n", szString);
336
337 if (cExtFunctions >= 0x80000005)
338 {
339 ASMCpuId(0x80000005, &uEAX, &uEBX, &uECX, &uEDX);
340 RTPrintf("TLB 2/4M Instr/Uni: %s %3d entries\n"
341 "TLB 2/4M Data: %s %3d entries\n",
342 getCacheAss((uEAX >> 8) & 0xff), (uEAX >> 0) & 0xff,
343 getCacheAss((uEAX >> 24) & 0xff), (uEAX >> 16) & 0xff);
344 RTPrintf("TLB 4K Instr/Uni: %s %3d entries\n"
345 "TLB 4K Data: %s %3d entries\n",
346 getCacheAss((uEBX >> 8) & 0xff), (uEBX >> 0) & 0xff,
347 getCacheAss((uEBX >> 24) & 0xff), (uEBX >> 16) & 0xff);
348 RTPrintf("L1 Instr Cache Line Size: %d bytes\n"
349 "L1 Instr Cache Lines Per Tag: %d\n"
350 "L1 Instr Cache Associativity: %s\n"
351 "L1 Instr Cache Size: %d KB\n",
352 (uEDX >> 0) & 0xff,
353 (uEDX >> 8) & 0xff,
354 getCacheAss((uEDX >> 16) & 0xff),
355 (uEDX >> 24) & 0xff);
356 RTPrintf("L1 Data Cache Line Size: %d bytes\n"
357 "L1 Data Cache Lines Per Tag: %d\n"
358 "L1 Data Cache Associativity: %s\n"
359 "L1 Data Cache Size: %d KB\n",
360 (uECX >> 0) & 0xff,
361 (uECX >> 8) & 0xff,
362 getCacheAss((uECX >> 16) & 0xff),
363 (uECX >> 24) & 0xff);
364 }
365
366 if (cExtFunctions >= 0x80000006)
367 {
368 ASMCpuId(0x80000006, &uEAX, &uEBX, &uECX, &uEDX);
369 RTPrintf("L2 TLB 2/4M Instr/Uni: %s %4d entries\n"
370 "L2 TLB 2/4M Data: %s %4d entries\n",
371 getL2CacheAss((uEAX >> 12) & 0xf), (uEAX >> 0) & 0xfff,
372 getL2CacheAss((uEAX >> 28) & 0xf), (uEAX >> 16) & 0xfff);
373 RTPrintf("L2 TLB 4K Instr/Uni: %s %4d entries\n"
374 "L2 TLB 4K Data: %s %4d entries\n",
375 getL2CacheAss((uEBX >> 12) & 0xf), (uEBX >> 0) & 0xfff,
376 getL2CacheAss((uEBX >> 28) & 0xf), (uEBX >> 16) & 0xfff);
377 RTPrintf("L2 Cache Line Size: %d bytes\n"
378 "L2 Cache Lines Per Tag: %d\n"
379 "L2 Cache Associativity: %s\n"
380 "L2 Cache Size: %d KB\n",
381 (uEDX >> 0) & 0xff,
382 (uEDX >> 8) & 0xf,
383 getL2CacheAss((uEDX >> 12) & 0xf),
384 (uEDX >> 16) & 0xffff);
385 }
386
387 if (cExtFunctions >= 0x80000007)
388 {
389 ASMCpuId(0x80000007, &uEAX, &uEBX, &uECX, &uEDX);
390 RTPrintf("APM Features: ");
391 if (uEDX & BIT(0)) RTPrintf(" TS");
392 if (uEDX & BIT(1)) RTPrintf(" FID");
393 if (uEDX & BIT(2)) RTPrintf(" VID");
394 if (uEDX & BIT(3)) RTPrintf(" TTP");
395 if (uEDX & BIT(4)) RTPrintf(" TM");
396 if (uEDX & BIT(5)) RTPrintf(" STC");
397 for (iBit = 6; iBit < 32; iBit++)
398 if (uEDX & BIT(iBit))
399 RTPrintf(" %d", iBit);
400 RTPrintf("\n");
401 }
402
403 if (cExtFunctions >= 0x80000008)
404 {
405 ASMCpuId(0x80000008, &uEAX, &uEBX, &uECX, &uEDX);
406 RTPrintf("Physical Address Width: %d bits\n"
407 "Virtual Address Width: %d bits\n",
408 (uEAX >> 0) & 0xff,
409 (uEAX >> 8) & 0xff);
410 RTPrintf("Physical Core Count: %d\n",
411 (uECX >> 0) & 0xff);
412 }
413}
414#endif /* !PIC */
415
416
417static void tstASMAtomicXchgU8(void)
418{
419 struct
420 {
421 uint8_t u8Dummy0;
422 uint8_t u8;
423 uint8_t u8Dummy1;
424 } s;
425
426 s.u8 = 0;
427 s.u8Dummy0 = s.u8Dummy1 = 0x42;
428 CHECKOP(ASMAtomicXchgU8(&s.u8, 1), 0, "%#x", uint8_t);
429 CHECKVAL(s.u8, 1, "%#x");
430
431 CHECKOP(ASMAtomicXchgU8(&s.u8, 0), 1, "%#x", uint8_t);
432 CHECKVAL(s.u8, 0, "%#x");
433
434 CHECKOP(ASMAtomicXchgU8(&s.u8, 0xff), 0, "%#x", uint8_t);
435 CHECKVAL(s.u8, 0xff, "%#x");
436
437 CHECKOP(ASMAtomicXchgU8(&s.u8, 0x87), 0xffff, "%#x", uint8_t);
438 CHECKVAL(s.u8, 0x87, "%#x");
439 CHECKVAL(s.u8Dummy0, 0x42, "%#x");
440 CHECKVAL(s.u8Dummy1, 0x42, "%#x");
441}
442
443
444static void tstASMAtomicXchgU16(void)
445{
446 struct
447 {
448 uint16_t u16Dummy0;
449 uint16_t u16;
450 uint16_t u16Dummy1;
451 } s;
452
453 s.u16 = 0;
454 s.u16Dummy0 = s.u16Dummy1 = 0x1234;
455 CHECKOP(ASMAtomicXchgU16(&s.u16, 1), 0, "%#x", uint16_t);
456 CHECKVAL(s.u16, 1, "%#x");
457
458 CHECKOP(ASMAtomicXchgU16(&s.u16, 0), 1, "%#x", uint16_t);
459 CHECKVAL(s.u16, 0, "%#x");
460
461 CHECKOP(ASMAtomicXchgU16(&s.u16, 0xffff), 0, "%#x", uint16_t);
462 CHECKVAL(s.u16, 0xffff, "%#x");
463
464 CHECKOP(ASMAtomicXchgU16(&s.u16, 0x8765), 0xffff, "%#x", uint16_t);
465 CHECKVAL(s.u16, 0x8765, "%#x");
466 CHECKVAL(s.u16Dummy0, 0x1234, "%#x");
467 CHECKVAL(s.u16Dummy1, 0x1234, "%#x");
468}
469
470
471static void tstASMAtomicXchgU32(void)
472{
473 struct
474 {
475 uint32_t u32Dummy0;
476 uint32_t u32;
477 uint32_t u32Dummy1;
478 } s;
479
480 s.u32 = 0;
481 s.u32Dummy0 = s.u32Dummy1 = 0x11223344;
482
483 CHECKOP(ASMAtomicXchgU32(&s.u32, 1), 0, "%#x", uint32_t);
484 CHECKVAL(s.u32, 1, "%#x");
485
486 CHECKOP(ASMAtomicXchgU32(&s.u32, 0), 1, "%#x", uint32_t);
487 CHECKVAL(s.u32, 0, "%#x");
488
489 CHECKOP(ASMAtomicXchgU32(&s.u32, ~0U), 0, "%#x", uint32_t);
490 CHECKVAL(s.u32, ~0U, "%#x");
491
492 CHECKOP(ASMAtomicXchgU32(&s.u32, 0x87654321), ~0U, "%#x", uint32_t);
493 CHECKVAL(s.u32, 0x87654321, "%#x");
494
495 CHECKVAL(s.u32Dummy0, 0x11223344, "%#x");
496 CHECKVAL(s.u32Dummy1, 0x11223344, "%#x");
497}
498
499
500static void tstASMAtomicXchgU64(void)
501{
502 struct
503 {
504 uint64_t u64Dummy0;
505 uint64_t u64;
506 uint64_t u64Dummy1;
507 } s;
508
509 s.u64 = 0;
510 s.u64Dummy0 = s.u64Dummy1 = 0x1122334455667788ULL;
511
512 CHECKOP(ASMAtomicXchgU64(&s.u64, 1), 0ULL, "%#llx", uint64_t);
513 CHECKVAL(s.u64, 1ULL, "%#llx");
514
515 CHECKOP(ASMAtomicXchgU64(&s.u64, 0), 1ULL, "%#llx", uint64_t);
516 CHECKVAL(s.u64, 0ULL, "%#llx");
517
518 CHECKOP(ASMAtomicXchgU64(&s.u64, ~0ULL), 0ULL, "%#llx", uint64_t);
519 CHECKVAL(s.u64, ~0ULL, "%#llx");
520
521 CHECKOP(ASMAtomicXchgU64(&s.u64, 0xfedcba0987654321ULL), ~0ULL, "%#llx", uint64_t);
522 CHECKVAL(s.u64, 0xfedcba0987654321ULL, "%#llx");
523
524 CHECKVAL(s.u64Dummy0, 0x1122334455667788ULL, "%#x");
525 CHECKVAL(s.u64Dummy1, 0x1122334455667788ULL, "%#x");
526}
527
528
529#ifdef __amd64__
530static void tstASMAtomicXchgU128(void)
531{
532 struct
533 {
534 RTUINT128U u128Dummy0;
535 RTUINT128U u128;
536 RTUINT128U u128Dummy1;
537 } s;
538 RTUINT128U u128Ret;
539 RTUINT128U u128Arg;
540
541
542 s.u128Dummy0.s.Lo = s.u128Dummy0.s.Hi = 0x1122334455667788;
543 s.u128.s.Lo = 0;
544 s.u128.s.Hi = 0;
545 s.u128Dummy1 = s.u128Dummy0;
546
547 u128Arg.s.Lo = 1;
548 u128Arg.s.Hi = 0;
549 u128Ret.u = ASMAtomicXchgU128(&s.u128.u, u128Arg.u);
550 CHECKVAL(u128Ret.s.Lo, 0ULL, "%#llx");
551 CHECKVAL(u128Ret.s.Hi, 0ULL, "%#llx");
552 CHECKVAL(s.u128.s.Lo, 1ULL, "%#llx");
553 CHECKVAL(s.u128.s.Hi, 0ULL, "%#llx");
554
555 u128Arg.s.Lo = 0;
556 u128Arg.s.Hi = 0;
557 u128Ret.u = ASMAtomicXchgU128(&s.u128.u, u128Arg.u);
558 CHECKVAL(u128Ret.s.Lo, 1ULL, "%#llx");
559 CHECKVAL(u128Ret.s.Hi, 0ULL, "%#llx");
560 CHECKVAL(s.u128.s.Lo, 0ULL, "%#llx");
561 CHECKVAL(s.u128.s.Hi, 0ULL, "%#llx");
562
563 u128Arg.s.Lo = ~0ULL;
564 u128Arg.s.Hi = ~0ULL;
565 u128Ret.u = ASMAtomicXchgU128(&s.u128.u, u128Arg.u);
566 CHECKVAL(u128Ret.s.Lo, 0ULL, "%#llx");
567 CHECKVAL(u128Ret.s.Hi, 0ULL, "%#llx");
568 CHECKVAL(s.u128.s.Lo, ~0ULL, "%#llx");
569 CHECKVAL(s.u128.s.Hi, ~0ULL, "%#llx");
570
571
572 u128Arg.s.Lo = 0xfedcba0987654321ULL;
573 u128Arg.s.Hi = 0x8897a6b5c4d3e2f1ULL;
574 u128Ret.u = ASMAtomicXchgU128(&s.u128.u, u128Arg.u);
575 CHECKVAL(u128Ret.s.Lo, ~0ULL, "%#llx");
576 CHECKVAL(u128Ret.s.Hi, ~0ULL, "%#llx");
577 CHECKVAL(s.u128.s.Lo, 0xfedcba0987654321ULL, "%#llx");
578 CHECKVAL(s.u128.s.Hi, 0x8897a6b5c4d3e2f1ULL, "%#llx");
579
580 CHECKVAL(s.u128Dummy0.s.Lo, 0x1122334455667788, "%#llx");
581 CHECKVAL(s.u128Dummy0.s.Hi, 0x1122334455667788, "%#llx");
582 CHECKVAL(s.u128Dummy1.s.Lo, 0x1122334455667788, "%#llx");
583 CHECKVAL(s.u128Dummy1.s.Hi, 0x1122334455667788, "%#llx");
584}
585#endif
586
587
588static void tstASMAtomicXchgPtr(void)
589{
590 void *pv = NULL;
591
592 CHECKOP(ASMAtomicXchgPtr(&pv, (void *)(~(uintptr_t)0)), NULL, "%p", void *);
593 CHECKVAL(pv, (void *)(~(uintptr_t)0), "%p");
594
595 CHECKOP(ASMAtomicXchgPtr(&pv, (void *)0x87654321), (void *)(~(uintptr_t)0), "%p", void *);
596 CHECKVAL(pv, (void *)0x87654321, "%p");
597
598 CHECKOP(ASMAtomicXchgPtr(&pv, NULL), (void *)0x87654321, "%p", void *);
599 CHECKVAL(pv, NULL, "%p");
600}
601
602
603static void tstASMAtomicCmpXchgU32(void)
604{
605 uint32_t u32 = 0xffffffff;
606
607 CHECKOP(ASMAtomicCmpXchgU32(&u32, 0, 0), false, "%d", bool);
608 CHECKVAL(u32, 0xffffffff, "%x");
609
610 CHECKOP(ASMAtomicCmpXchgU32(&u32, 0, 0xffffffff), true, "%d", bool);
611 CHECKVAL(u32, 0, "%x");
612
613 CHECKOP(ASMAtomicCmpXchgU32(&u32, 0x8008efd, 0xffffffff), false, "%d", bool);
614 CHECKVAL(u32, 0, "%x");
615
616 CHECKOP(ASMAtomicCmpXchgU32(&u32, 0x8008efd, 0), true, "%d", bool);
617 CHECKVAL(u32, 0x8008efd, "%x");
618}
619
620
621static void tstASMAtomicCmpXchgU64(void)
622{
623 uint64_t u64 = 0xffffffffffffffULL;
624
625 CHECKOP(ASMAtomicCmpXchgU64(&u64, 0, 0), false, "%d", bool);
626 CHECKVAL(u64, 0xffffffffffffffULL, "%x");
627
628 CHECKOP(ASMAtomicCmpXchgU64(&u64, 0, 0xffffffffffffffULL), true, "%d", bool);
629 CHECKVAL(u64, 0, "%x");
630
631 CHECKOP(ASMAtomicCmpXchgU64(&u64, 0x80040008008efdULL, 0xffffffff), false, "%d", bool);
632 CHECKVAL(u64, 0, "%x");
633
634 CHECKOP(ASMAtomicCmpXchgU64(&u64, 0x80040008008efdULL, 0xffffffff00000000ULL), false, "%d", bool);
635 CHECKVAL(u64, 0, "%x");
636
637 CHECKOP(ASMAtomicCmpXchgU64(&u64, 0x80040008008efdULL, 0), true, "%d", bool);
638 CHECKVAL(u64, 0x80040008008efdULL, "%x");
639}
640
641
642static void tstASMAtomicReadU64(void)
643{
644 uint64_t u64 = 0;
645
646 CHECKOP(ASMAtomicReadU64(&u64), 0ULL, "%#llx", uint64_t);
647 CHECKVAL(u64, 0ULL, "%#llx");
648
649 u64 = ~0ULL;
650 CHECKOP(ASMAtomicReadU64(&u64), ~0ULL, "%#llx", uint64_t);
651 CHECKVAL(u64, ~0ULL, "%#llx");
652
653 u64 = 0xfedcba0987654321ULL;
654 CHECKOP(ASMAtomicReadU64(&u64), 0xfedcba0987654321ULL, "%#llx", uint64_t);
655 CHECKVAL(u64, 0xfedcba0987654321ULL, "%#llx");
656}
657
658
659static void tstASMAtomicDecIncS32(void)
660{
661 int32_t i32Rc;
662 int32_t i32 = 10;
663#define MYCHECK(op, rc) \
664 do { \
665 i32Rc = op; \
666 if (i32Rc != (rc)) \
667 { \
668 RTPrintf("%s, %d: FAILURE: %s -> %d expected %d\n", __FUNCTION__, __LINE__, #op, i32Rc, rc); \
669 g_cErrors++; \
670 } \
671 if (i32 != (rc)) \
672 { \
673 RTPrintf("%s, %d: FAILURE: %s => i32=%d expected %d\n", __FUNCTION__, __LINE__, #op, i32, rc); \
674 g_cErrors++; \
675 } \
676 } while (0)
677 MYCHECK(ASMAtomicDecS32(&i32), 9);
678 MYCHECK(ASMAtomicDecS32(&i32), 8);
679 MYCHECK(ASMAtomicDecS32(&i32), 7);
680 MYCHECK(ASMAtomicDecS32(&i32), 6);
681 MYCHECK(ASMAtomicDecS32(&i32), 5);
682 MYCHECK(ASMAtomicDecS32(&i32), 4);
683 MYCHECK(ASMAtomicDecS32(&i32), 3);
684 MYCHECK(ASMAtomicDecS32(&i32), 2);
685 MYCHECK(ASMAtomicDecS32(&i32), 1);
686 MYCHECK(ASMAtomicDecS32(&i32), 0);
687 MYCHECK(ASMAtomicDecS32(&i32), -1);
688 MYCHECK(ASMAtomicDecS32(&i32), -2);
689 MYCHECK(ASMAtomicIncS32(&i32), -1);
690 MYCHECK(ASMAtomicIncS32(&i32), 0);
691 MYCHECK(ASMAtomicIncS32(&i32), 1);
692 MYCHECK(ASMAtomicIncS32(&i32), 2);
693 MYCHECK(ASMAtomicIncS32(&i32), 3);
694 MYCHECK(ASMAtomicDecS32(&i32), 2);
695 MYCHECK(ASMAtomicIncS32(&i32), 3);
696 MYCHECK(ASMAtomicDecS32(&i32), 2);
697 MYCHECK(ASMAtomicIncS32(&i32), 3);
698#undef MYCHECK
699
700}
701
702
703static void tstASMAtomicAndOrU32(void)
704{
705 uint32_t u32 = 0xffffffff;
706
707 ASMAtomicOrU32(&u32, 0xffffffff);
708 CHECKVAL(u32, 0xffffffff, "%x");
709
710 ASMAtomicAndU32(&u32, 0xffffffff);
711 CHECKVAL(u32, 0xffffffff, "%x");
712
713 ASMAtomicAndU32(&u32, 0x8f8f8f8f);
714 CHECKVAL(u32, 0x8f8f8f8f, "%x");
715
716 ASMAtomicOrU32(&u32, 0x70707070);
717 CHECKVAL(u32, 0xffffffff, "%x");
718
719 ASMAtomicAndU32(&u32, 1);
720 CHECKVAL(u32, 1, "%x");
721
722 ASMAtomicOrU32(&u32, 0x80000000);
723 CHECKVAL(u32, 0x80000001, "%x");
724
725 ASMAtomicAndU32(&u32, 0x80000000);
726 CHECKVAL(u32, 0x80000000, "%x");
727
728 ASMAtomicAndU32(&u32, 0);
729 CHECKVAL(u32, 0, "%x");
730
731 ASMAtomicOrU32(&u32, 0x42424242);
732 CHECKVAL(u32, 0x42424242, "%x");
733}
734
735
736void tstASMMemZeroPage(void)
737{
738 struct
739 {
740 uint64_t u64Magic1;
741 uint8_t abPage[PAGE_SIZE];
742 uint64_t u64Magic2;
743 } Buf1, Buf2, Buf3;
744
745 Buf1.u64Magic1 = UINT64_C(0xffffffffffffffff);
746 memset(Buf1.abPage, 0x55, sizeof(Buf1.abPage));
747 Buf1.u64Magic2 = UINT64_C(0xffffffffffffffff);
748 Buf2.u64Magic1 = UINT64_C(0xffffffffffffffff);
749 memset(Buf2.abPage, 0x77, sizeof(Buf2.abPage));
750 Buf2.u64Magic2 = UINT64_C(0xffffffffffffffff);
751 Buf3.u64Magic1 = UINT64_C(0xffffffffffffffff);
752 memset(Buf3.abPage, 0x99, sizeof(Buf3.abPage));
753 Buf3.u64Magic2 = UINT64_C(0xffffffffffffffff);
754 ASMMemZeroPage(Buf1.abPage);
755 ASMMemZeroPage(Buf2.abPage);
756 ASMMemZeroPage(Buf3.abPage);
757 if ( Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
758 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
759 || Buf1.u64Magic1 != UINT64_C(0xffffffffffffffff)
760 || Buf1.u64Magic2 != UINT64_C(0xffffffffffffffff)
761 || Buf2.u64Magic1 != UINT64_C(0xffffffffffffffff)
762 || Buf2.u64Magic2 != UINT64_C(0xffffffffffffffff))
763 {
764 RTPrintf("tstInlineAsm: ASMMemZeroPage violated one/both magic(s)!\n");
765 g_cErrors++;
766 }
767 for (unsigned i = 0; i < sizeof(Buf1.abPage); i++)
768 if (Buf1.abPage[i])
769 {
770 RTPrintf("tstInlineAsm: ASMMemZeroPage didn't clear byte at offset %#x!\n", i);
771 g_cErrors++;
772 }
773 for (unsigned i = 0; i < sizeof(Buf1.abPage); i++)
774 if (Buf1.abPage[i])
775 {
776 RTPrintf("tstInlineAsm: ASMMemZeroPage didn't clear byte at offset %#x!\n", i);
777 g_cErrors++;
778 }
779 for (unsigned i = 0; i < sizeof(Buf2.abPage); i++)
780 if (Buf2.abPage[i])
781 {
782 RTPrintf("tstInlineAsm: ASMMemZeroPage didn't clear byte at offset %#x!\n", i);
783 g_cErrors++;
784 }
785}
786
787
788void tstASMMath(void)
789{
790 uint64_t u64 = ASMMult2xU32RetU64(UINT32_C(0x80000000), UINT32_C(0x10000000));
791 CHECKVAL(u64, UINT64_C(0x0800000000000000), "%#018RX64");
792
793 uint32_t u32 = ASMDivU64ByU32RetU32(UINT64_C(0x0800000000000000), UINT32_C(0x10000000));
794 CHECKVAL(u32, UINT32_C(0x80000000), "%#010RX32");
795}
796
797
798int main(int argc, char *argv[])
799{
800 RTR3Init();
801 RTPrintf("tstInlineAsm: TESTING\n");
802
803 /*
804 * Execute the tests.
805 */
806#ifndef PIC
807 tstASMCpuId();
808#endif
809 tstASMAtomicXchgU8();
810 tstASMAtomicXchgU16();
811 tstASMAtomicXchgU32();
812 tstASMAtomicXchgU64();
813#ifdef __amd64__
814 tstASMAtomicXchgU128();
815#endif
816 tstASMAtomicXchgPtr();
817 tstASMAtomicCmpXchgU32();
818 tstASMAtomicCmpXchgU64();
819 tstASMAtomicReadU64();
820 tstASMAtomicDecIncS32();
821 tstASMAtomicAndOrU32();
822 tstASMMemZeroPage();
823 tstASMMath();
824
825 /*
826 * Show the result.
827 */
828 if (!g_cErrors)
829 RTPrintf("tstInlineAsm: SUCCESS\n", g_cErrors);
830 else
831 RTPrintf("tstInlineAsm: FAILURE - %d errors\n", g_cErrors);
832 return !!g_cErrors;
833}
834
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