VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-instr-2-gen.cpp@ 104000

最後變更 在這個檔案從104000是 104000,由 vboxsync 提交於 12 月 前

ValKit/bs3-cpu-instr-2: Added shl,shr,sar,rol,ror,rcl&rcr tests (only intel data). bugref:10376

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 26.7 KB
 
1/* $Id: bs3-cpu-instr-2-gen.cpp 104000 2024-03-22 15:37:38Z vboxsync $ */
2/** @file
3 * BS3Kit - bs3-cpu-instr-2, Test Data Generator.
4 */
5
6/*
7 * Copyright (C) 2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.alldomusa.eu.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/assert.h>
42#include <iprt/asm.h>
43#include <iprt/asm-amd64-x86.h>
44#include <iprt/initterm.h>
45#include <iprt/message.h>
46#include <iprt/rand.h>
47#include <iprt/stream.h>
48#include <iprt/x86.h>
49#include "bs3-cpu-instr-2.h"
50
51
52/*********************************************************************************************************************************
53* External Functions *
54*********************************************************************************************************************************/
55#define PROTOTYPE_BINARY(a_Ins) \
56 DECLASM(uint32_t) RT_CONCAT(GenU8_,a_Ins)( uint8_t, uint8_t, uint32_t, uint8_t *); \
57 DECLASM(uint32_t) RT_CONCAT(GenU16_,a_Ins)(uint16_t, uint16_t, uint32_t, uint16_t *); \
58 DECLASM(uint32_t) RT_CONCAT(GenU32_,a_Ins)(uint32_t, uint32_t, uint32_t, uint32_t *); \
59 DECLASM(uint32_t) RT_CONCAT(GenU64_,a_Ins)(uint64_t, uint64_t, uint32_t, uint64_t *)
60
61PROTOTYPE_BINARY(and);
62PROTOTYPE_BINARY(or);
63PROTOTYPE_BINARY(xor);
64PROTOTYPE_BINARY(test);
65
66PROTOTYPE_BINARY(add);
67PROTOTYPE_BINARY(adc);
68PROTOTYPE_BINARY(sub);
69PROTOTYPE_BINARY(sbb);
70PROTOTYPE_BINARY(cmp);
71
72PROTOTYPE_BINARY(bt);
73PROTOTYPE_BINARY(btc);
74PROTOTYPE_BINARY(btr);
75PROTOTYPE_BINARY(bts);
76
77
78#define PROTOTYPE_SHIFT(a_Ins) \
79 DECLASM(uint32_t) RT_CONCAT(GenU8_,a_Ins)( uint8_t, uint8_t, uint32_t, uint8_t *); \
80 DECLASM(uint32_t) RT_CONCAT(GenU16_,a_Ins)(uint16_t, uint8_t, uint32_t, uint16_t *); \
81 DECLASM(uint32_t) RT_CONCAT(GenU32_,a_Ins)(uint32_t, uint8_t, uint32_t, uint32_t *); \
82 DECLASM(uint32_t) RT_CONCAT(GenU64_,a_Ins)(uint64_t, uint8_t, uint32_t, uint64_t *); \
83 DECLASM(uint32_t) RT_CONCAT3(GenU8_,a_Ins,_Ib)( uint8_t, uint8_t, uint32_t, uint8_t *); \
84 DECLASM(uint32_t) RT_CONCAT3(GenU16_,a_Ins,_Ib)(uint16_t, uint8_t, uint32_t, uint16_t *); \
85 DECLASM(uint32_t) RT_CONCAT3(GenU32_,a_Ins,_Ib)(uint32_t, uint8_t, uint32_t, uint32_t *); \
86 DECLASM(uint32_t) RT_CONCAT3(GenU64_,a_Ins,_Ib)(uint64_t, uint8_t, uint32_t, uint64_t *)
87
88PROTOTYPE_SHIFT(shl);
89PROTOTYPE_SHIFT(shr);
90PROTOTYPE_SHIFT(sar);
91PROTOTYPE_SHIFT(rol);
92PROTOTYPE_SHIFT(ror);
93PROTOTYPE_SHIFT(rcl);
94PROTOTYPE_SHIFT(rcr);
95
96
97static uint32_t RandEflStatus(void)
98{
99 return RTRandU32Ex(0, X86_EFL_STATUS_BITS) & X86_EFL_STATUS_BITS;
100}
101
102
103static uint8_t RandU8Shift(unsigned i, unsigned cTests, uint32_t *puTracker, unsigned cBits)
104{
105 uint8_t cShift = (uint8_t)RTRandU32Ex(0, 0xff);
106 if ((cShift % 11) != 0)
107 {
108 if ((cShift % 3) == 0)
109 cShift &= (cBits * 2) - 1;
110 else
111 cShift &= cBits - 1;
112 }
113
114 /* Make sure we've got the following counts: 0, 1, cBits, cBits + 1.
115 Note! Missing shift count 1 will cause the 'shl reg, 1' tests to spin forever. */
116 if (cShift == 0)
117 *puTracker |= RT_BIT_32(0);
118 else if (cShift == 1)
119 *puTracker |= RT_BIT_32(1);
120 else if (cShift == cBits)
121 *puTracker |= RT_BIT_32(2);
122 else if (cShift == cBits + 1)
123 *puTracker |= RT_BIT_32(3);
124 else if (*puTracker != 15 && i > cTests / 2)
125 {
126 if (!(*puTracker & RT_BIT_32(0)))
127 {
128 *puTracker |= RT_BIT_32(0);
129 cShift = 0;
130 }
131 else if (!(*puTracker & RT_BIT_32(1)))
132 {
133 *puTracker |= RT_BIT_32(1);
134 cShift = 1;
135 }
136 else if (!(*puTracker & RT_BIT_32(2)))
137 {
138 *puTracker |= RT_BIT_32(2);
139 cShift = cBits;
140 }
141 else if (!(*puTracker & RT_BIT_32(3)))
142 {
143 *puTracker |= RT_BIT_32(2);
144 cShift = cBits + 1;
145 }
146 else
147 RT_BREAKPOINT();
148 }
149
150 return cShift;
151}
152
153
154static uint8_t RandU8(unsigned i, unsigned iOp, unsigned iOuter = 0)
155{
156 RT_NOREF_PV(iOuter);
157 if (i == 0)
158 return 0;
159 if (i == 1)
160 return UINT8_MAX;
161 if (i == 2)
162 return iOp == 1 ? 0 : UINT8_MAX;
163 return (uint8_t)RTRandU32Ex(0, UINT8_MAX);
164}
165
166
167static uint16_t RandU16(unsigned i, unsigned iOp, unsigned iOuter = 0)
168{
169 Assert(iOuter <= 1);
170 if (i == 0)
171 return 0;
172 if (i == 1)
173 return UINT16_MAX;
174 if (i == 2)
175 return iOp == 1 ? 0 : UINT16_MAX;
176 if (iOuter == 1)
177 return (uint16_t)(int16_t)(int8_t)RandU8(i, iOp);
178 if ((i % 3) == 0)
179 return (uint16_t)RTRandU32Ex(0, UINT16_MAX >> RTRandU32Ex(1, 11));
180 return (uint16_t)RTRandU32Ex(0, UINT16_MAX);
181}
182
183
184static uint32_t RandU32(unsigned i, unsigned iOp, unsigned iOuter = 0)
185{
186 Assert(iOuter <= 1);
187 if (i == 0)
188 return 0;
189 if (i == 1)
190 return UINT32_MAX;
191 if (i == 2)
192 return iOp == 1 ? 0 : UINT32_MAX;
193 if (iOuter == 1)
194 return (uint32_t)(int32_t)(int8_t)RandU8(i, iOp);
195 if ((i % 3) == 0)
196 return RTRandU32Ex(0, UINT32_MAX >> RTRandU32Ex(1, 23));
197 return RTRandU32();
198}
199
200
201static uint64_t RandU64(unsigned i, unsigned iOp, unsigned iOuter = 0)
202{
203 if (iOuter != 0)
204 {
205 Assert(iOuter <= 2);
206 if (iOuter == 1)
207 return (uint64_t)(int64_t)(int8_t)RTRandU32Ex(0, UINT8_MAX);
208 if ((i % 2) != 0)
209 return (uint64_t)(int32_t)RTRandU32();
210 int32_t i32 = (int32_t)RTRandU32Ex(0, UINT32_MAX >> RTRandU32Ex(1, 23));
211 if (RTRandU32Ex(0, 1) & 1)
212 i32 = -i32;
213 return (uint64_t)(int64_t)i32;
214 }
215 if (i == 0)
216 return 0;
217 if (i == 1)
218 return UINT64_MAX;
219 if (i == 2)
220 return iOp == 1 ? 0 : UINT64_MAX;
221 if ((i % 3) == 0)
222 return RTRandU64Ex(0, UINT64_MAX >> RTRandU32Ex(1, 55));
223 return RTRandU64();
224}
225
226
227DECL_FORCE_INLINE(uint32_t)
228EnsureEflCoverage(unsigned iTest, unsigned cTests, unsigned cActiveEfls, uint32_t fActiveEfl,
229 uint32_t fSet, uint32_t fClear, uint32_t *pfMustBeClear)
230{
231 *pfMustBeClear = 0;
232 unsigned cLeft = cTests - iTest;
233 if (cLeft > cActiveEfls * 2)
234 return 0;
235
236 /* Find out which flag we're checking for now. */
237 unsigned iBit = ASMBitFirstSetU32(fActiveEfl) - 1;
238 while (cLeft >= 2)
239 {
240 cLeft -= 2;
241 fActiveEfl &= ~RT_BIT_32(iBit);
242 iBit = ASMBitFirstSetU32(fActiveEfl) - 1;
243 }
244
245 if (cLeft & 1)
246 {
247 if (!(fSet & RT_BIT_32(iBit)))
248 return RT_BIT_32(iBit);
249 }
250 else if (!(fClear & RT_BIT_32(iBit)))
251 *pfMustBeClear = RT_BIT_32(iBit);
252 return 0;
253}
254
255
256static void FileHeader(PRTSTREAM pOut, const char *pszFilename, const char *pszIncludeBlocker)
257{
258 RTStrmPrintf(pOut,
259 "// ##### BEGINFILE \"%s\"\n"
260 "/* $" "Id$ */\n"
261 "/** @file\n"
262 " * BS3Kit - bs3-cpu-instr-2, %s - auto generated (do not edit).\n"
263 " */\n"
264 "\n"
265 "/*\n"
266 " * Copyright (C) 2024 Oracle and/or its affiliates.\n"
267 " *\n"
268 " * This file is part of VirtualBox base platform packages, as\n"
269 " * available from https://www.alldomusa.eu.org.\n"
270 " *\n"
271 " * This program is free software; you can redistribute it and/or\n"
272 " * modify it under the terms of the GNU General Public License\n"
273 " * as published by the Free Software Foundation, in version 3 of the\n"
274 " * License.\n"
275 " *\n"
276 " * This program is distributed in the hope that it will be useful, but\n"
277 " * WITHOUT ANY WARRANTY; without even the implied warranty of\n"
278 " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
279 " * General Public License for more details.\n"
280 " *\n"
281 " * You should have received a copy of the GNU General Public License\n"
282 " * along with this program; if not, see <https://www.gnu.org/licenses>.\n"
283 " *\n"
284 " * The contents of this file may alternatively be used under the terms\n"
285 " * of the Common Development and Distribution License Version 1.0\n"
286 " * (CDDL), a copy of it is provided in the \"COPYING.CDDL\" file included\n"
287 " * in the VirtualBox distribution, in which case the provisions of the\n"
288 " * CDDL are applicable instead of those of the GPL.\n"
289 " *\n"
290 " * You may elect to license modified versions of this file under the\n"
291 " * terms and conditions of either the GPL or the CDDL or both.\n"
292 " *\n"
293 " * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0\n"
294 " */\n"
295 "\n"
296 , pszFilename, pszFilename);
297 if (!pszIncludeBlocker)
298 RTStrmPrintf(pOut,
299 "#include <bs3kit.h>\n"
300 "#include \"bs3-cpu-instr-2.h\"\n");
301 else
302 RTStrmPrintf(pOut,
303 "#ifndef %s\n"
304 "#define %s\n"
305 "#ifndef RT_WITHOUT_PRAGMA_ONCE\n"
306 "# pragma once\n"
307 "#endif\n",
308 pszIncludeBlocker, pszIncludeBlocker);
309}
310
311int main(int argc, char **argv)
312{
313 RTR3InitExe(argc, &argv, 0);
314
315 /*
316 * Constants.
317 */
318 enum { kEflBeaviour_Intel = 0, kEflBeaviour_Amd }
319 const enmEflBehaviour = ASMIsAmdCpu() || ASMIsHygonCpu() ? kEflBeaviour_Amd : kEflBeaviour_Intel;
320 static const char * const s_apszEflBehaviourTabNm[] = { "intel_", "amd_" };
321
322 /*
323 * Parse arguments.
324 */
325 PRTSTREAM pOut = g_pStdOut;
326 unsigned cTestsU8 = 32;
327 unsigned cTestsU16 = 32;
328 unsigned cTestsU32 = 36;
329 unsigned cTestsU64 = 48;
330
331 /** @todo */
332 if (argc != 1)
333 {
334 RTMsgSyntax("No arguments expected");
335 return RTEXITCODE_SYNTAX;
336 }
337
338
339 /*
340 * Generate the test data.
341 */
342 static struct
343 {
344 const char *pszName;
345 DECLCALLBACKMEMBER(uint32_t, pfnU8, ( uint8_t uSrc1, uint8_t uSrc2, uint32_t fCarry, uint8_t *puResult));
346 DECLCALLBACKMEMBER(uint32_t, pfnU16,(uint16_t uSrc1, uint16_t uSrc2, uint32_t fCarry, uint16_t *puResult));
347 DECLCALLBACKMEMBER(uint32_t, pfnU32,(uint32_t uSrc1, uint32_t uSrc2, uint32_t fCarry, uint32_t *puResult));
348 DECLCALLBACKMEMBER(uint32_t, pfnU64,(uint64_t uSrc1, uint64_t uSrc2, uint32_t fCarry, uint64_t *puResult));
349 uint8_t cActiveEfls;
350 uint16_t fActiveEfls;
351 bool fCarryIn;
352 bool fImmVars;
353 } const s_aBinary[] =
354 {
355 { "and", GenU8_and, GenU16_and, GenU32_and, GenU64_and, 3, X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF, false, true },
356 { "or", GenU8_or, GenU16_or, GenU32_or, GenU64_or, 3, X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF, false, true },
357 { "xor", GenU8_xor, GenU16_xor, GenU32_xor, GenU64_xor, 3, X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF, false, true },
358 { "test", GenU8_test, GenU16_test, GenU32_test, GenU64_test, 3, X86_EFL_PF | X86_EFL_ZF | X86_EFL_SF, false, true },
359
360 { "add", GenU8_add, GenU16_add, GenU32_add, GenU64_add, 6, X86_EFL_STATUS_BITS, false, true },
361 { "adc", GenU8_adc, GenU16_adc, GenU32_adc, GenU64_adc, 6, X86_EFL_STATUS_BITS, true, true },
362 { "sub", GenU8_sub, GenU16_sub, GenU32_sub, GenU64_sub, 6, X86_EFL_STATUS_BITS, false, true },
363 { "sbb", GenU8_sbb, GenU16_sbb, GenU32_sbb, GenU64_sbb, 6, X86_EFL_STATUS_BITS, true, true },
364 { "cmp", GenU8_cmp, GenU16_cmp, GenU32_cmp, GenU64_cmp, 6, X86_EFL_STATUS_BITS, false, true },
365
366 { "bt", NULL, GenU16_bt, GenU32_bt, GenU64_bt, 1, X86_EFL_CF, false, false },
367 { "btc", NULL, GenU16_btc, GenU32_btc, GenU64_btc, 1, X86_EFL_CF, false, false },
368 { "btr", NULL, GenU16_btr, GenU32_btr, GenU64_btr, 1, X86_EFL_CF, false, false },
369 { "bts", NULL, GenU16_bts, GenU32_bts, GenU64_bts, 1, X86_EFL_CF, false, false },
370 };
371
372 static struct
373 {
374 const char *pszName;
375 DECLCALLBACKMEMBER(uint32_t, pfnU8, ( uint8_t uSrc1, uint8_t uSrc2, uint32_t fCarry, uint8_t *puResult));
376 DECLCALLBACKMEMBER(uint32_t, pfnU16,(uint16_t uSrc1, uint8_t uSrc2, uint32_t fCarry, uint16_t *puResult));
377 DECLCALLBACKMEMBER(uint32_t, pfnU32,(uint32_t uSrc1, uint8_t uSrc2, uint32_t fCarry, uint32_t *puResult));
378 DECLCALLBACKMEMBER(uint32_t, pfnU64,(uint64_t uSrc1, uint8_t uSrc2, uint32_t fCarry, uint64_t *puResult));
379 DECLCALLBACKMEMBER(uint32_t, pfnU8Ib, ( uint8_t uSrc1, uint8_t uSrc2, uint32_t fCarry, uint8_t *puResult));
380 DECLCALLBACKMEMBER(uint32_t, pfnU16Ib,(uint16_t uSrc1, uint8_t uSrc2, uint32_t fCarry, uint16_t *puResult));
381 DECLCALLBACKMEMBER(uint32_t, pfnU32Ib,(uint32_t uSrc1, uint8_t uSrc2, uint32_t fCarry, uint32_t *puResult));
382 DECLCALLBACKMEMBER(uint32_t, pfnU64Ib,(uint64_t uSrc1, uint8_t uSrc2, uint32_t fCarry, uint64_t *puResult));
383 uint8_t cActiveEfls;
384 uint16_t fActiveEfls;
385 bool fCarryIn;
386 } const s_aShifters[] =
387 {
388 { "shl", GenU8_shl, GenU16_shl, GenU32_shl, GenU64_shl, GenU8_shl_Ib, GenU16_shl_Ib, GenU32_shl_Ib, GenU64_shl_Ib, 6, X86_EFL_STATUS_BITS, false },
389 { "shr", GenU8_shr, GenU16_shr, GenU32_shr, GenU64_shr, GenU8_shr_Ib, GenU16_shr_Ib, GenU32_shr_Ib, GenU64_shr_Ib, 6, X86_EFL_STATUS_BITS, false },
390 { "sar", GenU8_sar, GenU16_sar, GenU32_sar, GenU64_sar, GenU8_sar_Ib, GenU16_sar_Ib, GenU32_sar_Ib, GenU64_sar_Ib, 6, X86_EFL_STATUS_BITS, false },
391 { "rol", GenU8_rol, GenU16_rol, GenU32_rol, GenU64_rol, GenU8_rol_Ib, GenU16_rol_Ib, GenU32_rol_Ib, GenU64_rol_Ib, 2, X86_EFL_CF | X86_EFL_OF, false },
392 { "ror", GenU8_ror, GenU16_ror, GenU32_ror, GenU64_ror, GenU8_ror_Ib, GenU16_ror_Ib, GenU32_ror_Ib, GenU64_ror_Ib, 2, X86_EFL_CF | X86_EFL_OF, false },
393 { "rcl", GenU8_rcl, GenU16_rcl, GenU32_rcl, GenU64_rcl, GenU8_rcl_Ib, GenU16_rcl_Ib, GenU32_rcl_Ib, GenU64_rcl_Ib, 2, X86_EFL_CF | X86_EFL_OF, true },
394 { "rcr", GenU8_rcr, GenU16_rcr, GenU32_rcr, GenU64_rcr, GenU8_rcr_Ib, GenU16_rcr_Ib, GenU32_rcr_Ib, GenU64_rcr_Ib, 2, X86_EFL_CF | X86_EFL_OF, true },
395 };
396
397 RTStrmPrintf(pOut, "\n"); /* filesplitter requires this. */
398
399 /*
400 * Header:
401 */
402 FileHeader(pOut, "bs3-cpu-instr-2-data.h", "VBOX_INCLUDED_SRC_bootsectors_bs3_cpu_instr_2_data_h");
403#define DO_ONE_TYPE(a_Entry, a_pszExtraNm, a_szTypeBaseNm, a_cBits) do { \
404 RTStrmPrintf(pOut, \
405 "\n" \
406 "extern const uint16_t g_cBs3CpuInstr2_%s_%sTestDataU" #a_cBits ";\n" \
407 "extern const " a_szTypeBaseNm #a_cBits " g_aBs3CpuInstr2_%s_%sTestDataU" #a_cBits "[];\n", \
408 a_Entry.pszName, a_pszExtraNm, a_Entry.pszName, a_pszExtraNm); \
409 } while (0)
410 for (unsigned iInstr = 0; iInstr < RT_ELEMENTS(s_aBinary); iInstr++)
411 {
412 if (s_aBinary[iInstr].pfnU8)
413 DO_ONE_TYPE(s_aBinary[iInstr], "", "BS3CPUINSTR2BIN", 8);
414 if (s_aBinary[iInstr].pfnU16)
415 DO_ONE_TYPE(s_aBinary[iInstr], "", "BS3CPUINSTR2BIN", 16);
416 if (s_aBinary[iInstr].pfnU32)
417 DO_ONE_TYPE(s_aBinary[iInstr], "", "BS3CPUINSTR2BIN", 32);
418 if (s_aBinary[iInstr].pfnU64)
419 DO_ONE_TYPE(s_aBinary[iInstr], "", "BS3CPUINSTR2BIN", 64);
420 }
421
422 for (unsigned iInstr = 0; iInstr < RT_ELEMENTS(s_aShifters); iInstr++)
423 for (unsigned iEflBehaviour = 0; iEflBehaviour < RT_ELEMENTS(s_apszEflBehaviourTabNm); iEflBehaviour++)
424 {
425 DO_ONE_TYPE(s_aShifters[iInstr], s_apszEflBehaviourTabNm[iEflBehaviour], "BS3CPUINSTR2SHIFT", 8);
426 DO_ONE_TYPE(s_aShifters[iInstr], s_apszEflBehaviourTabNm[iEflBehaviour], "BS3CPUINSTR2SHIFT", 16);
427 DO_ONE_TYPE(s_aShifters[iInstr], s_apszEflBehaviourTabNm[iEflBehaviour], "BS3CPUINSTR2SHIFT", 32);
428 DO_ONE_TYPE(s_aShifters[iInstr], s_apszEflBehaviourTabNm[iEflBehaviour], "BS3CPUINSTR2SHIFT", 64);
429 }
430#undef DO_ONE_TYPE
431
432 RTStrmPrintf(pOut,
433 "\n"
434 "#endif /* !VBOX_INCLUDED_SRC_bootsectors_bs3_cpu_instr_2_data_h */\n"
435 "\n// ##### ENDFILE\n");
436
437#define DO_ONE_TYPE(a_Entry, a_pszExtraNm, a_szTypeBaseNm, a_ValueType, a_cBits, a_szFmt, a_pfnMember, a_cTests, a_fImmVars, a_fShift, a_pfnMemberIb) do { \
438 unsigned const cOuterLoops = 1 + a_fImmVars * (a_cBits == 64 ? 2 : a_cBits != 8 ? 1 : 0); \
439 unsigned const cTestFactor = !a_Entry.fCarryIn ? 1 : 2; \
440 RTStrmPrintf(pOut, \
441 "\n" \
442 "const uint16_t g_cBs3CpuInstr2_%s_%sTestDataU" #a_cBits " = %u;\n" \
443 "const " a_szTypeBaseNm #a_cBits " g_aBs3CpuInstr2_%s_%sTestDataU" #a_cBits "[%u] =\n" \
444 "{\n", \
445 a_Entry.pszName, a_pszExtraNm, a_cTests * cTestFactor * cOuterLoops, \
446 a_Entry.pszName, a_pszExtraNm, a_cTests * cTestFactor * cOuterLoops); \
447 for (unsigned iOuter = 0; iOuter < cOuterLoops; iOuter++) \
448 { \
449 if (iOuter != 0) \
450 RTStrmPrintf(pOut, " /* r/m" #a_cBits", imm%u: */\n", iOuter == 1 ? 8 : 32); \
451 uint32_t fSet = 0; \
452 uint32_t fClear = 0; \
453 uint32_t uShiftTracker = 0; \
454 for (unsigned iTest = 0; iTest < a_cTests; iTest++) \
455 { \
456 uint32_t fMustBeClear = 0; \
457 uint32_t fMustBeSet = EnsureEflCoverage(iTest, a_cTests, a_Entry.cActiveEfls, \
458 a_Entry.fActiveEfls, fSet, fClear, &fMustBeClear); \
459 for (unsigned iTry = 0;; iTry++) \
460 { \
461 a_ValueType const uSrc1 = RandU##a_cBits(iTest + iTry, 1); \
462 a_ValueType const uSrc2 = !(a_fShift) ? RandU##a_cBits(iTest + iTry, 2, iOuter) \
463 : RandU8Shift(iTest + iTry, a_cTests, &uShiftTracker, a_cBits); \
464 a_ValueType uResult = 0; \
465 uint32_t const fEflIn = !(a_fShift) ? 0 /*fCarry*/ : a_Entry.fCarryIn \
466 ? RandEflStatus() & ~(uint32_t)X86_EFL_CF : RandEflStatus(); \
467 uint32_t fEflOut = a_Entry.a_pfnMember(uSrc1, uSrc2, fEflIn, &uResult) \
468 & X86_EFL_STATUS_BITS; \
469 if (iTry < _1M && ((fEflOut & fMustBeClear) || (~fEflOut & fMustBeSet))) \
470 continue; \
471 fSet |= fEflOut; \
472 fClear |= ~fEflOut; \
473 if (!(a_fShift)) \
474 RTStrmPrintf(pOut, " { " a_szFmt ", " a_szFmt ", " a_szFmt ", %#05RX16 },\n", \
475 uSrc1, uSrc2, uResult, fEflOut); \
476 else \
477 { /* Seems that 'rol reg,Ib' (and possibly others) produces different OF results on intel. */ \
478 a_ValueType uResultIb = 0; \
479 uint32_t fEflOutIb = a_Entry.a_pfnMemberIb(uSrc1, uSrc2, fEflIn, &uResultIb) \
480 & X86_EFL_STATUS_BITS; \
481 if (uResultIb != uResult) RT_BREAKPOINT(); \
482 if ((fEflOutIb ^ fEflOut) & (X86_EFL_STATUS_BITS & ~X86_EFL_OF)) RT_BREAKPOINT(); \
483 if (fEflOutIb & X86_EFL_OF) fEflOut |= RT_BIT_32(BS3CPUINSTR2SHIFT_EFL_IB_OVERFLOW_OUT_BIT); \
484 RTStrmPrintf(pOut, " { " a_szFmt ", %#04RX8, %#05RX16, " a_szFmt ", %#05RX16 },%s\n", \
485 uSrc1, (uint8_t)uSrc2, (uint16_t)fEflIn, uResult, (uint16_t)fEflOut, \
486 (fEflOut ^ fEflOutIb) & X86_EFL_OF ? " /* OF/Ib */" : ""); \
487 } \
488 if (a_Entry.fCarryIn) \
489 { \
490 uResult = 0; \
491 fEflOut = a_Entry.a_pfnMember(uSrc1, uSrc2, fEflIn | X86_EFL_CF, &uResult) & X86_EFL_STATUS_BITS; \
492 fSet |= fEflOut; \
493 fClear |= ~fEflOut; \
494 if (!(a_fShift)) \
495 RTStrmPrintf(pOut, " { " a_szFmt ", " a_szFmt ", " a_szFmt ", %#05RX16 },\n", uSrc1, uSrc2, \
496 uResult, (uint16_t)(fEflOut | RT_BIT_32(BS3CPUINSTR2BIN_EFL_CARRY_IN_BIT))); \
497 else \
498 { /* Seems that 'rol reg,Ib' (and possibly others) produces different OF results on intel. */ \
499 a_ValueType uResultIb = 0; \
500 uint32_t fEflOutIb = a_Entry.a_pfnMemberIb(uSrc1, uSrc2, fEflIn | X86_EFL_CF, &uResultIb) \
501 & X86_EFL_STATUS_BITS; \
502 if (uResultIb != uResult) RT_BREAKPOINT(); \
503 if ((fEflOutIb ^ fEflOut) & (X86_EFL_STATUS_BITS & ~X86_EFL_OF)) RT_BREAKPOINT(); \
504 if (fEflOutIb & X86_EFL_OF) fEflOut |= RT_BIT_32(BS3CPUINSTR2SHIFT_EFL_IB_OVERFLOW_OUT_BIT); \
505 RTStrmPrintf(pOut, " { " a_szFmt ", %#04RX8, %#05RX16, " a_szFmt ", %#05RX16 },%s\n", \
506 uSrc1, (uint8_t)uSrc2, (uint16_t)(fEflIn | X86_EFL_CF), uResult, \
507 (uint16_t)fEflOut, (fEflOut ^ fEflOutIb) & X86_EFL_OF ? " /* OF/Ib */" : ""); \
508 } \
509 } \
510 break; \
511 } \
512 } \
513 } \
514 RTStrmPrintf(pOut, \
515 "};\n"); \
516 } while (0)
517
518 /*
519 * Source: 8, 16 & 32 bit data.
520 */
521 FileHeader(pOut, "bs3-cpu-instr-2-data16.c16", NULL);
522 for (unsigned iInstr = 0; iInstr < RT_ELEMENTS(s_aBinary); iInstr++)
523 {
524 if (s_aBinary[iInstr].pfnU8)
525 DO_ONE_TYPE(s_aBinary[iInstr], "", "BS3CPUINSTR2BIN", uint8_t, 8, "%#04RX8", pfnU8, cTestsU8, s_aBinary[iInstr].fImmVars, 0, pfnU8);
526 if (s_aBinary[iInstr].pfnU16)
527 DO_ONE_TYPE(s_aBinary[iInstr], "", "BS3CPUINSTR2BIN", uint16_t, 16, "%#06RX16", pfnU16, cTestsU16, s_aBinary[iInstr].fImmVars, 0, pfnU16);
528 if (s_aBinary[iInstr].pfnU32)
529 DO_ONE_TYPE(s_aBinary[iInstr], "", "BS3CPUINSTR2BIN", uint32_t, 32, "%#010RX32", pfnU32, cTestsU32, s_aBinary[iInstr].fImmVars, 0, pfnU32);
530 }
531 RTStrmPrintf(pOut, "\n// ##### ENDFILE\n");
532
533 /*
534 * Source: 64 bit data (goes in different data segment).
535 */
536 FileHeader(pOut, "bs3-cpu-instr-2-data64.c64", NULL);
537 for (unsigned iInstr = 0; iInstr < RT_ELEMENTS(s_aBinary); iInstr++)
538 if (s_aBinary[iInstr].pfnU64)
539 DO_ONE_TYPE(s_aBinary[iInstr], "", "BS3CPUINSTR2BIN", uint64_t, 64, "%#018RX64", pfnU64, cTestsU64, s_aBinary[iInstr].fImmVars, 0, pfnU64);
540 RTStrmPrintf(pOut, "\n// ##### ENDFILE\n");
541
542
543 /*
544 * Source: 8, 16 & 32 bit data for the host CPU.
545 */
546 const char * const pszEflTabNm = s_apszEflBehaviourTabNm[enmEflBehaviour];
547 FileHeader(pOut, enmEflBehaviour == kEflBeaviour_Amd ? "bs3-cpu-instr-2-data16-amd.c16" : "bs3-cpu-instr-2-data16-intel.c16", NULL);
548 for (unsigned iInstr = 0; iInstr < RT_ELEMENTS(s_aShifters); iInstr++)
549 {
550 DO_ONE_TYPE(s_aShifters[iInstr], pszEflTabNm, "BS3CPUINSTR2SHIFT", uint8_t, 8, "%#04RX8", pfnU8, cTestsU8, 0, 1, pfnU8Ib);
551 DO_ONE_TYPE(s_aShifters[iInstr], pszEflTabNm, "BS3CPUINSTR2SHIFT", uint16_t, 16, "%#06RX16", pfnU16, cTestsU16, 0, 1, pfnU16Ib);
552 DO_ONE_TYPE(s_aShifters[iInstr], pszEflTabNm, "BS3CPUINSTR2SHIFT", uint32_t, 32, "%#010RX32", pfnU32, cTestsU32, 0, 1, pfnU32Ib);
553 }
554 RTStrmPrintf(pOut, "\n// ##### ENDFILE\n");
555
556 /*
557 * Source: 64 bit data for the host CPU (goes in different data segment).
558 */
559 FileHeader(pOut, enmEflBehaviour == kEflBeaviour_Amd ? "bs3-cpu-instr-2-data64-amd.c64" : "bs3-cpu-instr-2-data64-intel.c64", NULL);
560 for (unsigned iInstr = 0; iInstr < RT_ELEMENTS(s_aShifters); iInstr++)
561 DO_ONE_TYPE(s_aShifters[iInstr], pszEflTabNm, "BS3CPUINSTR2SHIFT", uint64_t, 64, "%#018RX64", pfnU64, cTestsU64, 0, 1, pfnU64Ib);
562 RTStrmPrintf(pOut, "\n// ##### ENDFILE\n");
563
564#undef DO_ONE_TYPE
565
566 return 0;
567}
568
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette