VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTInlineAsm.cpp@ 33136

Last change on this file since 33136 was 33136, checked in by vboxsync, 14 years ago

iprt/asm.h,tstRTInlineAsm: Added 64-bit atomic OR, AND, INC, DEC, ADD and SUB methods.

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