1 | /* $Id: tstIEMAImpl.cpp 93893 2022-02-22 21:27:58Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * IEM Assembly Instruction Helper Testcase.
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2022 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 |
|
---|
18 |
|
---|
19 | /*********************************************************************************************************************************
|
---|
20 | * Header Files *
|
---|
21 | *********************************************************************************************************************************/
|
---|
22 | #include "../include/IEMInternal.h"
|
---|
23 |
|
---|
24 | #include <iprt/errcore.h>
|
---|
25 | #include <VBox/log.h>
|
---|
26 | #include <iprt/assert.h>
|
---|
27 | #include <iprt/initterm.h>
|
---|
28 | #include <iprt/message.h>
|
---|
29 | #include <iprt/mp.h>
|
---|
30 | #include <iprt/rand.h>
|
---|
31 | #include <iprt/stream.h>
|
---|
32 | #include <iprt/string.h>
|
---|
33 | #include <iprt/test.h>
|
---|
34 |
|
---|
35 |
|
---|
36 | /*********************************************************************************************************************************
|
---|
37 | * Structures and Typedefs *
|
---|
38 | *********************************************************************************************************************************/
|
---|
39 | /** @name 8-bit binary (PFNIEMAIMPLBINU8)
|
---|
40 | * @{ */
|
---|
41 | typedef struct BINU8_TEST_T
|
---|
42 | {
|
---|
43 | uint32_t fEflIn;
|
---|
44 | uint32_t fEflOut;
|
---|
45 | uint8_t uDstIn;
|
---|
46 | uint8_t uDstOut;
|
---|
47 | uint8_t uSrcIn;
|
---|
48 | uint8_t uMisc;
|
---|
49 | } BINU8_TEST_T;
|
---|
50 |
|
---|
51 | typedef struct BINU8_T
|
---|
52 | {
|
---|
53 | const char *pszName;
|
---|
54 | PFNIEMAIMPLBINU8 pfn;
|
---|
55 | BINU8_TEST_T const *paTests;
|
---|
56 | uint32_t cTests;
|
---|
57 | uint32_t uExtra;
|
---|
58 | } BINU8_T;
|
---|
59 | /** @} */
|
---|
60 |
|
---|
61 |
|
---|
62 | /** @name 16-bit binary (PFNIEMAIMPLBINU16)
|
---|
63 | * @{ */
|
---|
64 | typedef struct BINU16_TEST_T
|
---|
65 | {
|
---|
66 | uint32_t fEflIn;
|
---|
67 | uint32_t fEflOut;
|
---|
68 | uint16_t uDstIn;
|
---|
69 | uint16_t uDstOut;
|
---|
70 | uint16_t uSrcIn;
|
---|
71 | uint16_t uMisc;
|
---|
72 | } BINU16_TEST_T;
|
---|
73 |
|
---|
74 | typedef struct BINU16_T
|
---|
75 | {
|
---|
76 | const char *pszName;
|
---|
77 | PFNIEMAIMPLBINU16 pfn;
|
---|
78 | BINU16_TEST_T const *paTests;
|
---|
79 | uint32_t cTests;
|
---|
80 | uint32_t uExtra;
|
---|
81 | } BINU16_T;
|
---|
82 | /** @} */
|
---|
83 |
|
---|
84 |
|
---|
85 | /** @name 32-bit binary (PFNIEMAIMPLBINU32)
|
---|
86 | * @{ */
|
---|
87 | typedef struct BINU32_TEST_T
|
---|
88 | {
|
---|
89 | uint32_t fEflIn;
|
---|
90 | uint32_t fEflOut;
|
---|
91 | uint32_t uDstIn;
|
---|
92 | uint32_t uDstOut;
|
---|
93 | uint32_t uSrcIn;
|
---|
94 | uint32_t uMisc;
|
---|
95 | } BINU32_TEST_T;
|
---|
96 |
|
---|
97 | typedef struct BINU32_T
|
---|
98 | {
|
---|
99 | const char *pszName;
|
---|
100 | PFNIEMAIMPLBINU32 pfn;
|
---|
101 | BINU32_TEST_T const *paTests;
|
---|
102 | uint32_t cTests;
|
---|
103 | uint32_t uExtra;
|
---|
104 | } BINU32_T;
|
---|
105 | /** @} */
|
---|
106 |
|
---|
107 |
|
---|
108 | /** @name 64-bit binary (PFNIEMAIMPLBINU64)
|
---|
109 | * @{ */
|
---|
110 | typedef struct BINU64_TEST_T
|
---|
111 | {
|
---|
112 | uint32_t fEflIn;
|
---|
113 | uint32_t fEflOut;
|
---|
114 | uint64_t uDstIn;
|
---|
115 | uint64_t uDstOut;
|
---|
116 | uint64_t uSrcIn;
|
---|
117 | uint64_t uMisc;
|
---|
118 | } BINU64_TEST_T;
|
---|
119 |
|
---|
120 | typedef struct BINU64_T
|
---|
121 | {
|
---|
122 | const char *pszName;
|
---|
123 | PFNIEMAIMPLBINU64 pfn;
|
---|
124 | BINU64_TEST_T const *paTests;
|
---|
125 | uint32_t cTests;
|
---|
126 | uint32_t uExtra;
|
---|
127 | } BINU64_T;
|
---|
128 | /** @} */
|
---|
129 |
|
---|
130 |
|
---|
131 | /** @name mult/div (PFNIEMAIMPLBINU8, PFNIEMAIMPLBINU16, PFNIEMAIMPLBINU32, PFNIEMAIMPLBINU64)
|
---|
132 | * @{ */
|
---|
133 | typedef struct MULDIVU8_TEST_T
|
---|
134 | {
|
---|
135 | uint32_t fEflIn;
|
---|
136 | uint32_t fEflOut;
|
---|
137 | uint16_t uDstIn;
|
---|
138 | uint16_t uDstOut;
|
---|
139 | uint8_t uSrcIn;
|
---|
140 | int32_t rc;
|
---|
141 | } MULDIVU8_TEST_T;
|
---|
142 |
|
---|
143 | typedef struct MULDIVU16_TEST_T
|
---|
144 | {
|
---|
145 | uint32_t fEflIn;
|
---|
146 | uint32_t fEflOut;
|
---|
147 | uint16_t uDst1In;
|
---|
148 | uint16_t uDst1Out;
|
---|
149 | uint16_t uDst2In;
|
---|
150 | uint16_t uDst2Out;
|
---|
151 | uint16_t uSrcIn;
|
---|
152 | int32_t rc;
|
---|
153 | } MULDIVU16_TEST_T;
|
---|
154 |
|
---|
155 | typedef struct MULDIVU32_TEST_T
|
---|
156 | {
|
---|
157 | uint32_t fEflIn;
|
---|
158 | uint32_t fEflOut;
|
---|
159 | uint32_t uDst1In;
|
---|
160 | uint32_t uDst1Out;
|
---|
161 | uint32_t uDst2In;
|
---|
162 | uint32_t uDst2Out;
|
---|
163 | uint32_t uSrcIn;
|
---|
164 | int32_t rc;
|
---|
165 | } MULDIVU32_TEST_T;
|
---|
166 |
|
---|
167 | typedef struct MULDIVU64_TEST_T
|
---|
168 | {
|
---|
169 | uint32_t fEflIn;
|
---|
170 | uint32_t fEflOut;
|
---|
171 | uint64_t uDst1In;
|
---|
172 | uint64_t uDst1Out;
|
---|
173 | uint64_t uDst2In;
|
---|
174 | uint64_t uDst2Out;
|
---|
175 | uint64_t uSrcIn;
|
---|
176 | int32_t rc;
|
---|
177 | } MULDIVU64_TEST_T;
|
---|
178 | /** @} */
|
---|
179 |
|
---|
180 |
|
---|
181 | /*********************************************************************************************************************************
|
---|
182 | * Defined Constants And Macros *
|
---|
183 | *********************************************************************************************************************************/
|
---|
184 | #define ENTRY(a_Name) ENTRY_EX(a_Name, 0)
|
---|
185 | #define ENTRY_EX(a_Name, a_uExtra) \
|
---|
186 | { #a_Name, iemAImpl_ ## a_Name, g_aTests_ ## a_Name, RT_ELEMENTS(g_aTests_ ## a_Name), a_uExtra }
|
---|
187 |
|
---|
188 |
|
---|
189 | /*********************************************************************************************************************************
|
---|
190 | * Internal Functions *
|
---|
191 | *********************************************************************************************************************************/
|
---|
192 | static uint32_t RandEFlags(void);
|
---|
193 | static uint8_t RandU8(void);
|
---|
194 | static uint16_t RandU16(void);
|
---|
195 | static uint32_t RandU32(void);
|
---|
196 | static uint64_t RandU64(void);
|
---|
197 | static RTUINT128U RandU128(void);
|
---|
198 |
|
---|
199 |
|
---|
200 | /*********************************************************************************************************************************
|
---|
201 | * Global Variables *
|
---|
202 | *********************************************************************************************************************************/
|
---|
203 | static RTTEST g_hTest;
|
---|
204 | static uint8_t *g_pu8, *g_pu8Two;
|
---|
205 | static uint16_t *g_pu16, *g_pu16Two;
|
---|
206 | static uint32_t *g_pu32, *g_pu32Two, *g_pfEfl;
|
---|
207 | static uint64_t *g_pu64, *g_pu64Two;
|
---|
208 | static RTUINT128U *g_pu128, *g_pu128Two;
|
---|
209 |
|
---|
210 |
|
---|
211 | #include "tstIEMAImplData.h"
|
---|
212 |
|
---|
213 | /*
|
---|
214 | * Test helpers.
|
---|
215 | */
|
---|
216 | static const char *EFlagsDiff(uint32_t fActual, uint32_t fExpected)
|
---|
217 | {
|
---|
218 | if (fActual == fExpected)
|
---|
219 | return "";
|
---|
220 |
|
---|
221 | uint32_t const fXor = fActual ^ fExpected;
|
---|
222 | static char s_szBuf[256];
|
---|
223 | size_t cch = RTStrPrintf(s_szBuf, sizeof(s_szBuf), " - %#x", fXor);
|
---|
224 |
|
---|
225 | static struct
|
---|
226 | {
|
---|
227 | const char *pszName;
|
---|
228 | uint32_t fFlag;
|
---|
229 | } const s_aFlags[] =
|
---|
230 | {
|
---|
231 | #define EFL_ENTRY(a_Flags) { #a_Flags, X86_EFL_ ## a_Flags }
|
---|
232 | EFL_ENTRY(CF),
|
---|
233 | EFL_ENTRY(PF),
|
---|
234 | EFL_ENTRY(AF),
|
---|
235 | EFL_ENTRY(ZF),
|
---|
236 | EFL_ENTRY(SF),
|
---|
237 | EFL_ENTRY(TF),
|
---|
238 | EFL_ENTRY(IF),
|
---|
239 | EFL_ENTRY(DF),
|
---|
240 | EFL_ENTRY(OF),
|
---|
241 | EFL_ENTRY(IOPL),
|
---|
242 | EFL_ENTRY(NT),
|
---|
243 | EFL_ENTRY(RF),
|
---|
244 | EFL_ENTRY(VM),
|
---|
245 | EFL_ENTRY(AC),
|
---|
246 | EFL_ENTRY(VIF),
|
---|
247 | EFL_ENTRY(VIP),
|
---|
248 | EFL_ENTRY(ID),
|
---|
249 | };
|
---|
250 | for (size_t i = 0; i < RT_ELEMENTS(s_aFlags); i++)
|
---|
251 | if (s_aFlags[i].fFlag & fXor)
|
---|
252 | cch += RTStrPrintf(&s_szBuf[cch], sizeof(s_szBuf) - cch,
|
---|
253 | s_aFlags[i].fFlag & fActual ? "/%s" : "/!%s", s_aFlags[i].pszName);
|
---|
254 | RTStrPrintf(&s_szBuf[cch], sizeof(s_szBuf) - cch, "");
|
---|
255 | return s_szBuf;
|
---|
256 | }
|
---|
257 |
|
---|
258 |
|
---|
259 | /*
|
---|
260 | * 8-bit binary operations.
|
---|
261 | */
|
---|
262 |
|
---|
263 | #ifndef HAVE_BINU8_TESTS
|
---|
264 | static const BINU8_TEST_T g_aTests_add_u8[] = { {0} };
|
---|
265 | static const BINU8_TEST_T g_aTests_add_u8_locked[] = { {0} };
|
---|
266 | static const BINU8_TEST_T g_aTests_adc_u8[] = { {0} };
|
---|
267 | static const BINU8_TEST_T g_aTests_adc_u8_locked[] = { {0} };
|
---|
268 | static const BINU8_TEST_T g_aTests_sub_u8[] = { {0} };
|
---|
269 | static const BINU8_TEST_T g_aTests_sub_u8_locked[] = { {0} };
|
---|
270 | static const BINU8_TEST_T g_aTests_sbb_u8[] = { {0} };
|
---|
271 | static const BINU8_TEST_T g_aTests_sbb_u8_locked[] = { {0} };
|
---|
272 | static const BINU8_TEST_T g_aTests_or_u8[] = { {0} };
|
---|
273 | static const BINU8_TEST_T g_aTests_or_u8_locked[] = { {0} };
|
---|
274 | static const BINU8_TEST_T g_aTests_xor_u8[] = { {0} };
|
---|
275 | static const BINU8_TEST_T g_aTests_xor_u8_locked[] = { {0} };
|
---|
276 | static const BINU8_TEST_T g_aTests_and_u8[] = { {0} };
|
---|
277 | static const BINU8_TEST_T g_aTests_and_u8_locked[] = { {0} };
|
---|
278 | static const BINU8_TEST_T g_aTests_cmp_u8[] = { {0} };
|
---|
279 | static const BINU8_TEST_T g_aTests_test_u8[] = { {0} };
|
---|
280 | #endif
|
---|
281 |
|
---|
282 | static const BINU8_T g_aBinU8[] =
|
---|
283 | {
|
---|
284 | ENTRY(add_u8),
|
---|
285 | ENTRY(add_u8_locked),
|
---|
286 | ENTRY(adc_u8),
|
---|
287 | ENTRY(adc_u8_locked),
|
---|
288 | ENTRY(sub_u8),
|
---|
289 | ENTRY(sub_u8_locked),
|
---|
290 | ENTRY(sbb_u8),
|
---|
291 | ENTRY(sbb_u8_locked),
|
---|
292 | ENTRY(or_u8),
|
---|
293 | ENTRY(or_u8_locked),
|
---|
294 | ENTRY(xor_u8),
|
---|
295 | ENTRY(xor_u8_locked),
|
---|
296 | ENTRY(and_u8),
|
---|
297 | ENTRY(and_u8_locked),
|
---|
298 | ENTRY(cmp_u8),
|
---|
299 | ENTRY(test_u8),
|
---|
300 | };
|
---|
301 |
|
---|
302 |
|
---|
303 | static void BinU8Generate(uint32_t cTests)
|
---|
304 | {
|
---|
305 | RTPrintf("\n\n#define HAVE_BINU8_TESTS\n");
|
---|
306 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aBinU8); iFn++)
|
---|
307 | {
|
---|
308 | RTPrintf("static const BINU8_TEST_T g_aTests_%s[] =\n{\n", g_aBinU8[iFn].pszName);
|
---|
309 | for (uint32_t iTest = 0; iTest < cTests; iTest++ )
|
---|
310 | {
|
---|
311 | BINU8_TEST_T Test;
|
---|
312 | Test.fEflIn = RandEFlags();
|
---|
313 | Test.fEflOut = Test.fEflIn;
|
---|
314 | Test.uDstIn = RandU8();
|
---|
315 | Test.uDstOut = Test.uDstIn;
|
---|
316 | Test.uSrcIn = RandU8();
|
---|
317 | Test.uMisc = 0;
|
---|
318 | g_aBinU8[iFn].pfn(&Test.uDstOut, Test.uSrcIn, &Test.fEflOut);
|
---|
319 | RTPrintf(" { %#08x, %#08x, %#04x, %#04x, %#04x, %#x }, /* #%u */\n",
|
---|
320 | Test.fEflIn, Test.fEflOut, Test.uDstIn, Test.uDstOut, Test.uSrcIn, Test.uMisc, iTest);
|
---|
321 | }
|
---|
322 | RTPrintf("};\n");
|
---|
323 | }
|
---|
324 | }
|
---|
325 |
|
---|
326 | static void BinU8Test(void)
|
---|
327 | {
|
---|
328 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aBinU8); iFn++)
|
---|
329 | {
|
---|
330 | RTTestSub(g_hTest, g_aBinU8[iFn].pszName);
|
---|
331 |
|
---|
332 | BINU8_TEST_T const * const paTests = g_aBinU8[iFn].paTests;
|
---|
333 | uint32_t const cTests = g_aBinU8[iFn].cTests;
|
---|
334 | for (uint32_t iTest = 0; iTest < cTests; iTest++ )
|
---|
335 | {
|
---|
336 | uint32_t fEfl = paTests[iTest].fEflIn;
|
---|
337 | uint8_t uDst = paTests[iTest].uDstIn;
|
---|
338 | g_aBinU8[iFn].pfn(&uDst, paTests[iTest].uSrcIn, &fEfl);
|
---|
339 | if ( uDst != paTests[iTest].uDstOut
|
---|
340 | || fEfl != paTests[iTest].fEflOut)
|
---|
341 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#04x src=%#04x -> efl=%#08x dst=%#04x, expected %#08x & %#04x%s - %s\n",
|
---|
342 | iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uSrcIn,
|
---|
343 | fEfl, uDst, paTests[iTest].fEflOut, paTests[iTest].uDstOut,
|
---|
344 | EFlagsDiff(fEfl, paTests[iTest].fEflOut),
|
---|
345 | uDst == paTests[iTest].uDstOut ? "eflags" : fEfl == paTests[iTest].fEflOut ? "dst" : "both");
|
---|
346 | else
|
---|
347 | {
|
---|
348 | *g_pu8 = paTests[iTest].uDstIn;
|
---|
349 | *g_pfEfl = paTests[iTest].fEflIn;
|
---|
350 | g_aBinU8[iFn].pfn(g_pu8, paTests[iTest].uSrcIn, g_pfEfl);
|
---|
351 | RTTEST_CHECK(g_hTest, *g_pu8 == paTests[iTest].uDstOut);
|
---|
352 | RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut);
|
---|
353 | }
|
---|
354 | }
|
---|
355 | }
|
---|
356 | }
|
---|
357 |
|
---|
358 |
|
---|
359 | /*
|
---|
360 | * 16-bit binary operations.
|
---|
361 | */
|
---|
362 |
|
---|
363 | #ifndef HAVE_BINU16_TESTS
|
---|
364 | static const BINU16_TEST_T g_aTests_add_u16[] = { {0} };
|
---|
365 | static const BINU16_TEST_T g_aTests_add_u16_locked[] = { {0} };
|
---|
366 | static const BINU16_TEST_T g_aTests_adc_u16[] = { {0} };
|
---|
367 | static const BINU16_TEST_T g_aTests_adc_u16_locked[] = { {0} };
|
---|
368 | static const BINU16_TEST_T g_aTests_sub_u16[] = { {0} };
|
---|
369 | static const BINU16_TEST_T g_aTests_sub_u16_locked[] = { {0} };
|
---|
370 | static const BINU16_TEST_T g_aTests_sbb_u16[] = { {0} };
|
---|
371 | static const BINU16_TEST_T g_aTests_sbb_u16_locked[] = { {0} };
|
---|
372 | static const BINU16_TEST_T g_aTests_or_u16[] = { {0} };
|
---|
373 | static const BINU16_TEST_T g_aTests_or_u16_locked[] = { {0} };
|
---|
374 | static const BINU16_TEST_T g_aTests_xor_u16[] = { {0} };
|
---|
375 | static const BINU16_TEST_T g_aTests_xor_u16_locked[] = { {0} };
|
---|
376 | static const BINU16_TEST_T g_aTests_and_u16[] = { {0} };
|
---|
377 | static const BINU16_TEST_T g_aTests_and_u16_locked[] = { {0} };
|
---|
378 | static const BINU16_TEST_T g_aTests_cmp_u16[] = { {0} };
|
---|
379 | static const BINU16_TEST_T g_aTests_test_u16[] = { {0} };
|
---|
380 | static const BINU16_TEST_T g_aTests_bt_u16[] = { {0} };
|
---|
381 | static const BINU16_TEST_T g_aTests_btc_u16[] = { {0} };
|
---|
382 | static const BINU16_TEST_T g_aTests_btc_u16_locked[] = { {0} };
|
---|
383 | static const BINU16_TEST_T g_aTests_btr_u16[] = { {0} };
|
---|
384 | static const BINU16_TEST_T g_aTests_btr_u16_locked[] = { {0} };
|
---|
385 | static const BINU16_TEST_T g_aTests_bts_u16[] = { {0} };
|
---|
386 | static const BINU16_TEST_T g_aTests_bts_u16_locked[] = { {0} };
|
---|
387 | static const BINU16_TEST_T g_aTests_bsf_u16[] = { {0} };
|
---|
388 | static const BINU16_TEST_T g_aTests_bsr_u16[] = { {0} };
|
---|
389 | static const BINU16_TEST_T g_aTests_imul_two_u16[] = { {0} };
|
---|
390 | static const BINU16_TEST_T g_aTests_arpl[] = { {0} };
|
---|
391 | #endif
|
---|
392 |
|
---|
393 | static const BINU16_T g_aBinU16[] =
|
---|
394 | {
|
---|
395 | ENTRY(add_u16),
|
---|
396 | ENTRY(add_u16_locked),
|
---|
397 | ENTRY(adc_u16),
|
---|
398 | ENTRY(adc_u16_locked),
|
---|
399 | ENTRY(sub_u16),
|
---|
400 | ENTRY(sub_u16_locked),
|
---|
401 | ENTRY(sbb_u16),
|
---|
402 | ENTRY(sbb_u16_locked),
|
---|
403 | ENTRY(or_u16),
|
---|
404 | ENTRY(or_u16_locked),
|
---|
405 | ENTRY(xor_u16),
|
---|
406 | ENTRY(xor_u16_locked),
|
---|
407 | ENTRY(and_u16),
|
---|
408 | ENTRY(and_u16_locked),
|
---|
409 | ENTRY(cmp_u16),
|
---|
410 | ENTRY(test_u16),
|
---|
411 | ENTRY_EX(bt_u16, 1),
|
---|
412 | ENTRY_EX(btc_u16, 1),
|
---|
413 | ENTRY_EX(btc_u16_locked, 1),
|
---|
414 | ENTRY_EX(btr_u16, 1),
|
---|
415 | ENTRY_EX(btr_u16_locked, 1),
|
---|
416 | ENTRY_EX(bts_u16, 1),
|
---|
417 | ENTRY_EX(bts_u16_locked, 1),
|
---|
418 | ENTRY(bsf_u16),
|
---|
419 | ENTRY(bsr_u16),
|
---|
420 | ENTRY(imul_two_u16),
|
---|
421 | ENTRY(arpl),
|
---|
422 | };
|
---|
423 |
|
---|
424 | static void BinU16Generate(uint32_t cTests)
|
---|
425 | {
|
---|
426 | RTPrintf("\n\n#define HAVE_BINU16_TESTS\n");
|
---|
427 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aBinU16); iFn++)
|
---|
428 | {
|
---|
429 | RTPrintf("static const BINU16_TEST_T g_aTests_%s[] =\n{\n", g_aBinU16[iFn].pszName);
|
---|
430 | for (uint32_t iTest = 0; iTest < cTests; iTest++ )
|
---|
431 | {
|
---|
432 | BINU16_TEST_T Test;
|
---|
433 | Test.fEflIn = RandEFlags();
|
---|
434 | Test.fEflOut = Test.fEflIn;
|
---|
435 | Test.uDstIn = RandU16();
|
---|
436 | Test.uDstOut = Test.uDstIn;
|
---|
437 | Test.uSrcIn = RandU16();
|
---|
438 | if (g_aBinU16[iFn].uExtra)
|
---|
439 | Test.uSrcIn &= 0xf; /* Restrict bit index to a word */
|
---|
440 | Test.uMisc = 0;
|
---|
441 | g_aBinU16[iFn].pfn(&Test.uDstOut, Test.uSrcIn, &Test.fEflOut);
|
---|
442 | RTPrintf(" { %#08x, %#08x, %#06x, %#06x, %#06x, %#x }, /* #%u */\n",
|
---|
443 | Test.fEflIn, Test.fEflOut, Test.uDstIn, Test.uDstOut, Test.uSrcIn, Test.uMisc, iTest);
|
---|
444 | }
|
---|
445 | RTPrintf("};\n");
|
---|
446 | }
|
---|
447 | }
|
---|
448 |
|
---|
449 | static void BinU16Test(void)
|
---|
450 | {
|
---|
451 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aBinU16); iFn++)
|
---|
452 | {
|
---|
453 | RTTestSub(g_hTest, g_aBinU16[iFn].pszName);
|
---|
454 |
|
---|
455 | BINU16_TEST_T const * const paTests = g_aBinU16[iFn].paTests;
|
---|
456 | uint32_t const cTests = g_aBinU16[iFn].cTests;
|
---|
457 | for (uint32_t iTest = 0; iTest < cTests; iTest++ )
|
---|
458 | {
|
---|
459 | uint32_t fEfl = paTests[iTest].fEflIn;
|
---|
460 | uint16_t uDst = paTests[iTest].uDstIn;
|
---|
461 | g_aBinU16[iFn].pfn(&uDst, paTests[iTest].uSrcIn, &fEfl);
|
---|
462 | if ( uDst != paTests[iTest].uDstOut
|
---|
463 | || fEfl != paTests[iTest].fEflOut)
|
---|
464 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#06x src=%#06x -> efl=%#08x dst=%#06x, expected %#08x & %#06x%s - %s\n",
|
---|
465 | iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uSrcIn,
|
---|
466 | fEfl, uDst, paTests[iTest].fEflOut, paTests[iTest].uDstOut,
|
---|
467 | EFlagsDiff(fEfl, paTests[iTest].fEflOut),
|
---|
468 | uDst == paTests[iTest].uDstOut ? "eflags" : fEfl == paTests[iTest].fEflOut ? "dst" : "both");
|
---|
469 | else
|
---|
470 | {
|
---|
471 | *g_pu16 = paTests[iTest].uDstIn;
|
---|
472 | *g_pfEfl = paTests[iTest].fEflIn;
|
---|
473 | g_aBinU16[iFn].pfn(g_pu16, paTests[iTest].uSrcIn, g_pfEfl);
|
---|
474 | RTTEST_CHECK(g_hTest, *g_pu16== paTests[iTest].uDstOut);
|
---|
475 | RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut);
|
---|
476 | }
|
---|
477 | }
|
---|
478 | }
|
---|
479 | }
|
---|
480 |
|
---|
481 |
|
---|
482 | /*
|
---|
483 | * 32-bit binary operations.
|
---|
484 | */
|
---|
485 |
|
---|
486 | #ifndef HAVE_BINU32_TESTS
|
---|
487 | static const BINU32_TEST_T g_aTests_add_u32[] = { {0} };
|
---|
488 | static const BINU32_TEST_T g_aTests_add_u32_locked[] = { {0} };
|
---|
489 | static const BINU32_TEST_T g_aTests_adc_u32[] = { {0} };
|
---|
490 | static const BINU32_TEST_T g_aTests_adc_u32_locked[] = { {0} };
|
---|
491 | static const BINU32_TEST_T g_aTests_sub_u32[] = { {0} };
|
---|
492 | static const BINU32_TEST_T g_aTests_sub_u32_locked[] = { {0} };
|
---|
493 | static const BINU32_TEST_T g_aTests_sbb_u32[] = { {0} };
|
---|
494 | static const BINU32_TEST_T g_aTests_sbb_u32_locked[] = { {0} };
|
---|
495 | static const BINU32_TEST_T g_aTests_or_u32[] = { {0} };
|
---|
496 | static const BINU32_TEST_T g_aTests_or_u32_locked[] = { {0} };
|
---|
497 | static const BINU32_TEST_T g_aTests_xor_u32[] = { {0} };
|
---|
498 | static const BINU32_TEST_T g_aTests_xor_u32_locked[] = { {0} };
|
---|
499 | static const BINU32_TEST_T g_aTests_and_u32[] = { {0} };
|
---|
500 | static const BINU32_TEST_T g_aTests_and_u32_locked[] = { {0} };
|
---|
501 | static const BINU32_TEST_T g_aTests_cmp_u32[] = { {0} };
|
---|
502 | static const BINU32_TEST_T g_aTests_test_u32[] = { {0} };
|
---|
503 | static const BINU32_TEST_T g_aTests_bt_u32[] = { {0} };
|
---|
504 | static const BINU32_TEST_T g_aTests_btc_u32[] = { {0} };
|
---|
505 | static const BINU32_TEST_T g_aTests_btc_u32_locked[] = { {0} };
|
---|
506 | static const BINU32_TEST_T g_aTests_btr_u32[] = { {0} };
|
---|
507 | static const BINU32_TEST_T g_aTests_btr_u32_locked[] = { {0} };
|
---|
508 | static const BINU32_TEST_T g_aTests_bts_u32[] = { {0} };
|
---|
509 | static const BINU32_TEST_T g_aTests_bts_u32_locked[] = { {0} };
|
---|
510 | static const BINU32_TEST_T g_aTests_bsf_u32[] = { {0} };
|
---|
511 | static const BINU32_TEST_T g_aTests_bsr_u32[] = { {0} };
|
---|
512 | static const BINU32_TEST_T g_aTests_imul_two_u32[] = { {0} };
|
---|
513 | #endif
|
---|
514 |
|
---|
515 | static const BINU32_T g_aBinU32[] =
|
---|
516 | {
|
---|
517 | ENTRY(add_u32),
|
---|
518 | ENTRY(add_u32_locked),
|
---|
519 | ENTRY(adc_u32),
|
---|
520 | ENTRY(adc_u32_locked),
|
---|
521 | ENTRY(sub_u32),
|
---|
522 | ENTRY(sub_u32_locked),
|
---|
523 | ENTRY(sbb_u32),
|
---|
524 | ENTRY(sbb_u32_locked),
|
---|
525 | ENTRY(or_u32),
|
---|
526 | ENTRY(or_u32_locked),
|
---|
527 | ENTRY(xor_u32),
|
---|
528 | ENTRY(xor_u32_locked),
|
---|
529 | ENTRY(and_u32),
|
---|
530 | ENTRY(and_u32_locked),
|
---|
531 | ENTRY(cmp_u32),
|
---|
532 | ENTRY(test_u32),
|
---|
533 | ENTRY_EX(bt_u32, 1),
|
---|
534 | ENTRY_EX(btc_u32, 1),
|
---|
535 | ENTRY_EX(btc_u32_locked, 1),
|
---|
536 | ENTRY_EX(btr_u32, 1),
|
---|
537 | ENTRY_EX(btr_u32_locked, 1),
|
---|
538 | ENTRY_EX(bts_u32, 1),
|
---|
539 | ENTRY_EX(bts_u32_locked, 1),
|
---|
540 | ENTRY(bsf_u32),
|
---|
541 | ENTRY(bsr_u32),
|
---|
542 | ENTRY(imul_two_u32),
|
---|
543 | };
|
---|
544 |
|
---|
545 | static void BinU32Generate(uint32_t cTests)
|
---|
546 | {
|
---|
547 | RTPrintf("\n\n#define HAVE_BINU32_TESTS\n");
|
---|
548 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aBinU32); iFn++)
|
---|
549 | {
|
---|
550 | RTPrintf("static const BINU32_TEST_T g_aTests_%s[] =\n{\n", g_aBinU32[iFn].pszName);
|
---|
551 | for (uint32_t iTest = 0; iTest < cTests; iTest++ )
|
---|
552 | {
|
---|
553 | BINU32_TEST_T Test;
|
---|
554 | Test.fEflIn = RandEFlags();
|
---|
555 | Test.fEflOut = Test.fEflIn;
|
---|
556 | Test.uDstIn = RandU32();
|
---|
557 | Test.uDstOut = Test.uDstIn;
|
---|
558 | Test.uSrcIn = RandU32();
|
---|
559 | if (g_aBinU32[iFn].uExtra)
|
---|
560 | Test.uSrcIn &= 0x1f; /* Restrict bit index to a word */
|
---|
561 | Test.uMisc = 0;
|
---|
562 | g_aBinU32[iFn].pfn(&Test.uDstOut, Test.uSrcIn, &Test.fEflOut);
|
---|
563 | RTPrintf(" { %#08x, %#08x, %#010RX32, %#010RX32, %#010RX32, %#x }, /* #%u */\n",
|
---|
564 | Test.fEflIn, Test.fEflOut, Test.uDstIn, Test.uDstOut, Test.uSrcIn, Test.uMisc, iTest);
|
---|
565 | }
|
---|
566 | RTPrintf("};\n");
|
---|
567 | }
|
---|
568 | }
|
---|
569 |
|
---|
570 | static void BinU32Test(void)
|
---|
571 | {
|
---|
572 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aBinU32); iFn++)
|
---|
573 | {
|
---|
574 | RTTestSub(g_hTest, g_aBinU32[iFn].pszName);
|
---|
575 |
|
---|
576 | BINU32_TEST_T const * const paTests = g_aBinU32[iFn].paTests;
|
---|
577 | uint32_t const cTests = g_aBinU32[iFn].cTests;
|
---|
578 | for (uint32_t iTest = 0; iTest < cTests; iTest++ )
|
---|
579 | {
|
---|
580 | uint32_t fEfl = paTests[iTest].fEflIn;
|
---|
581 | uint32_t uDst = paTests[iTest].uDstIn;
|
---|
582 | g_aBinU32[iFn].pfn(&uDst, paTests[iTest].uSrcIn, &fEfl);
|
---|
583 | if ( uDst != paTests[iTest].uDstOut
|
---|
584 | || fEfl != paTests[iTest].fEflOut)
|
---|
585 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#010RX32 src=%#010RX32 -> efl=%#08x dst=%#010RX32, expected %#08x & %#010RX32%s - %s\n",
|
---|
586 | iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uSrcIn,
|
---|
587 | fEfl, uDst, paTests[iTest].fEflOut, paTests[iTest].uDstOut,
|
---|
588 | EFlagsDiff(fEfl, paTests[iTest].fEflOut),
|
---|
589 | uDst == paTests[iTest].uDstOut ? "eflags" : fEfl == paTests[iTest].fEflOut ? "dst" : "both");
|
---|
590 | else
|
---|
591 | {
|
---|
592 | *g_pu32 = paTests[iTest].uDstIn;
|
---|
593 | *g_pfEfl = paTests[iTest].fEflIn;
|
---|
594 | g_aBinU32[iFn].pfn(g_pu32, paTests[iTest].uSrcIn, g_pfEfl);
|
---|
595 | RTTEST_CHECK(g_hTest, *g_pu32 == paTests[iTest].uDstOut);
|
---|
596 | RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut);
|
---|
597 | }
|
---|
598 | }
|
---|
599 | }
|
---|
600 | }
|
---|
601 |
|
---|
602 |
|
---|
603 | /*
|
---|
604 | * 64-bit binary operations.
|
---|
605 | */
|
---|
606 |
|
---|
607 | #ifndef HAVE_BINU64_TESTS
|
---|
608 | static const BINU64_TEST_T g_aTests_add_u64[] = { {0} };
|
---|
609 | static const BINU64_TEST_T g_aTests_add_u64_locked[] = { {0} };
|
---|
610 | static const BINU64_TEST_T g_aTests_adc_u64[] = { {0} };
|
---|
611 | static const BINU64_TEST_T g_aTests_adc_u64_locked[] = { {0} };
|
---|
612 | static const BINU64_TEST_T g_aTests_sub_u64[] = { {0} };
|
---|
613 | static const BINU64_TEST_T g_aTests_sub_u64_locked[] = { {0} };
|
---|
614 | static const BINU64_TEST_T g_aTests_sbb_u64[] = { {0} };
|
---|
615 | static const BINU64_TEST_T g_aTests_sbb_u64_locked[] = { {0} };
|
---|
616 | static const BINU64_TEST_T g_aTests_or_u64[] = { {0} };
|
---|
617 | static const BINU64_TEST_T g_aTests_or_u64_locked[] = { {0} };
|
---|
618 | static const BINU64_TEST_T g_aTests_xor_u64[] = { {0} };
|
---|
619 | static const BINU64_TEST_T g_aTests_xor_u64_locked[] = { {0} };
|
---|
620 | static const BINU64_TEST_T g_aTests_and_u64[] = { {0} };
|
---|
621 | static const BINU64_TEST_T g_aTests_and_u64_locked[] = { {0} };
|
---|
622 | static const BINU64_TEST_T g_aTests_cmp_u64[] = { {0} };
|
---|
623 | static const BINU64_TEST_T g_aTests_test_u64[] = { {0} };
|
---|
624 | static const BINU64_TEST_T g_aTests_bt_u64[] = { {0} };
|
---|
625 | static const BINU64_TEST_T g_aTests_btc_u64[] = { {0} };
|
---|
626 | static const BINU64_TEST_T g_aTests_btc_u64_locked[] = { {0} };
|
---|
627 | static const BINU64_TEST_T g_aTests_btr_u64[] = { {0} };
|
---|
628 | static const BINU64_TEST_T g_aTests_btr_u64_locked[] = { {0} };
|
---|
629 | static const BINU64_TEST_T g_aTests_bts_u64[] = { {0} };
|
---|
630 | static const BINU64_TEST_T g_aTests_bts_u64_locked[] = { {0} };
|
---|
631 | static const BINU64_TEST_T g_aTests_bsf_u64[] = { {0} };
|
---|
632 | static const BINU64_TEST_T g_aTests_bsr_u64[] = { {0} };
|
---|
633 | static const BINU64_TEST_T g_aTests_imul_two_u64[] = { {0} };
|
---|
634 | #endif
|
---|
635 |
|
---|
636 | static const BINU64_T g_aBinU64[] =
|
---|
637 | {
|
---|
638 | ENTRY(add_u64),
|
---|
639 | ENTRY(add_u64_locked),
|
---|
640 | ENTRY(adc_u64),
|
---|
641 | ENTRY(adc_u64_locked),
|
---|
642 | ENTRY(sub_u64),
|
---|
643 | ENTRY(sub_u64_locked),
|
---|
644 | ENTRY(sbb_u64),
|
---|
645 | ENTRY(sbb_u64_locked),
|
---|
646 | ENTRY(or_u64),
|
---|
647 | ENTRY(or_u64_locked),
|
---|
648 | ENTRY(xor_u64),
|
---|
649 | ENTRY(xor_u64_locked),
|
---|
650 | ENTRY(and_u64),
|
---|
651 | ENTRY(and_u64_locked),
|
---|
652 | ENTRY(cmp_u64),
|
---|
653 | ENTRY(test_u64),
|
---|
654 | ENTRY_EX(bt_u64, 1),
|
---|
655 | ENTRY_EX(btc_u64, 1),
|
---|
656 | ENTRY_EX(btc_u64_locked, 1),
|
---|
657 | ENTRY_EX(btr_u64, 1),
|
---|
658 | ENTRY_EX(btr_u64_locked, 1),
|
---|
659 | ENTRY_EX(bts_u64, 1),
|
---|
660 | ENTRY_EX(bts_u64_locked, 1),
|
---|
661 | ENTRY(bsf_u64),
|
---|
662 | ENTRY(bsr_u64),
|
---|
663 | ENTRY(imul_two_u64),
|
---|
664 | };
|
---|
665 |
|
---|
666 | static void BinU64Generate(uint32_t cTests)
|
---|
667 | {
|
---|
668 | RTPrintf("\n\n#define HAVE_BINU64_TESTS\n");
|
---|
669 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aBinU64); iFn++)
|
---|
670 | {
|
---|
671 | RTPrintf("static const BINU64_TEST_T g_aTests_%s[] =\n{\n", g_aBinU64[iFn].pszName);
|
---|
672 | for (uint32_t iTest = 0; iTest < cTests; iTest++ )
|
---|
673 | {
|
---|
674 | BINU64_TEST_T Test;
|
---|
675 | Test.fEflIn = RandEFlags();
|
---|
676 | Test.fEflOut = Test.fEflIn;
|
---|
677 | Test.uDstIn = RandU64();
|
---|
678 | Test.uDstOut = Test.uDstIn;
|
---|
679 | Test.uSrcIn = RandU64();
|
---|
680 | if (g_aBinU64[iFn].uExtra)
|
---|
681 | Test.uSrcIn &= 0x3f; /* Restrict bit index to a word */
|
---|
682 | Test.uMisc = 0;
|
---|
683 | g_aBinU64[iFn].pfn(&Test.uDstOut, Test.uSrcIn, &Test.fEflOut);
|
---|
684 | RTPrintf(" { %#08x, %#08x, %#018RX64, %#018RX64, %#018RX64, %#x }, /* #%u */\n",
|
---|
685 | Test.fEflIn, Test.fEflOut, Test.uDstIn, Test.uDstOut, Test.uSrcIn, Test.uMisc, iTest);
|
---|
686 | }
|
---|
687 | RTPrintf("};\n");
|
---|
688 | }
|
---|
689 | }
|
---|
690 |
|
---|
691 | static void BinU64Test(void)
|
---|
692 | {
|
---|
693 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aBinU64); iFn++)
|
---|
694 | {
|
---|
695 | RTTestSub(g_hTest, g_aBinU64[iFn].pszName);
|
---|
696 |
|
---|
697 | BINU64_TEST_T const * const paTests = g_aBinU64[iFn].paTests;
|
---|
698 | uint32_t const cTests = g_aBinU64[iFn].cTests;
|
---|
699 | for (uint32_t iTest = 0; iTest < cTests; iTest++ )
|
---|
700 | {
|
---|
701 | uint32_t fEfl = paTests[iTest].fEflIn;
|
---|
702 | uint64_t uDst = paTests[iTest].uDstIn;
|
---|
703 | g_aBinU64[iFn].pfn(&uDst, paTests[iTest].uSrcIn, &fEfl);
|
---|
704 | if ( uDst != paTests[iTest].uDstOut
|
---|
705 | || fEfl != paTests[iTest].fEflOut)
|
---|
706 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#018RX64 src=%#018RX64 -> efl=%#08x dst=%#018RX64, expected %#08x & %#018RX64%s - %s\n",
|
---|
707 | iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uSrcIn,
|
---|
708 | fEfl, uDst, paTests[iTest].fEflOut, paTests[iTest].uDstOut,
|
---|
709 | EFlagsDiff(fEfl, paTests[iTest].fEflOut),
|
---|
710 | uDst == paTests[iTest].uDstOut ? "eflags" : fEfl == paTests[iTest].fEflOut ? "dst" : "both");
|
---|
711 | else
|
---|
712 | {
|
---|
713 | *g_pu64 = paTests[iTest].uDstIn;
|
---|
714 | *g_pfEfl = paTests[iTest].fEflIn;
|
---|
715 | g_aBinU64[iFn].pfn(g_pu64, paTests[iTest].uSrcIn, g_pfEfl);
|
---|
716 | RTTEST_CHECK(g_hTest, *g_pu64 == paTests[iTest].uDstOut);
|
---|
717 | RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut);
|
---|
718 | }
|
---|
719 | }
|
---|
720 | }
|
---|
721 | }
|
---|
722 |
|
---|
723 |
|
---|
724 | /*
|
---|
725 | * XCHG
|
---|
726 | */
|
---|
727 | static void XchgTest(void)
|
---|
728 | {
|
---|
729 | RTTestSub(g_hTest, "xchg");
|
---|
730 | typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXCHGU8, (uint8_t *pu8Mem, uint8_t *pu8Reg));
|
---|
731 | typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXCHGU16,(uint16_t *pu16Mem, uint16_t *pu16Reg));
|
---|
732 | typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXCHGU32,(uint32_t *pu32Mem, uint32_t *pu32Reg));
|
---|
733 | typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXCHGU64,(uint64_t *pu64Mem, uint64_t *pu64Reg));
|
---|
734 |
|
---|
735 | static struct
|
---|
736 | {
|
---|
737 | uint8_t cb; uint64_t fMask;
|
---|
738 | union
|
---|
739 | {
|
---|
740 | uintptr_t pfn;
|
---|
741 | FNIEMAIMPLXCHGU8 *pfnU8;
|
---|
742 | FNIEMAIMPLXCHGU16 *pfnU16;
|
---|
743 | FNIEMAIMPLXCHGU32 *pfnU32;
|
---|
744 | FNIEMAIMPLXCHGU64 *pfnU64;
|
---|
745 | } u;
|
---|
746 | }
|
---|
747 | s_aXchgWorkers[] =
|
---|
748 | {
|
---|
749 | { 1, UINT8_MAX, { (uintptr_t)iemAImpl_xchg_u8_locked } },
|
---|
750 | { 2, UINT16_MAX, { (uintptr_t)iemAImpl_xchg_u16_locked } },
|
---|
751 | { 4, UINT32_MAX, { (uintptr_t)iemAImpl_xchg_u32_locked } },
|
---|
752 | { 8, UINT64_MAX, { (uintptr_t)iemAImpl_xchg_u64_locked } },
|
---|
753 | { 1, UINT8_MAX, { (uintptr_t)iemAImpl_xchg_u8_unlocked } },
|
---|
754 | { 2, UINT16_MAX, { (uintptr_t)iemAImpl_xchg_u16_unlocked } },
|
---|
755 | { 4, UINT32_MAX, { (uintptr_t)iemAImpl_xchg_u32_unlocked } },
|
---|
756 | { 8, UINT64_MAX, { (uintptr_t)iemAImpl_xchg_u64_unlocked } },
|
---|
757 | };
|
---|
758 | for (size_t i = 0; i < RT_ELEMENTS(s_aXchgWorkers); i++)
|
---|
759 | {
|
---|
760 | RTUINT64U uIn1, uIn2, uMem, uDst;
|
---|
761 | uMem.u = uIn1.u = RTRandU64Ex(0, s_aXchgWorkers[i].fMask);
|
---|
762 | uDst.u = uIn2.u = RTRandU64Ex(0, s_aXchgWorkers[i].fMask);
|
---|
763 | if (uIn1.u == uIn2.u)
|
---|
764 | uDst.u = uIn2.u = ~uIn2.u;
|
---|
765 |
|
---|
766 | switch (s_aXchgWorkers[i].cb)
|
---|
767 | {
|
---|
768 | case 1:
|
---|
769 | s_aXchgWorkers[i].u.pfnU8(g_pu8, g_pu8Two);
|
---|
770 | s_aXchgWorkers[i].u.pfnU8(&uMem.au8[0], &uDst.au8[0]);
|
---|
771 | break;
|
---|
772 | case 2:
|
---|
773 | s_aXchgWorkers[i].u.pfnU16(g_pu16, g_pu16Two);
|
---|
774 | s_aXchgWorkers[i].u.pfnU16(&uMem.Words.w0, &uDst.Words.w0);
|
---|
775 | break;
|
---|
776 | case 4:
|
---|
777 | s_aXchgWorkers[i].u.pfnU32(g_pu32, g_pu32Two);
|
---|
778 | s_aXchgWorkers[i].u.pfnU32(&uMem.DWords.dw0, &uDst.DWords.dw0);
|
---|
779 | break;
|
---|
780 | case 8:
|
---|
781 | s_aXchgWorkers[i].u.pfnU64(g_pu64, g_pu64Two);
|
---|
782 | s_aXchgWorkers[i].u.pfnU64(&uMem.u, &uDst.u);
|
---|
783 | break;
|
---|
784 | default: RTTestFailed(g_hTest, "%d\n", s_aXchgWorkers[i].cb); break;
|
---|
785 | }
|
---|
786 |
|
---|
787 | if (uMem.u != uIn2.u || uDst.u != uIn1.u)
|
---|
788 | RTTestFailed(g_hTest, "i=%u: %#RX64, %#RX64 -> %#RX64, %#RX64\n", i, uIn1.u, uIn2.u, uMem.u, uDst.u);
|
---|
789 | }
|
---|
790 | }
|
---|
791 |
|
---|
792 |
|
---|
793 | /*
|
---|
794 | * XADD
|
---|
795 | */
|
---|
796 | static void XaddTest(void)
|
---|
797 | {
|
---|
798 | #define TEST_XADD(a_cBits, a_Type, a_Fmt) do { \
|
---|
799 | typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU ## a_cBits, (a_Type *, a_Type *, uint32_t *)); \
|
---|
800 | static struct \
|
---|
801 | { \
|
---|
802 | const char *pszName; \
|
---|
803 | FNIEMAIMPLXADDU ## a_cBits *pfn; \
|
---|
804 | BINU ## a_cBits ## _TEST_T const *paTests; \
|
---|
805 | uint32_t cTests; \
|
---|
806 | } const s_aFuncs[] = \
|
---|
807 | { \
|
---|
808 | { "xadd_u" # a_cBits, iemAImpl_xadd_u ## a_cBits, \
|
---|
809 | g_aTests_add_u ## a_cBits, RT_ELEMENTS(g_aTests_add_u ## a_cBits) }, \
|
---|
810 | { "xadd_u" # a_cBits "8_locked", iemAImpl_xadd_u ## a_cBits ## _locked, \
|
---|
811 | g_aTests_add_u ## a_cBits, RT_ELEMENTS(g_aTests_add_u ## a_cBits) }, \
|
---|
812 | }; \
|
---|
813 | for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++) \
|
---|
814 | { \
|
---|
815 | RTTestSub(g_hTest, s_aFuncs[iFn].pszName); \
|
---|
816 | BINU ## a_cBits ## _TEST_T const * const paTests = s_aFuncs[iFn].paTests; \
|
---|
817 | uint32_t const cTests = s_aFuncs[iFn].cTests; \
|
---|
818 | for (uint32_t iTest = 0; iTest < cTests; iTest++) \
|
---|
819 | { \
|
---|
820 | uint32_t fEfl = paTests[iTest].fEflIn; \
|
---|
821 | a_Type uSrc = paTests[iTest].uSrcIn; \
|
---|
822 | *g_pu ## a_cBits = paTests[iTest].uDstIn; \
|
---|
823 | s_aFuncs[iFn].pfn(g_pu ## a_cBits, &uSrc, &fEfl); \
|
---|
824 | if ( fEfl != paTests[iTest].fEflOut \
|
---|
825 | || *g_pu ## a_cBits != paTests[iTest].uDstOut \
|
---|
826 | || uSrc != paTests[iTest].uDstIn) \
|
---|
827 | RTTestFailed(g_hTest, "%s/#%u: efl=%#08x dst=" a_Fmt " src=" a_Fmt " -> efl=%#08x dst=" a_Fmt " src=" a_Fmt ", expected %#08x, " a_Fmt ", " a_Fmt "%s\n", \
|
---|
828 | s_aFuncs[iFn].pszName, iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uSrcIn, \
|
---|
829 | fEfl, *g_pu ## a_cBits, uSrc, paTests[iTest].fEflOut, paTests[iTest].uDstOut, paTests[iTest].uDstIn, \
|
---|
830 | EFlagsDiff(fEfl, paTests[iTest].fEflOut)); \
|
---|
831 | } \
|
---|
832 | } \
|
---|
833 | } while(0)
|
---|
834 | TEST_XADD(8, uint8_t, "%#04x");
|
---|
835 | TEST_XADD(16, uint16_t, "%#06x");
|
---|
836 | TEST_XADD(32, uint32_t, "%#010RX32");
|
---|
837 | TEST_XADD(64, uint64_t, "%#010RX64");
|
---|
838 | }
|
---|
839 |
|
---|
840 |
|
---|
841 | /*
|
---|
842 | * CMPXCHG
|
---|
843 | */
|
---|
844 |
|
---|
845 | static void CmpXchgTest(void)
|
---|
846 | {
|
---|
847 | #define TEST_CMPXCHG(a_cBits, a_Type, a_Fmt) do {\
|
---|
848 | typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLCMPXCHGU ## a_cBits, (a_Type *, a_Type *, a_Type, uint32_t *)); \
|
---|
849 | static struct \
|
---|
850 | { \
|
---|
851 | const char *pszName; \
|
---|
852 | FNIEMAIMPLCMPXCHGU ## a_cBits *pfn; \
|
---|
853 | PFNIEMAIMPLBINU ## a_cBits pfnSub; \
|
---|
854 | BINU ## a_cBits ## _TEST_T const *paTests; \
|
---|
855 | uint32_t cTests; \
|
---|
856 | } const s_aFuncs[] = \
|
---|
857 | { \
|
---|
858 | { "cmpxchg_u" # a_cBits, iemAImpl_cmpxchg_u ## a_cBits, iemAImpl_sub_u ## a_cBits, \
|
---|
859 | g_aTests_cmp_u ## a_cBits, RT_ELEMENTS(g_aTests_cmp_u ## a_cBits) }, \
|
---|
860 | { "cmpxchg_u" # a_cBits "_locked", iemAImpl_cmpxchg_u ## a_cBits ## _locked, iemAImpl_sub_u ## a_cBits, \
|
---|
861 | g_aTests_cmp_u ## a_cBits, RT_ELEMENTS(g_aTests_cmp_u ## a_cBits) }, \
|
---|
862 | }; \
|
---|
863 | for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++) \
|
---|
864 | { \
|
---|
865 | RTTestSub(g_hTest, s_aFuncs[iFn].pszName); \
|
---|
866 | BINU ## a_cBits ## _TEST_T const * const paTests = s_aFuncs[iFn].paTests; \
|
---|
867 | uint32_t const cTests = s_aFuncs[iFn].cTests; \
|
---|
868 | for (uint32_t iTest = 0; iTest < cTests; iTest++) \
|
---|
869 | { \
|
---|
870 | /* as is (99% likely to be negative). */ \
|
---|
871 | uint32_t fEfl = paTests[iTest].fEflIn; \
|
---|
872 | a_Type const uNew = paTests[iTest].uSrcIn + 0x42; \
|
---|
873 | a_Type uA = paTests[iTest].uDstIn; \
|
---|
874 | *g_pu ## a_cBits = paTests[iTest].uSrcIn; \
|
---|
875 | a_Type const uExpect = uA != paTests[iTest].uSrcIn ? paTests[iTest].uSrcIn : uNew; \
|
---|
876 | s_aFuncs[iFn].pfn(g_pu ## a_cBits, &uA, uNew, &fEfl); \
|
---|
877 | if ( fEfl != paTests[iTest].fEflOut \
|
---|
878 | || *g_pu ## a_cBits != uExpect \
|
---|
879 | || uA != paTests[iTest].uSrcIn) \
|
---|
880 | RTTestFailed(g_hTest, "%s/#%ua: efl=%#08x dst=" a_Fmt " cmp=" a_Fmt " new=" a_Fmt " -> efl=%#08x dst=" a_Fmt " old=" a_Fmt ", expected %#08x, " a_Fmt ", " a_Fmt "%s\n", \
|
---|
881 | s_aFuncs[iFn].pszName, iTest, paTests[iTest].fEflIn, paTests[iTest].uSrcIn, paTests[iTest].uDstIn, \
|
---|
882 | uNew, fEfl, *g_pu ## a_cBits, uA, paTests[iTest].fEflOut, uExpect, paTests[iTest].uSrcIn, \
|
---|
883 | EFlagsDiff(fEfl, paTests[iTest].fEflOut)); \
|
---|
884 | /* positive */ \
|
---|
885 | uint32_t fEflExpect = paTests[iTest].fEflIn; \
|
---|
886 | uA = paTests[iTest].uDstIn; \
|
---|
887 | s_aFuncs[iFn].pfnSub(&uA, uA, &fEflExpect); \
|
---|
888 | fEfl = paTests[iTest].fEflIn; \
|
---|
889 | uA = paTests[iTest].uDstIn; \
|
---|
890 | *g_pu ## a_cBits = uA; \
|
---|
891 | s_aFuncs[iFn].pfn(g_pu ## a_cBits, &uA, uNew, &fEfl); \
|
---|
892 | if ( fEfl != fEflExpect \
|
---|
893 | || *g_pu ## a_cBits != uNew \
|
---|
894 | || uA != paTests[iTest].uDstIn) \
|
---|
895 | RTTestFailed(g_hTest, "%s/#%ua: efl=%#08x dst=" a_Fmt " cmp=" a_Fmt " new=" a_Fmt " -> efl=%#08x dst=" a_Fmt " old=" a_Fmt ", expected %#08x, " a_Fmt ", " a_Fmt "%s\n", \
|
---|
896 | s_aFuncs[iFn].pszName, iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uDstIn, \
|
---|
897 | uNew, fEfl, *g_pu ## a_cBits, uA, fEflExpect, uNew, paTests[iTest].uDstIn, \
|
---|
898 | EFlagsDiff(fEfl, fEflExpect)); \
|
---|
899 | } \
|
---|
900 | } \
|
---|
901 | } while(0)
|
---|
902 | TEST_CMPXCHG(8, uint8_t, "%#04RX8");
|
---|
903 | TEST_CMPXCHG(16, uint16_t, "%#06x");
|
---|
904 | TEST_CMPXCHG(32, uint32_t, "%#010RX32");
|
---|
905 | #if ARCH_BITS != 32 /* calling convension issue, skipping as it's an unsupported host */
|
---|
906 | TEST_CMPXCHG(64, uint64_t, "%#010RX64");
|
---|
907 | #endif
|
---|
908 | }
|
---|
909 |
|
---|
910 | static void CmpXchg8bTest(void)
|
---|
911 | {
|
---|
912 | typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLCMPXCHG8B,(uint64_t *, PRTUINT64U, PRTUINT64U, uint32_t *));
|
---|
913 | static struct
|
---|
914 | {
|
---|
915 | const char *pszName;
|
---|
916 | FNIEMAIMPLCMPXCHG8B *pfn;
|
---|
917 | } const s_aFuncs[] =
|
---|
918 | {
|
---|
919 | { "cmpxchg8b", iemAImpl_cmpxchg8b },
|
---|
920 | { "cmpxchg8b_locked", iemAImpl_cmpxchg8b_locked },
|
---|
921 | };
|
---|
922 | for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++)
|
---|
923 | {
|
---|
924 | RTTestSub(g_hTest, s_aFuncs[iFn].pszName);
|
---|
925 | for (uint32_t iTest = 0; iTest < 4; iTest += 2)
|
---|
926 | {
|
---|
927 | uint64_t const uOldValue = RandU64();
|
---|
928 | uint64_t const uNewValue = RandU64();
|
---|
929 |
|
---|
930 | /* positive test. */
|
---|
931 | RTUINT64U uA, uB;
|
---|
932 | uB.u = uNewValue;
|
---|
933 | uA.u = uOldValue;
|
---|
934 | *g_pu64 = uOldValue;
|
---|
935 | uint32_t fEflIn = RandEFlags();
|
---|
936 | uint32_t fEfl = fEflIn;
|
---|
937 | s_aFuncs[iFn].pfn(g_pu64, &uA, &uB, &fEfl);
|
---|
938 | if ( fEfl != (fEflIn | X86_EFL_ZF)
|
---|
939 | || *g_pu64 != uNewValue
|
---|
940 | || uA.u != uOldValue)
|
---|
941 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#018RX64 cmp=%#018RX64 new=%#018RX64\n -> efl=%#08x dst=%#018RX64 old=%#018RX64,\n wanted %#08x, %#018RX64, %#018RX64%s\n",
|
---|
942 | iTest, fEflIn, uOldValue, uOldValue, uNewValue,
|
---|
943 | fEfl, *g_pu64, uA.u,
|
---|
944 | (fEflIn | X86_EFL_ZF), uNewValue, uOldValue, EFlagsDiff(fEfl, fEflIn | X86_EFL_ZF));
|
---|
945 | RTTEST_CHECK(g_hTest, uB.u == uNewValue);
|
---|
946 |
|
---|
947 | /* negative */
|
---|
948 | uint64_t const uExpect = ~uOldValue;
|
---|
949 | *g_pu64 = uExpect;
|
---|
950 | uA.u = uOldValue;
|
---|
951 | uB.u = uNewValue;
|
---|
952 | fEfl = fEflIn = RandEFlags();
|
---|
953 | s_aFuncs[iFn].pfn(g_pu64, &uA, &uB, &fEfl);
|
---|
954 | if ( fEfl != (fEflIn & ~X86_EFL_ZF)
|
---|
955 | || *g_pu64 != uExpect
|
---|
956 | || uA.u != uExpect)
|
---|
957 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#018RX64 cmp=%#018RX64 new=%#018RX64\n -> efl=%#08x dst=%#018RX64 old=%#018RX64,\n wanted %#08x, %#018RX64, %#018RX64%s\n",
|
---|
958 | iTest + 1, fEflIn, uExpect, uOldValue, uNewValue,
|
---|
959 | fEfl, *g_pu64, uA.u,
|
---|
960 | (fEflIn & ~X86_EFL_ZF), uExpect, uExpect, EFlagsDiff(fEfl, fEflIn & ~X86_EFL_ZF));
|
---|
961 | RTTEST_CHECK(g_hTest, uB.u == uNewValue);
|
---|
962 | }
|
---|
963 | }
|
---|
964 | }
|
---|
965 |
|
---|
966 | static void CmpXchg16bTest(void)
|
---|
967 | {
|
---|
968 | typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLCMPXCHG16B,(PRTUINT128U, PRTUINT128U, PRTUINT128U, uint32_t *));
|
---|
969 | static struct
|
---|
970 | {
|
---|
971 | const char *pszName;
|
---|
972 | FNIEMAIMPLCMPXCHG16B *pfn;
|
---|
973 | } const s_aFuncs[] =
|
---|
974 | {
|
---|
975 | { "cmpxchg16b", iemAImpl_cmpxchg16b },
|
---|
976 | { "cmpxchg16b_locked", iemAImpl_cmpxchg16b_locked },
|
---|
977 | #if !defined(RT_ARCH_ARM64)
|
---|
978 | { "cmpxchg16b_fallback", iemAImpl_cmpxchg16b_fallback },
|
---|
979 | #endif
|
---|
980 | };
|
---|
981 | for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++)
|
---|
982 | {
|
---|
983 | #if !defined(IEM_WITHOUT_ASSEMBLY) && defined(RT_ARCH_AMD64)
|
---|
984 | if (!(ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_CX16))
|
---|
985 | continue;
|
---|
986 | #endif
|
---|
987 | RTTestSub(g_hTest, s_aFuncs[iFn].pszName);
|
---|
988 | for (uint32_t iTest = 0; iTest < 4; iTest += 2)
|
---|
989 | {
|
---|
990 | RTUINT128U const uOldValue = RandU128();
|
---|
991 | RTUINT128U const uNewValue = RandU128();
|
---|
992 |
|
---|
993 | /* positive test. */
|
---|
994 | RTUINT128U uA, uB;
|
---|
995 | uB = uNewValue;
|
---|
996 | uA = uOldValue;
|
---|
997 | *g_pu128 = uOldValue;
|
---|
998 | uint32_t fEflIn = RandEFlags();
|
---|
999 | uint32_t fEfl = fEflIn;
|
---|
1000 | s_aFuncs[iFn].pfn(g_pu128, &uA, &uB, &fEfl);
|
---|
1001 | if ( fEfl != (fEflIn | X86_EFL_ZF)
|
---|
1002 | || g_pu128->s.Lo != uNewValue.s.Lo
|
---|
1003 | || g_pu128->s.Hi != uNewValue.s.Hi
|
---|
1004 | || uA.s.Lo != uOldValue.s.Lo
|
---|
1005 | || uA.s.Hi != uOldValue.s.Hi)
|
---|
1006 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#018RX64'%016RX64 cmp=%#018RX64'%016RX64 new=%#018RX64'%016RX64\n"
|
---|
1007 | " -> efl=%#08x dst=%#018RX64'%016RX64 old=%#018RX64'%016RX64,\n"
|
---|
1008 | " wanted %#08x, %#018RX64'%016RX64, %#018RX64'%016RX64%s\n",
|
---|
1009 | iTest, fEflIn, uOldValue.s.Hi, uOldValue.s.Lo, uOldValue.s.Hi, uOldValue.s.Lo, uNewValue.s.Hi, uNewValue.s.Lo,
|
---|
1010 | fEfl, g_pu128->s.Hi, g_pu128->s.Lo, uA.s.Hi, uA.s.Lo,
|
---|
1011 | (fEflIn | X86_EFL_ZF), uNewValue.s.Hi, uNewValue.s.Lo, uOldValue.s.Hi, uOldValue.s.Lo,
|
---|
1012 | EFlagsDiff(fEfl, fEflIn | X86_EFL_ZF));
|
---|
1013 | RTTEST_CHECK(g_hTest, uB.s.Lo == uNewValue.s.Lo && uB.s.Hi == uNewValue.s.Hi);
|
---|
1014 |
|
---|
1015 | /* negative */
|
---|
1016 | RTUINT128U const uExpect = RTUINT128_INIT(~uOldValue.s.Hi, ~uOldValue.s.Lo);
|
---|
1017 | *g_pu128 = uExpect;
|
---|
1018 | uA = uOldValue;
|
---|
1019 | uB = uNewValue;
|
---|
1020 | fEfl = fEflIn = RandEFlags();
|
---|
1021 | s_aFuncs[iFn].pfn(g_pu128, &uA, &uB, &fEfl);
|
---|
1022 | if ( fEfl != (fEflIn & ~X86_EFL_ZF)
|
---|
1023 | || g_pu128->s.Lo != uExpect.s.Lo
|
---|
1024 | || g_pu128->s.Hi != uExpect.s.Hi
|
---|
1025 | || uA.s.Lo != uExpect.s.Lo
|
---|
1026 | || uA.s.Hi != uExpect.s.Hi)
|
---|
1027 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=%#018RX64'%016RX64 cmp=%#018RX64'%016RX64 new=%#018RX64'%016RX64\n"
|
---|
1028 | " -> efl=%#08x dst=%#018RX64'%016RX64 old=%#018RX64'%016RX64,\n"
|
---|
1029 | " wanted %#08x, %#018RX64'%016RX64, %#018RX64'%016RX64%s\n",
|
---|
1030 | iTest + 1, fEflIn, uExpect.s.Hi, uExpect.s.Lo, uOldValue.s.Hi, uOldValue.s.Lo, uNewValue.s.Hi, uNewValue.s.Lo,
|
---|
1031 | fEfl, g_pu128->s.Hi, g_pu128->s.Lo, uA.s.Hi, uA.s.Lo,
|
---|
1032 | (fEflIn & ~X86_EFL_ZF), uExpect.s.Hi, uExpect.s.Lo, uExpect.s.Hi, uExpect.s.Lo,
|
---|
1033 | EFlagsDiff(fEfl, fEflIn & ~X86_EFL_ZF));
|
---|
1034 | RTTEST_CHECK(g_hTest, uB.s.Lo == uNewValue.s.Lo && uB.s.Hi == uNewValue.s.Hi);
|
---|
1035 | }
|
---|
1036 | }
|
---|
1037 | }
|
---|
1038 |
|
---|
1039 |
|
---|
1040 | /*
|
---|
1041 | * Double shifts.
|
---|
1042 | *
|
---|
1043 | * Note! We use BINUxx_TEST_T with the shift value in the uMisc field.
|
---|
1044 | */
|
---|
1045 |
|
---|
1046 | #ifndef HAVE_SHIFT_DBL_TESTS
|
---|
1047 | static const BINU16_TEST_T g_aTests_shrd_u16[] = { {0} };
|
---|
1048 | static const BINU16_TEST_T g_aTests_shld_u16[] = { {0} };
|
---|
1049 | static const BINU32_TEST_T g_aTests_shrd_u32[] = { {0} };
|
---|
1050 | static const BINU32_TEST_T g_aTests_shld_u32[] = { {0} };
|
---|
1051 | static const BINU64_TEST_T g_aTests_shrd_u64[] = { {0} };
|
---|
1052 | static const BINU64_TEST_T g_aTests_shld_u64[] = { {0} };
|
---|
1053 | #endif
|
---|
1054 |
|
---|
1055 | #define TEST_SHIFT_DBL(a_cBits, a_Type, a_Fmt) \
|
---|
1056 | static const struct \
|
---|
1057 | { \
|
---|
1058 | const char *pszName; \
|
---|
1059 | PFNIEMAIMPLSHIFTDBLU ## a_cBits pfn; \
|
---|
1060 | BINU ## a_cBits ## _TEST_T const *paTests; \
|
---|
1061 | uint32_t cTests, uExtra; \
|
---|
1062 | } g_aShiftDblU ## a_cBits [] = \
|
---|
1063 | { \
|
---|
1064 | ENTRY(shld_u ## a_cBits), \
|
---|
1065 | ENTRY(shrd_u ## a_cBits), \
|
---|
1066 | }; \
|
---|
1067 | \
|
---|
1068 | static void ShiftDblU ## a_cBits ## Generate(uint32_t cTests) \
|
---|
1069 | { \
|
---|
1070 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aShiftDblU ## a_cBits); iFn++) \
|
---|
1071 | { \
|
---|
1072 | RTPrintf("static const BINU" #a_cBits "_TEST_T g_aTests_%s[] =\n{\n", g_aShiftDblU ## a_cBits[iFn].pszName); \
|
---|
1073 | for (uint32_t iTest = 0; iTest < cTests; iTest++ ) \
|
---|
1074 | { \
|
---|
1075 | BINU ## a_cBits ## _TEST_T Test; \
|
---|
1076 | Test.fEflIn = RandEFlags(); \
|
---|
1077 | Test.fEflOut = Test.fEflIn; \
|
---|
1078 | Test.uDstIn = RandU ## a_cBits(); \
|
---|
1079 | Test.uDstOut = Test.uDstIn; \
|
---|
1080 | Test.uSrcIn = RandU ## a_cBits(); \
|
---|
1081 | Test.uMisc = RandU8() & (a_cBits - 1); \
|
---|
1082 | g_aShiftDblU ## a_cBits[iFn].pfn(&Test.uDstOut, Test.uSrcIn, Test.uMisc, &Test.fEflOut); \
|
---|
1083 | RTPrintf(" { %#08x, %#08x, " a_Fmt ", " a_Fmt ", " a_Fmt ", %2u }, /* #%u */\n", \
|
---|
1084 | Test.fEflIn, Test.fEflOut, Test.uDstIn, Test.uDstOut, Test.uSrcIn, Test.uMisc, iTest); \
|
---|
1085 | } \
|
---|
1086 | RTPrintf("};\n"); \
|
---|
1087 | } \
|
---|
1088 | } \
|
---|
1089 | \
|
---|
1090 | static void ShiftDblU ## a_cBits ## Test(void) \
|
---|
1091 | { \
|
---|
1092 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aShiftDblU ## a_cBits); iFn++) \
|
---|
1093 | { \
|
---|
1094 | RTTestSub(g_hTest, g_aShiftDblU ## a_cBits[iFn].pszName); \
|
---|
1095 | BINU ## a_cBits ## _TEST_T const * const paTests = g_aShiftDblU ## a_cBits[iFn].paTests; \
|
---|
1096 | uint32_t const cTests = g_aShiftDblU ## a_cBits[iFn].cTests; \
|
---|
1097 | for (uint32_t iTest = 0; iTest < cTests; iTest++ ) \
|
---|
1098 | { \
|
---|
1099 | uint32_t fEfl = paTests[iTest].fEflIn; \
|
---|
1100 | a_Type uDst = paTests[iTest].uDstIn; \
|
---|
1101 | g_aShiftDblU ## a_cBits[iFn].pfn(&uDst, paTests[iTest].uSrcIn, paTests[iTest].uMisc, &fEfl); \
|
---|
1102 | if ( uDst != paTests[iTest].uDstOut \
|
---|
1103 | || (fEfl /*| X86_EFL_AF*/) != (paTests[iTest].fEflOut /*| X86_EFL_AF*/)) \
|
---|
1104 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=" a_Fmt " src=" a_Fmt " shift=%-2u -> efl=%#08x dst=" a_Fmt ", expected %#08x & " a_Fmt "%s\n", \
|
---|
1105 | iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uSrcIn, (unsigned)paTests[iTest].uMisc, \
|
---|
1106 | fEfl, uDst, paTests[iTest].fEflOut, paTests[iTest].uDstOut, \
|
---|
1107 | EFlagsDiff(fEfl /*| X86_EFL_AF*/, paTests[iTest].fEflOut /*| X86_EFL_AF*/)); \
|
---|
1108 | else \
|
---|
1109 | { \
|
---|
1110 | *g_pu ## a_cBits = paTests[iTest].uDstIn; \
|
---|
1111 | *g_pfEfl = paTests[iTest].fEflIn; \
|
---|
1112 | g_aShiftDblU ## a_cBits[iFn].pfn(g_pu ## a_cBits, paTests[iTest].uSrcIn, paTests[iTest].uMisc, g_pfEfl); \
|
---|
1113 | RTTEST_CHECK(g_hTest, *g_pu ## a_cBits == paTests[iTest].uDstOut); \
|
---|
1114 | RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut); \
|
---|
1115 | } \
|
---|
1116 | } \
|
---|
1117 | } \
|
---|
1118 | }
|
---|
1119 | TEST_SHIFT_DBL(16, uint16_t, "%#06RX16")
|
---|
1120 | TEST_SHIFT_DBL(32, uint32_t, "%#010RX32")
|
---|
1121 | TEST_SHIFT_DBL(64, uint64_t, "%#018RX64")
|
---|
1122 |
|
---|
1123 | static void ShiftDblGenerate(uint32_t cTests)
|
---|
1124 | {
|
---|
1125 | RTPrintf("\n\n#define HAVE_SHIFT_DBL_TESTS\n");
|
---|
1126 | ShiftDblU16Generate(cTests);
|
---|
1127 | ShiftDblU32Generate(cTests);
|
---|
1128 | ShiftDblU64Generate(cTests);
|
---|
1129 | }
|
---|
1130 |
|
---|
1131 | static void ShiftDblTest(void)
|
---|
1132 | {
|
---|
1133 | ShiftDblU16Test();
|
---|
1134 | ShiftDblU32Test();
|
---|
1135 | ShiftDblU64Test();
|
---|
1136 | }
|
---|
1137 |
|
---|
1138 |
|
---|
1139 | /*
|
---|
1140 | * Unary operators.
|
---|
1141 | *
|
---|
1142 | * Note! We use BINUxx_TEST_T ignoreing uSrcIn and uMisc.
|
---|
1143 | */
|
---|
1144 |
|
---|
1145 | #ifndef HAVE_UNARY_TESTS
|
---|
1146 | # define DUMMY_UNARY_TESTS(a_cBits, a_Type) \
|
---|
1147 | static const a_Type g_aTests_inc_u ## a_cBits[] = { {0} }; \
|
---|
1148 | static const a_Type g_aTests_inc_u ## a_cBits ## _locked[] = { {0} }; \
|
---|
1149 | static const a_Type g_aTests_dec_u ## a_cBits[] = { {0} }; \
|
---|
1150 | static const a_Type g_aTests_dec_u ## a_cBits ## _locked[] = { {0} }; \
|
---|
1151 | static const a_Type g_aTests_not_u ## a_cBits[] = { {0} }; \
|
---|
1152 | static const a_Type g_aTests_not_u ## a_cBits ## _locked[] = { {0} }; \
|
---|
1153 | static const a_Type g_aTests_neg_u ## a_cBits[] = { {0} }; \
|
---|
1154 | static const a_Type g_aTests_neg_u ## a_cBits ## _locked[] = { {0} }
|
---|
1155 | DUMMY_UNARY_TESTS(8, BINU8_TEST_T);
|
---|
1156 | DUMMY_UNARY_TESTS(16, BINU16_TEST_T);
|
---|
1157 | DUMMY_UNARY_TESTS(32, BINU32_TEST_T);
|
---|
1158 | DUMMY_UNARY_TESTS(64, BINU64_TEST_T);
|
---|
1159 | #endif
|
---|
1160 |
|
---|
1161 | #define TEST_UNARY(a_cBits, a_Type, a_Fmt, a_TestType) \
|
---|
1162 | static const struct \
|
---|
1163 | { \
|
---|
1164 | const char *pszName; \
|
---|
1165 | PFNIEMAIMPLUNARYU ## a_cBits pfn; \
|
---|
1166 | a_TestType const *paTests; \
|
---|
1167 | uint32_t cTests, uExtra; \
|
---|
1168 | } g_aUnaryU ## a_cBits [] = \
|
---|
1169 | { \
|
---|
1170 | ENTRY(inc_u ## a_cBits), \
|
---|
1171 | ENTRY(inc_u ## a_cBits ## _locked), \
|
---|
1172 | ENTRY(dec_u ## a_cBits), \
|
---|
1173 | ENTRY(dec_u ## a_cBits ## _locked), \
|
---|
1174 | ENTRY(not_u ## a_cBits), \
|
---|
1175 | ENTRY(not_u ## a_cBits ## _locked), \
|
---|
1176 | ENTRY(neg_u ## a_cBits), \
|
---|
1177 | ENTRY(neg_u ## a_cBits ## _locked), \
|
---|
1178 | }; \
|
---|
1179 | \
|
---|
1180 | static void UnaryU ## a_cBits ## Generate(uint32_t cTests) \
|
---|
1181 | { \
|
---|
1182 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aUnaryU ## a_cBits); iFn++) \
|
---|
1183 | { \
|
---|
1184 | RTPrintf("static const BINU" #a_cBits "_TEST_T g_aTests_%s[] =\n{\n", g_aUnaryU ## a_cBits[iFn].pszName); \
|
---|
1185 | for (uint32_t iTest = 0; iTest < cTests; iTest++ ) \
|
---|
1186 | { \
|
---|
1187 | a_TestType Test; \
|
---|
1188 | Test.fEflIn = RandEFlags(); \
|
---|
1189 | Test.fEflOut = Test.fEflIn; \
|
---|
1190 | Test.uDstIn = RandU ## a_cBits(); \
|
---|
1191 | Test.uDstOut = Test.uDstIn; \
|
---|
1192 | Test.uSrcIn = 0; \
|
---|
1193 | Test.uMisc = 0; \
|
---|
1194 | g_aUnaryU ## a_cBits[iFn].pfn(&Test.uDstOut, &Test.fEflOut); \
|
---|
1195 | RTPrintf(" { %#08x, %#08x, " a_Fmt ", " a_Fmt ", 0, 0 }, /* #%u */\n", \
|
---|
1196 | Test.fEflIn, Test.fEflOut, Test.uDstIn, Test.uDstOut, iTest); \
|
---|
1197 | } \
|
---|
1198 | RTPrintf("};\n"); \
|
---|
1199 | } \
|
---|
1200 | } \
|
---|
1201 | \
|
---|
1202 | static void UnaryU ## a_cBits ## Test(void) \
|
---|
1203 | { \
|
---|
1204 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aUnaryU ## a_cBits); iFn++) \
|
---|
1205 | { \
|
---|
1206 | RTTestSub(g_hTest, g_aUnaryU ## a_cBits[iFn].pszName); \
|
---|
1207 | a_TestType const * const paTests = g_aUnaryU ## a_cBits[iFn].paTests; \
|
---|
1208 | uint32_t const cTests = g_aUnaryU ## a_cBits[iFn].cTests; \
|
---|
1209 | for (uint32_t iTest = 0; iTest < cTests; iTest++ ) \
|
---|
1210 | { \
|
---|
1211 | uint32_t fEfl = paTests[iTest].fEflIn; \
|
---|
1212 | a_Type uDst = paTests[iTest].uDstIn; \
|
---|
1213 | g_aUnaryU ## a_cBits[iFn].pfn(&uDst, &fEfl); \
|
---|
1214 | if ( uDst != paTests[iTest].uDstOut \
|
---|
1215 | || fEfl != paTests[iTest].fEflOut) \
|
---|
1216 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=" a_Fmt " -> efl=%#08x dst=" a_Fmt ", expected %#08x & " a_Fmt "%s\n", \
|
---|
1217 | iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, \
|
---|
1218 | fEfl, uDst, paTests[iTest].fEflOut, paTests[iTest].uDstOut, \
|
---|
1219 | EFlagsDiff(fEfl, paTests[iTest].fEflOut)); \
|
---|
1220 | else \
|
---|
1221 | { \
|
---|
1222 | *g_pu ## a_cBits = paTests[iTest].uDstIn; \
|
---|
1223 | *g_pfEfl = paTests[iTest].fEflIn; \
|
---|
1224 | g_aUnaryU ## a_cBits[iFn].pfn(g_pu ## a_cBits, g_pfEfl); \
|
---|
1225 | RTTEST_CHECK(g_hTest, *g_pu ## a_cBits == paTests[iTest].uDstOut); \
|
---|
1226 | RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut); \
|
---|
1227 | } \
|
---|
1228 | } \
|
---|
1229 | } \
|
---|
1230 | }
|
---|
1231 | TEST_UNARY(8, uint8_t, "%#04RX8", BINU8_TEST_T)
|
---|
1232 | TEST_UNARY(16, uint16_t, "%#06RX16", BINU16_TEST_T)
|
---|
1233 | TEST_UNARY(32, uint32_t, "%#010RX32", BINU32_TEST_T)
|
---|
1234 | TEST_UNARY(64, uint64_t, "%#018RX64", BINU64_TEST_T)
|
---|
1235 |
|
---|
1236 | static void UnaryGenerate(uint32_t cTests)
|
---|
1237 | {
|
---|
1238 | RTPrintf("\n\n#define HAVE_UNARY_TESTS\n");
|
---|
1239 | UnaryU8Generate(cTests);
|
---|
1240 | UnaryU16Generate(cTests);
|
---|
1241 | UnaryU32Generate(cTests);
|
---|
1242 | UnaryU64Generate(cTests);
|
---|
1243 | }
|
---|
1244 |
|
---|
1245 | static void UnaryTest(void)
|
---|
1246 | {
|
---|
1247 | UnaryU8Test();
|
---|
1248 | UnaryU16Test();
|
---|
1249 | UnaryU32Test();
|
---|
1250 | UnaryU64Test();
|
---|
1251 | }
|
---|
1252 |
|
---|
1253 |
|
---|
1254 | /*
|
---|
1255 | * Shifts.
|
---|
1256 | *
|
---|
1257 | * Note! We use BINUxx_TEST_T with the shift count in uMisc and uSrcIn unused.
|
---|
1258 | */
|
---|
1259 |
|
---|
1260 | #ifndef HAVE_SHIFT_TESTS
|
---|
1261 | # define DUMMY_SHIFT_TESTS(a_cBits, a_Type) \
|
---|
1262 | static const a_Type g_aTests_rol_u ## a_cBits[] = { {0} }; \
|
---|
1263 | static const a_Type g_aTests_ror_u ## a_cBits[] = { {0} }; \
|
---|
1264 | static const a_Type g_aTests_rcl_u ## a_cBits[] = { {0} }; \
|
---|
1265 | static const a_Type g_aTests_rcr_u ## a_cBits[] = { {0} }; \
|
---|
1266 | static const a_Type g_aTests_shl_u ## a_cBits[] = { {0} }; \
|
---|
1267 | static const a_Type g_aTests_shr_u ## a_cBits[] = { {0} }; \
|
---|
1268 | static const a_Type g_aTests_sar_u ## a_cBits[] = { {0} }
|
---|
1269 | DUMMY_SHIFT_TESTS(8, BINU8_TEST_T);
|
---|
1270 | DUMMY_SHIFT_TESTS(16, BINU16_TEST_T);
|
---|
1271 | DUMMY_SHIFT_TESTS(32, BINU32_TEST_T);
|
---|
1272 | DUMMY_SHIFT_TESTS(64, BINU64_TEST_T);
|
---|
1273 | #endif
|
---|
1274 |
|
---|
1275 | #define TEST_SHIFT(a_cBits, a_Type, a_Fmt, a_TestType) \
|
---|
1276 | static const struct \
|
---|
1277 | { \
|
---|
1278 | const char *pszName; \
|
---|
1279 | PFNIEMAIMPLSHIFTU ## a_cBits pfn; \
|
---|
1280 | a_TestType const *paTests; \
|
---|
1281 | uint32_t cTests, uExtra; \
|
---|
1282 | } g_aShiftU ## a_cBits [] = \
|
---|
1283 | { \
|
---|
1284 | ENTRY(rol_u ## a_cBits), \
|
---|
1285 | ENTRY(ror_u ## a_cBits), \
|
---|
1286 | ENTRY(rcl_u ## a_cBits), \
|
---|
1287 | ENTRY(rcr_u ## a_cBits), \
|
---|
1288 | ENTRY(shl_u ## a_cBits), \
|
---|
1289 | ENTRY(shr_u ## a_cBits), \
|
---|
1290 | ENTRY(sar_u ## a_cBits), \
|
---|
1291 | }; \
|
---|
1292 | \
|
---|
1293 | static void ShiftU ## a_cBits ## Generate(uint32_t cTests) \
|
---|
1294 | { \
|
---|
1295 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aShiftU ## a_cBits); iFn++) \
|
---|
1296 | { \
|
---|
1297 | RTPrintf("static const BINU" #a_cBits "_TEST_T g_aTests_%s[] =\n{\n", g_aShiftU ## a_cBits[iFn].pszName); \
|
---|
1298 | for (uint32_t iTest = 0; iTest < cTests; iTest++ ) \
|
---|
1299 | { \
|
---|
1300 | a_TestType Test; \
|
---|
1301 | Test.fEflIn = RandEFlags(); \
|
---|
1302 | Test.fEflOut = Test.fEflIn; \
|
---|
1303 | Test.uDstIn = RandU ## a_cBits(); \
|
---|
1304 | Test.uDstOut = Test.uDstIn; \
|
---|
1305 | Test.uSrcIn = 0; \
|
---|
1306 | Test.uMisc = RandU8() & (a_cBits - 1); \
|
---|
1307 | g_aShiftU ## a_cBits[iFn].pfn(&Test.uDstOut, Test.uMisc, &Test.fEflOut); \
|
---|
1308 | RTPrintf(" { %#08x, %#08x, " a_Fmt ", " a_Fmt ", 0, %-2u }, /* #%u */\n", \
|
---|
1309 | Test.fEflIn, Test.fEflOut, Test.uDstIn, Test.uDstOut, Test.uMisc, iTest); \
|
---|
1310 | } \
|
---|
1311 | RTPrintf("};\n"); \
|
---|
1312 | } \
|
---|
1313 | } \
|
---|
1314 | \
|
---|
1315 | static void ShiftU ## a_cBits ## Test(void) \
|
---|
1316 | { \
|
---|
1317 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aShiftU ## a_cBits); iFn++) \
|
---|
1318 | { \
|
---|
1319 | RTTestSub(g_hTest, g_aShiftU ## a_cBits[iFn].pszName); \
|
---|
1320 | a_TestType const * const paTests = g_aShiftU ## a_cBits[iFn].paTests; \
|
---|
1321 | uint32_t const cTests = g_aShiftU ## a_cBits[iFn].cTests; \
|
---|
1322 | for (uint32_t iTest = 0; iTest < cTests; iTest++ ) \
|
---|
1323 | { \
|
---|
1324 | uint32_t fEfl = paTests[iTest].fEflIn; \
|
---|
1325 | a_Type uDst = paTests[iTest].uDstIn; \
|
---|
1326 | g_aShiftU ## a_cBits[iFn].pfn(&uDst, paTests[iTest].uMisc, &fEfl); \
|
---|
1327 | if ( uDst != paTests[iTest].uDstOut \
|
---|
1328 | || fEfl != paTests[iTest].fEflOut) \
|
---|
1329 | RTTestFailed(g_hTest, "#%u: efl=%#08x dst=" a_Fmt " shift=%2u -> efl=%#08x dst=" a_Fmt ", expected %#08x & " a_Fmt "%s\n", \
|
---|
1330 | iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uMisc, \
|
---|
1331 | fEfl, uDst, paTests[iTest].fEflOut, paTests[iTest].uDstOut, \
|
---|
1332 | EFlagsDiff(fEfl, paTests[iTest].fEflOut)); \
|
---|
1333 | else \
|
---|
1334 | { \
|
---|
1335 | *g_pu ## a_cBits = paTests[iTest].uDstIn; \
|
---|
1336 | *g_pfEfl = paTests[iTest].fEflIn; \
|
---|
1337 | g_aShiftU ## a_cBits[iFn].pfn(g_pu ## a_cBits, paTests[iTest].uMisc, g_pfEfl); \
|
---|
1338 | RTTEST_CHECK(g_hTest, *g_pu ## a_cBits == paTests[iTest].uDstOut); \
|
---|
1339 | RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut); \
|
---|
1340 | } \
|
---|
1341 | } \
|
---|
1342 | } \
|
---|
1343 | }
|
---|
1344 | TEST_SHIFT(8, uint8_t, "%#04RX8", BINU8_TEST_T)
|
---|
1345 | TEST_SHIFT(16, uint16_t, "%#06RX16", BINU16_TEST_T)
|
---|
1346 | TEST_SHIFT(32, uint32_t, "%#010RX32", BINU32_TEST_T)
|
---|
1347 | TEST_SHIFT(64, uint64_t, "%#018RX64", BINU64_TEST_T)
|
---|
1348 |
|
---|
1349 | static void ShiftGenerate(uint32_t cTests)
|
---|
1350 | {
|
---|
1351 | RTPrintf("\n\n#define HAVE_SHIFT_TESTS\n");
|
---|
1352 | ShiftU8Generate(cTests);
|
---|
1353 | ShiftU16Generate(cTests);
|
---|
1354 | ShiftU32Generate(cTests);
|
---|
1355 | ShiftU64Generate(cTests);
|
---|
1356 | }
|
---|
1357 |
|
---|
1358 | static void ShiftTest(void)
|
---|
1359 | {
|
---|
1360 | ShiftU8Test();
|
---|
1361 | ShiftU16Test();
|
---|
1362 | ShiftU32Test();
|
---|
1363 | ShiftU64Test();
|
---|
1364 | }
|
---|
1365 |
|
---|
1366 |
|
---|
1367 | /*
|
---|
1368 | * Multiplication and division.
|
---|
1369 | *
|
---|
1370 | * Note! The 8-bit functions has a different format, so we need to duplicate things.
|
---|
1371 | * Note! Currently ignoring undefined bits.
|
---|
1372 | */
|
---|
1373 |
|
---|
1374 | #ifndef HAVE_MULDIV_TESTS
|
---|
1375 | # define DUMMY_MULDIV_TESTS(a_cBits, a_Type) \
|
---|
1376 | static const a_Type g_aTests_mul_u ## a_cBits[] = { {0} }; \
|
---|
1377 | static const a_Type g_aTests_imul_u ## a_cBits[] = { {0} }; \
|
---|
1378 | static const a_Type g_aTests_div_u ## a_cBits[] = { {0} }; \
|
---|
1379 | static const a_Type g_aTests_idiv_u ## a_cBits[] = { {0} }
|
---|
1380 | DUMMY_MULDIV_TESTS(8, MULDIVU8_TEST_T);
|
---|
1381 | DUMMY_MULDIV_TESTS(16, MULDIVU16_TEST_T);
|
---|
1382 | DUMMY_MULDIV_TESTS(32, MULDIVU32_TEST_T);
|
---|
1383 | DUMMY_MULDIV_TESTS(64, MULDIVU64_TEST_T);
|
---|
1384 | #endif
|
---|
1385 |
|
---|
1386 | /* U8 */
|
---|
1387 | static const struct
|
---|
1388 | {
|
---|
1389 | const char *pszName;
|
---|
1390 | PFNIEMAIMPLMULDIVU8 pfn;
|
---|
1391 | MULDIVU8_TEST_T const *paTests;
|
---|
1392 | uint32_t cTests, uExtra;
|
---|
1393 | } g_aMulDivU8[] =
|
---|
1394 | {
|
---|
1395 | ENTRY_EX(mul_u8, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF),
|
---|
1396 | ENTRY_EX(imul_u8, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF),
|
---|
1397 | ENTRY_EX(div_u8, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF),
|
---|
1398 | ENTRY_EX(idiv_u8, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF),
|
---|
1399 | };
|
---|
1400 |
|
---|
1401 | static void MulDivU8Generate(uint32_t cTests)
|
---|
1402 | {
|
---|
1403 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aMulDivU8); iFn++)
|
---|
1404 | {
|
---|
1405 | RTPrintf("static const MULDIVU8_TEST_T g_aTests_%s[] =\n{\n", g_aMulDivU8[iFn].pszName);
|
---|
1406 | for (uint32_t iTest = 0; iTest < cTests; iTest++ )
|
---|
1407 | {
|
---|
1408 | MULDIVU8_TEST_T Test;
|
---|
1409 | Test.fEflIn = RandEFlags();
|
---|
1410 | Test.fEflOut = Test.fEflIn;
|
---|
1411 | Test.uDstIn = RandU16();
|
---|
1412 | Test.uDstOut = Test.uDstIn;
|
---|
1413 | Test.uSrcIn = RandU8();
|
---|
1414 | Test.rc = g_aMulDivU8[iFn].pfn(&Test.uDstOut, Test.uSrcIn, &Test.fEflOut);
|
---|
1415 | RTPrintf(" { %#08x, %#08x, %#06RX16, %#06RX16, %#04RX8, %d }, /* #%u */\n",
|
---|
1416 | Test.fEflIn, Test.fEflOut, Test.uDstIn, Test.uDstOut, Test.uSrcIn, Test.rc, iTest);
|
---|
1417 | }
|
---|
1418 | RTPrintf("};\n");
|
---|
1419 | }
|
---|
1420 | }
|
---|
1421 |
|
---|
1422 | static void MulDivU8Test(void)
|
---|
1423 | {
|
---|
1424 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aMulDivU8); iFn++)
|
---|
1425 | {
|
---|
1426 | RTTestSub(g_hTest, g_aMulDivU8[iFn].pszName);
|
---|
1427 | MULDIVU8_TEST_T const * const paTests = g_aMulDivU8[iFn].paTests;
|
---|
1428 | uint32_t const cTests = g_aMulDivU8[iFn].cTests;
|
---|
1429 | uint32_t const fEflIgn = g_aMulDivU8[iFn].uExtra;
|
---|
1430 | for (uint32_t iTest = 0; iTest < cTests; iTest++ )
|
---|
1431 | {
|
---|
1432 | uint32_t fEfl = paTests[iTest].fEflIn;
|
---|
1433 | uint16_t uDst = paTests[iTest].uDstIn;
|
---|
1434 | int rc = g_aMulDivU8[iFn].pfn(&uDst, paTests[iTest].uSrcIn, &fEfl);
|
---|
1435 | if ( uDst != paTests[iTest].uDstOut
|
---|
1436 | || (fEfl | fEflIgn) != (paTests[iTest].fEflOut | fEflIgn)
|
---|
1437 | || rc != paTests[iTest].rc)
|
---|
1438 | RTTestFailed(g_hTest, "#%02u: efl=%#08x dst=%#06RX16 src=%#04RX8\n"
|
---|
1439 | " -> efl=%#08x dst=%#06RX16 rc=%d\n"
|
---|
1440 | "expected %#08x %#06RX16 %d%s\n",
|
---|
1441 | iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uSrcIn,
|
---|
1442 | fEfl, uDst, rc, paTests[iTest].fEflOut, paTests[iTest].uDstOut, paTests[iTest].rc,
|
---|
1443 | EFlagsDiff(fEfl | fEflIgn, paTests[iTest].fEflOut | fEflIgn));
|
---|
1444 | else
|
---|
1445 | {
|
---|
1446 | *g_pu16 = paTests[iTest].uDstIn;
|
---|
1447 | *g_pfEfl = paTests[iTest].fEflIn;
|
---|
1448 | rc = g_aMulDivU8[iFn].pfn(g_pu16, paTests[iTest].uSrcIn, g_pfEfl);
|
---|
1449 | RTTEST_CHECK(g_hTest, *g_pu16 == paTests[iTest].uDstOut);
|
---|
1450 | RTTEST_CHECK(g_hTest, (*g_pfEfl | fEflIgn) == (paTests[iTest].fEflOut | fEflIgn));
|
---|
1451 | RTTEST_CHECK(g_hTest, rc == paTests[iTest].rc);
|
---|
1452 | }
|
---|
1453 | }
|
---|
1454 | }
|
---|
1455 | }
|
---|
1456 |
|
---|
1457 | #define TEST_MULDIV(a_cBits, a_Type, a_Fmt, a_TestType) \
|
---|
1458 | static const struct \
|
---|
1459 | { \
|
---|
1460 | const char *pszName; \
|
---|
1461 | PFNIEMAIMPLMULDIVU ## a_cBits pfn; \
|
---|
1462 | a_TestType const *paTests; \
|
---|
1463 | uint32_t cTests, uExtra; \
|
---|
1464 | } g_aMulDivU ## a_cBits [] = \
|
---|
1465 | { \
|
---|
1466 | ENTRY_EX(mul_u ## a_cBits, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), \
|
---|
1467 | ENTRY_EX(imul_u ## a_cBits, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF), \
|
---|
1468 | ENTRY_EX(div_u ## a_cBits, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF), \
|
---|
1469 | ENTRY_EX(idiv_u ## a_cBits, X86_EFL_SF | X86_EFL_ZF | X86_EFL_AF | X86_EFL_PF | X86_EFL_CF | X86_EFL_OF), \
|
---|
1470 | }; \
|
---|
1471 | \
|
---|
1472 | static void MulDivU ## a_cBits ## Generate(uint32_t cTests) \
|
---|
1473 | { \
|
---|
1474 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aMulDivU ## a_cBits); iFn++) \
|
---|
1475 | { \
|
---|
1476 | RTPrintf("static const MULDIVU" #a_cBits "_TEST_T g_aTests_%s[] =\n{\n", g_aMulDivU ## a_cBits[iFn].pszName); \
|
---|
1477 | for (uint32_t iTest = 0; iTest < cTests; iTest++ ) \
|
---|
1478 | { \
|
---|
1479 | a_TestType Test; \
|
---|
1480 | Test.fEflIn = RandEFlags(); \
|
---|
1481 | Test.fEflOut = Test.fEflIn; \
|
---|
1482 | Test.uDst1In = RandU ## a_cBits(); \
|
---|
1483 | Test.uDst1Out = Test.uDst1In; \
|
---|
1484 | Test.uDst2In = RandU ## a_cBits(); \
|
---|
1485 | Test.uDst2Out = Test.uDst2In; \
|
---|
1486 | Test.uSrcIn = RandU ## a_cBits(); \
|
---|
1487 | Test.rc = g_aMulDivU ## a_cBits[iFn].pfn(&Test.uDst1Out, &Test.uDst2Out, Test.uSrcIn, &Test.fEflOut); \
|
---|
1488 | RTPrintf(" { %#08x, %#08x, " a_Fmt ", " a_Fmt ", " a_Fmt ", " a_Fmt ", " a_Fmt ", %d }, /* #%u */\n", \
|
---|
1489 | Test.fEflIn, Test.fEflOut, Test.uDst1In, Test.uDst1Out, Test.uDst2In, Test.uDst2Out, Test.uSrcIn, \
|
---|
1490 | Test.rc, iTest); \
|
---|
1491 | } \
|
---|
1492 | RTPrintf("};\n"); \
|
---|
1493 | } \
|
---|
1494 | } \
|
---|
1495 | \
|
---|
1496 | static void MulDivU ## a_cBits ## Test(void) \
|
---|
1497 | { \
|
---|
1498 | for (size_t iFn = 0; iFn < RT_ELEMENTS(g_aMulDivU ## a_cBits); iFn++) \
|
---|
1499 | { \
|
---|
1500 | RTTestSub(g_hTest, g_aMulDivU ## a_cBits[iFn].pszName); \
|
---|
1501 | a_TestType const * const paTests = g_aMulDivU ## a_cBits[iFn].paTests; \
|
---|
1502 | uint32_t const cTests = g_aMulDivU ## a_cBits[iFn].cTests; \
|
---|
1503 | uint32_t const fEflIgn = g_aMulDivU ## a_cBits[iFn].uExtra; \
|
---|
1504 | for (uint32_t iTest = 0; iTest < cTests; iTest++ ) \
|
---|
1505 | { \
|
---|
1506 | uint32_t fEfl = paTests[iTest].fEflIn; \
|
---|
1507 | a_Type uDst1 = paTests[iTest].uDst1In; \
|
---|
1508 | a_Type uDst2 = paTests[iTest].uDst2In; \
|
---|
1509 | int rc = g_aMulDivU ## a_cBits[iFn].pfn(&uDst1, &uDst2, paTests[iTest].uSrcIn, &fEfl); \
|
---|
1510 | if ( uDst1 != paTests[iTest].uDst1Out \
|
---|
1511 | || uDst2 != paTests[iTest].uDst2Out \
|
---|
1512 | || (fEfl | fEflIgn) != (paTests[iTest].fEflOut | fEflIgn)\
|
---|
1513 | || rc != paTests[iTest].rc) \
|
---|
1514 | RTTestFailed(g_hTest, "#%02u: efl=%#08x dst1=" a_Fmt " dst2=" a_Fmt " src=" a_Fmt "\n" \
|
---|
1515 | " -> efl=%#08x dst1=" a_Fmt " dst2=" a_Fmt " rc=%d\n" \
|
---|
1516 | "expected %#08x " a_Fmt " " a_Fmt " %d%s -%s%s%s\n", \
|
---|
1517 | iTest, paTests[iTest].fEflIn, paTests[iTest].uDst1In, paTests[iTest].uDst2In, paTests[iTest].uSrcIn, \
|
---|
1518 | fEfl, uDst1, uDst2, rc, \
|
---|
1519 | paTests[iTest].fEflOut, paTests[iTest].uDst1Out, paTests[iTest].uDst2Out, paTests[iTest].rc, \
|
---|
1520 | EFlagsDiff(fEfl | fEflIgn, paTests[iTest].fEflOut | fEflIgn), \
|
---|
1521 | uDst1 != paTests[iTest].uDst1Out ? " dst1" : "", uDst2 != paTests[iTest].uDst2Out ? " dst2" : "", \
|
---|
1522 | (fEfl | fEflIgn) != (paTests[iTest].fEflOut | fEflIgn) ? " eflags" : ""); \
|
---|
1523 | else \
|
---|
1524 | { \
|
---|
1525 | *g_pu ## a_cBits = paTests[iTest].uDst1In; \
|
---|
1526 | *g_pu ## a_cBits ## Two = paTests[iTest].uDst2In; \
|
---|
1527 | *g_pfEfl = paTests[iTest].fEflIn; \
|
---|
1528 | rc = g_aMulDivU ## a_cBits[iFn].pfn(g_pu ## a_cBits, g_pu ## a_cBits ## Two, paTests[iTest].uSrcIn, g_pfEfl); \
|
---|
1529 | RTTEST_CHECK(g_hTest, *g_pu ## a_cBits == paTests[iTest].uDst1Out); \
|
---|
1530 | RTTEST_CHECK(g_hTest, *g_pu ## a_cBits ## Two == paTests[iTest].uDst2Out); \
|
---|
1531 | RTTEST_CHECK(g_hTest, (*g_pfEfl | fEflIgn) == (paTests[iTest].fEflOut | fEflIgn)); \
|
---|
1532 | RTTEST_CHECK(g_hTest, rc == paTests[iTest].rc); \
|
---|
1533 | } \
|
---|
1534 | } \
|
---|
1535 | } \
|
---|
1536 | }
|
---|
1537 | TEST_MULDIV(16, uint16_t, "%#06RX16", MULDIVU16_TEST_T)
|
---|
1538 | TEST_MULDIV(32, uint32_t, "%#010RX32", MULDIVU32_TEST_T)
|
---|
1539 | TEST_MULDIV(64, uint64_t, "%#018RX64", MULDIVU64_TEST_T)
|
---|
1540 |
|
---|
1541 | static void MulDivGenerate(uint32_t cTests)
|
---|
1542 | {
|
---|
1543 | RTPrintf("\n\n#define HAVE_MULDIV_TESTS\n");
|
---|
1544 | MulDivU8Generate(cTests);
|
---|
1545 | MulDivU16Generate(cTests);
|
---|
1546 | MulDivU32Generate(cTests);
|
---|
1547 | MulDivU64Generate(cTests);
|
---|
1548 | }
|
---|
1549 |
|
---|
1550 | static void MulDivTest(void)
|
---|
1551 | {
|
---|
1552 | MulDivU8Test();
|
---|
1553 | MulDivU16Test();
|
---|
1554 | MulDivU32Test();
|
---|
1555 | MulDivU64Test();
|
---|
1556 | }
|
---|
1557 |
|
---|
1558 |
|
---|
1559 | /*
|
---|
1560 | * BSWAP
|
---|
1561 | */
|
---|
1562 | static void BswapTest(void)
|
---|
1563 | {
|
---|
1564 | RTTestSub(g_hTest, "bswap_u16");
|
---|
1565 | *g_pu32 = UINT32_C(0x12345678);
|
---|
1566 | iemAImpl_bswap_u16(g_pu32);
|
---|
1567 | #if 0
|
---|
1568 | RTTEST_CHECK_MSG(g_hTest, *g_pu32 == UINT32_C(0x12347856), (g_hTest, "*g_pu32=%#RX32\n", *g_pu32));
|
---|
1569 | #else
|
---|
1570 | RTTEST_CHECK_MSG(g_hTest, *g_pu32 == UINT32_C(0x12340000), (g_hTest, "*g_pu32=%#RX32\n", *g_pu32));
|
---|
1571 | #endif
|
---|
1572 | *g_pu32 = UINT32_C(0xffff1122);
|
---|
1573 | iemAImpl_bswap_u16(g_pu32);
|
---|
1574 | #if 0
|
---|
1575 | RTTEST_CHECK_MSG(g_hTest, *g_pu32 == UINT32_C(0xffff2211), (g_hTest, "*g_pu32=%#RX32\n", *g_pu32));
|
---|
1576 | #else
|
---|
1577 | RTTEST_CHECK_MSG(g_hTest, *g_pu32 == UINT32_C(0xffff0000), (g_hTest, "*g_pu32=%#RX32\n", *g_pu32));
|
---|
1578 | #endif
|
---|
1579 |
|
---|
1580 | RTTestSub(g_hTest, "bswap_u32");
|
---|
1581 | *g_pu32 = UINT32_C(0x12345678);
|
---|
1582 | iemAImpl_bswap_u32(g_pu32);
|
---|
1583 | RTTEST_CHECK(g_hTest, *g_pu32 == UINT32_C(0x78563412));
|
---|
1584 |
|
---|
1585 | RTTestSub(g_hTest, "bswap_u64");
|
---|
1586 | *g_pu64 = UINT64_C(0x0123456789abcdef);
|
---|
1587 | iemAImpl_bswap_u64(g_pu64);
|
---|
1588 | RTTEST_CHECK(g_hTest, *g_pu64 == UINT64_C(0xefcdab8967452301));
|
---|
1589 | }
|
---|
1590 |
|
---|
1591 |
|
---|
1592 | /*
|
---|
1593 | * Random helpers.
|
---|
1594 | */
|
---|
1595 |
|
---|
1596 | static uint32_t RandEFlags(void)
|
---|
1597 | {
|
---|
1598 | uint32_t fEfl = RTRandU32();
|
---|
1599 | return (fEfl & X86_EFL_LIVE_MASK) | X86_EFL_RA1_MASK;
|
---|
1600 | }
|
---|
1601 |
|
---|
1602 | static uint8_t RandU8(void)
|
---|
1603 | {
|
---|
1604 | return RTRandU32Ex(0, 0xff);
|
---|
1605 | }
|
---|
1606 |
|
---|
1607 |
|
---|
1608 | static uint16_t RandU16(void)
|
---|
1609 | {
|
---|
1610 | return RTRandU32Ex(0, 0xffff);
|
---|
1611 | }
|
---|
1612 |
|
---|
1613 |
|
---|
1614 | static uint32_t RandU32(void)
|
---|
1615 | {
|
---|
1616 | return RTRandU32();
|
---|
1617 | }
|
---|
1618 |
|
---|
1619 |
|
---|
1620 | static uint64_t RandU64(void)
|
---|
1621 | {
|
---|
1622 | return RTRandU64();
|
---|
1623 | }
|
---|
1624 |
|
---|
1625 |
|
---|
1626 | static RTUINT128U RandU128(void)
|
---|
1627 | {
|
---|
1628 | RTUINT128U Ret;
|
---|
1629 | Ret.s.Hi = RTRandU64();
|
---|
1630 | Ret.s.Lo = RTRandU64();
|
---|
1631 | return Ret;
|
---|
1632 | }
|
---|
1633 |
|
---|
1634 |
|
---|
1635 | int main(int argc, char **argv)
|
---|
1636 | {
|
---|
1637 | int rc = RTR3InitExe(argc, &argv, 0);
|
---|
1638 | if (RT_FAILURE(rc))
|
---|
1639 | return RTMsgInitFailure(rc);
|
---|
1640 |
|
---|
1641 | /*
|
---|
1642 | * Generate data?
|
---|
1643 | */
|
---|
1644 | if (argc > 2)
|
---|
1645 | {
|
---|
1646 | char szCpuDesc[256] = {0};
|
---|
1647 | RTMpGetDescription(NIL_RTCPUID, szCpuDesc, sizeof(szCpuDesc));
|
---|
1648 |
|
---|
1649 | RTPrintf("/* $Id: tstIEMAImpl.cpp 93893 2022-02-22 21:27:58Z vboxsync $ */\n"
|
---|
1650 | "/** @file\n"
|
---|
1651 | " * IEM Assembly Instruction Helper Testcase Data - %s.\n"
|
---|
1652 | " */\n"
|
---|
1653 | "\n"
|
---|
1654 | "/*\n"
|
---|
1655 | " * Copyright (C) 2022 Oracle Corporation\n"
|
---|
1656 | " *\n"
|
---|
1657 | " * This file is part of VirtualBox Open Source Edition (OSE), as\n"
|
---|
1658 | " * available from http://www.virtualbox.org. This file is free software;\n"
|
---|
1659 | " * you can redistribute it and/or modify it under the terms of the GNU\n"
|
---|
1660 | " * General Public License (GPL) as published by the Free Software\n"
|
---|
1661 | " * Foundation, in version 2 as it comes in the \"COPYING\" file of the\n"
|
---|
1662 | " * VirtualBox OSE distribution. VirtualBox OSE is distributed in the\n"
|
---|
1663 | " * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.\n"
|
---|
1664 | " */\n"
|
---|
1665 | "\n"
|
---|
1666 | , szCpuDesc);
|
---|
1667 | uint32_t cTests = 64;
|
---|
1668 | BinU8Generate(cTests);
|
---|
1669 | BinU16Generate(cTests);
|
---|
1670 | BinU32Generate(cTests);
|
---|
1671 | BinU64Generate(cTests);
|
---|
1672 | ShiftDblGenerate(cTests);
|
---|
1673 | UnaryGenerate(cTests);
|
---|
1674 | ShiftGenerate(cTests);
|
---|
1675 | MulDivGenerate(cTests);
|
---|
1676 | return RTEXITCODE_SUCCESS;
|
---|
1677 | }
|
---|
1678 |
|
---|
1679 | /*
|
---|
1680 | * Do testing. Currrently disabled by default as data needs to be checked
|
---|
1681 | * on both intel and AMD systems first.
|
---|
1682 | */
|
---|
1683 | rc = RTTestCreate("tstIEMAimpl", &g_hTest);
|
---|
1684 | AssertRCReturn(rc, RTEXITCODE_FAILURE);
|
---|
1685 | if (argc > 1)
|
---|
1686 | {
|
---|
1687 | /* Allocate guarded memory for use in the tests. */
|
---|
1688 | #define ALLOC_GUARDED_VAR(a_puVar) do { \
|
---|
1689 | rc = RTTestGuardedAlloc(g_hTest, sizeof(*a_puVar), sizeof(*a_puVar), false /*fHead*/, (void **)&a_puVar); \
|
---|
1690 | if (RT_FAILURE(rc)) RTTestFailed(g_hTest, "Failed to allocate guarded mem: " #a_puVar); \
|
---|
1691 | } while (0)
|
---|
1692 | ALLOC_GUARDED_VAR(g_pu8);
|
---|
1693 | ALLOC_GUARDED_VAR(g_pu16);
|
---|
1694 | ALLOC_GUARDED_VAR(g_pu32);
|
---|
1695 | ALLOC_GUARDED_VAR(g_pu64);
|
---|
1696 | ALLOC_GUARDED_VAR(g_pu128);
|
---|
1697 | ALLOC_GUARDED_VAR(g_pu8Two);
|
---|
1698 | ALLOC_GUARDED_VAR(g_pu16Two);
|
---|
1699 | ALLOC_GUARDED_VAR(g_pu32Two);
|
---|
1700 | ALLOC_GUARDED_VAR(g_pu64Two);
|
---|
1701 | ALLOC_GUARDED_VAR(g_pu128Two);
|
---|
1702 | ALLOC_GUARDED_VAR(g_pfEfl);
|
---|
1703 | if (RTTestErrorCount(g_hTest) == 0)
|
---|
1704 | {
|
---|
1705 | BinU8Test();
|
---|
1706 | BinU16Test();
|
---|
1707 | BinU32Test();
|
---|
1708 | BinU64Test();
|
---|
1709 | XchgTest();
|
---|
1710 | XaddTest();
|
---|
1711 | CmpXchgTest();
|
---|
1712 | CmpXchg8bTest();
|
---|
1713 | CmpXchg16bTest();
|
---|
1714 | ShiftDblTest();
|
---|
1715 | UnaryTest();
|
---|
1716 | ShiftTest();
|
---|
1717 | MulDivTest();
|
---|
1718 | BswapTest();
|
---|
1719 | }
|
---|
1720 | return RTTestSummaryAndDestroy(g_hTest);
|
---|
1721 | }
|
---|
1722 | return RTTestSkipAndDestroy(g_hTest, "unfinished testcase");
|
---|
1723 | }
|
---|