VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-data.py@ 94714

Last change on this file since 94714 was 94130, checked in by vboxsync, 3 years ago

ValKit/bs3kit: pylint 2.9.6 adjustments (mostly about using 'with' statements).

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 24.1 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: bs3-cpu-generated-1-data.py 94130 2022-03-08 14:57:49Z vboxsync $
4# pylint: disable=invalid-name
5
6"""
7Generates testcases from @optest specifications in IEM.
8"""
9
10from __future__ import print_function;
11
12__copyright__ = \
13"""
14Copyright (C) 2017-2022 Oracle Corporation
15
16This file is part of VirtualBox Open Source Edition (OSE), as
17available from http://www.virtualbox.org. This file is free software;
18you can redistribute it and/or modify it under the terms of the GNU
19General Public License (GPL) as published by the Free Software
20Foundation, in version 2 as it comes in the "COPYING" file of the
21VirtualBox OSE distribution. VirtualBox OSE is distributed in the
22hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
23
24The contents of this file may alternatively be used under the terms
25of the Common Development and Distribution License Version 1.0
26(CDDL) only, as it comes in the "COPYING.CDDL" file of the
27VirtualBox OSE distribution, in which case the provisions of the
28CDDL are applicable instead of those of the GPL.
29
30You may elect to license modified versions of this file under the
31terms and conditions of either the GPL or the CDDL or both.
32"""
33__version__ = "$Revision: 94130 $"
34
35# Standard python imports.
36import os;
37import sys;
38
39# Only the main script needs to modify the path.
40g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)));
41g_ksVmmAllDir = os.path.join(os.path.dirname(g_ksValidationKitDir), 'VMM', 'VMMAll')
42sys.path.append(g_ksVmmAllDir);
43
44import IEMAllInstructionsPython as iai; # pylint: disable=import-error
45
46
47# Python 3 hacks:
48if sys.version_info[0] >= 3:
49 long = int; # pylint: disable=redefined-builtin,invalid-name
50
51
52class Bs3Cg1TestEncoder(object):
53 """
54 Does the encoding of a single test.
55 """
56
57 def __init__(self, fLast):
58 self.fLast = fLast;
59 # Each list member (in all lists) are C expression of a byte.
60 self.asHdr = [];
61 self.asSelectors = [];
62 self.asInputs = [];
63 self.asOutputs = [];
64
65 @staticmethod
66 def _compileSelectors(aoSelectors): # (list(iai.TestSelector)) -> list(str)
67 """
68 Compiles a list of iai.TestSelector predicate checks.
69 Returns C byte expression strings.
70 """
71 asRet = [];
72 for oSelector in aoSelectors:
73 sConstant = oSelector.kdVariables[oSelector.sVariable][oSelector.sValue];
74 sConstant = sConstant.upper().replace('.', '_');
75 if oSelector.sOp == '==':
76 sByte = '(BS3CG1PRED_%s << BS3CG1SEL_OP_PRED_SHIFT) | BS3CG1SEL_OP_IS_TRUE' % (sConstant,);
77 elif oSelector.sOp == '!=':
78 sByte = '(BS3CG1PRED_%s << BS3CG1SEL_OP_PRED_SHIFT) | BS3CG1SEL_OP_IS_FALSE' % (sConstant,);
79 else:
80 raise Exception('Unknown selector operator: %s' % (oSelector.sOp,));
81 asRet.append(sByte);
82 return asRet;
83
84 kdSmallFields = {
85 'op1': 'BS3CG1_CTXOP_OP1',
86 'op2': 'BS3CG1_CTXOP_OP2',
87 'efl': 'BS3CG1_CTXOP_EFL',
88 };
89 kdOperators = {
90 '=': 'BS3CG1_CTXOP_ASSIGN',
91 '|=': 'BS3CG1_CTXOP_OR',
92 '&=': 'BS3CG1_CTXOP_AND',
93 '&~=': 'BS3CG1_CTXOP_AND_INV',
94 };
95 kdSmallSizes = {
96 1: 'BS3CG1_CTXOP_1_BYTE',
97 2: 'BS3CG1_CTXOP_2_BYTES',
98 4: 'BS3CG1_CTXOP_4_BYTES',
99 8: 'BS3CG1_CTXOP_8_BYTES',
100 16: 'BS3CG1_CTXOP_16_BYTES',
101 32: 'BS3CG1_CTXOP_32_BYTES',
102 12: 'BS3CG1_CTXOP_12_BYTES',
103 };
104
105 @staticmethod
106 def _amendOutputs(aoOutputs, oInstr): # type: (list(iai.TestInOut), iai.Instruction) -> list(iai.TestInOut)
107 """
108 Amends aoOutputs for instructions with special flag behaviour (undefined,
109 always set, always clear).
110
111 Undefined flags are copied from the result context as the very first
112 operation so they can be set to CPU vendor specific values later if
113 desired.
114
115 Always set or cleared flags are applied at the very end of the
116 modification operations so that we spot incorrect specifications.
117 """
118 if oInstr.asFlUndefined or oInstr.asFlClear or oInstr.asFlSet:
119 aoOutputs = list(aoOutputs);
120
121 if oInstr.asFlUndefined:
122 fFlags = oInstr.getUndefinedFlagsMask();
123 assert fFlags != 0;
124 aoOutputs.insert(0, iai.TestInOut('efl_undef', '=', str(fFlags), 'uint'));
125
126 if oInstr.asFlClear:
127 fFlags = oInstr.getClearedFlagsMask();
128 assert fFlags != 0;
129 aoOutputs.append(iai.TestInOut('efl', '&~=', str(fFlags), 'uint'));
130
131 if oInstr.asFlSet:
132 fFlags = oInstr.getSetFlagsMask();
133 assert fFlags != 0;
134 aoOutputs.append(iai.TestInOut('efl', '|=', str(fFlags), 'uint'));
135
136 return aoOutputs;
137
138 @staticmethod
139 def _compileContextModifers(aoOperations): # (list(iai.TestInOut))
140 """
141 Compile a list of iai.TestInOut context modifiers.
142 """
143 asRet = [];
144 for oOperation in aoOperations:
145 oType = iai.TestInOut.kdTypes[oOperation.sType];
146 aaoValues = oType.get(oOperation.sValue);
147 assert len(aaoValues) == 1 or len(aaoValues) == 2;
148
149 sOp = oOperation.sOp;
150 if sOp == '&|=':
151 sOp = '|=' if len(aaoValues) == 1 else '&~=';
152
153 for fSignExtend, abValue in aaoValues:
154 cbValue = len(abValue);
155
156 # The opcode byte.
157 sOpcode = Bs3Cg1TestEncoder.kdOperators[sOp];
158 sOpcode += ' | ';
159 if oOperation.sField in Bs3Cg1TestEncoder.kdSmallFields:
160 sOpcode += Bs3Cg1TestEncoder.kdSmallFields[oOperation.sField];
161 else:
162 sOpcode += 'BS3CG1_CTXOP_DST_ESC';
163 sOpcode += ' | ';
164 if cbValue in Bs3Cg1TestEncoder.kdSmallSizes:
165 sOpcode += Bs3Cg1TestEncoder.kdSmallSizes[cbValue];
166 else:
167 sOpcode += 'BS3CG1_CTXOP_SIZE_ESC';
168 if fSignExtend:
169 sOpcode += ' | BS3CG1_CTXOP_SIGN_EXT';
170 asRet.append(sOpcode);
171
172 # Escaped field identifier.
173 if oOperation.sField not in Bs3Cg1TestEncoder.kdSmallFields:
174 asRet.append('BS3CG1DST_%s' % (oOperation.sField.upper().replace('.', '_'),));
175
176 # Escaped size byte?
177 if cbValue not in Bs3Cg1TestEncoder.kdSmallSizes:
178 if cbValue >= 256 or cbValue not in [ 1, 2, 4, 6, 8, 12, 16, 32, 64, 128, ]:
179 raise Exception('Invalid value size: %s' % (cbValue,));
180 asRet.append('0x%02x' % (cbValue,));
181
182 # The value bytes.
183 for b in abValue:
184 asRet.append('0x%02x' % (b,));
185
186 sOp = '|=';
187
188 return asRet;
189
190 def _constructHeader(self):
191 """
192 Returns C byte expression strings for BS3CG1TESTHDR.
193 """
194 cbSelectors = len(self.asSelectors);
195 if cbSelectors >= 256:
196 raise Exception('Too many selectors: %s bytes, max 255 bytes' % (cbSelectors,))
197
198 cbInputs = len(self.asInputs);
199 if cbInputs >= 4096:
200 raise Exception('Too many input context modifiers: %s bytes, max 4095 bytes' % (cbInputs,))
201
202 cbOutputs = len(self.asOutputs);
203 if cbOutputs >= 2048:
204 raise Exception('Too many output context modifiers: %s bytes, max 2047 bytes' % (cbOutputs,))
205
206 return [
207 '%#04x' % (cbSelectors,), # 8-bit
208 '%#05x & 0xff' % (cbInputs,), # first 8 bits of cbInputs
209 '(%#05x >> 8) | ((%#05x & 0xf) << 4)' % (cbInputs, cbOutputs,), # last 4 bits of cbInputs, lower 4 bits of cbOutputs.
210 '(%#05x >> 4) | (%#05x << 7)' % (cbOutputs, self.fLast), # last 7 bits of cbOutputs and 1 bit fLast.
211 ];
212
213 def encodeTest(self, oTest): # type: (iai.InstructionTest)
214 """
215 Does the encoding.
216 """
217 self.asSelectors = self._compileSelectors(oTest.aoSelectors);
218 self.asInputs = self._compileContextModifers(oTest.aoInputs);
219 self.asOutputs = self._compileContextModifers(self._amendOutputs(oTest.aoOutputs, oTest.oInstr));
220 self.asHdr = self._constructHeader();
221
222
223class Bs3Cg1EncodedTests(object):
224 """
225 Encodes the tests for an instruction.
226 """
227
228 def __init__(self, oInstr):
229 self.offTests = -1;
230 self.cbTests = 0;
231 self.asLines = [] # type: list(str)
232 self.aoInstructions = [] # type: list(iai.Instruction)
233
234 # Encode the tests.
235 for iTest, oTest in enumerate(oInstr.aoTests):
236 oEncodedTest = Bs3Cg1TestEncoder(iTest + 1 == len(oInstr.aoTests));
237 oEncodedTest.encodeTest(oTest);
238
239 self.cbTests += len(oEncodedTest.asHdr) + len(oEncodedTest.asSelectors) \
240 + len(oEncodedTest.asInputs) + len(oEncodedTest.asOutputs);
241
242 self.asLines.append(' /* test #%s: %s */' % (iTest, oTest,));
243 self.asLines += self.bytesToLines(' ', oEncodedTest.asHdr);
244 if oEncodedTest.asSelectors:
245 self.asLines += self.bytesToLines(' /*sel:*/ ', oEncodedTest.asSelectors);
246 if oEncodedTest.asInputs:
247 self.asLines += self.bytesToLines(' /* in:*/ ', oEncodedTest.asInputs);
248 if oEncodedTest.asOutputs:
249 self.asLines += self.bytesToLines(' /*out:*/ ', oEncodedTest.asOutputs);
250
251 @staticmethod
252 def bytesToLines(sPrefix, asBytes):
253 """
254 Formats a series of bytes into one or more lines.
255 A byte ending with a newline indicates that we should start a new line,
256 and prefix it by len(sPrefix) spaces.
257
258 Returns list of lines.
259 """
260 asRet = [];
261 sLine = sPrefix;
262 for sByte in asBytes:
263 if sByte[-1] == '\n':
264 sLine += sByte[:-1] + ',';
265 asRet.append(sLine);
266 sLine = ' ' * len(sPrefix);
267 else:
268 if len(sLine) + 2 + len(sByte) > 132 and len(sLine) > len(sPrefix):
269 asRet.append(sLine[:-1]);
270 sLine = ' ' * len(sPrefix);
271 sLine += sByte + ', ';
272
273
274 if len(sLine) > len(sPrefix):
275 asRet.append(sLine);
276 return asRet;
277
278
279 def isEqual(self, oOther):
280 """ Compares two encoded tests. """
281 if self.cbTests != oOther.cbTests:
282 return False;
283 if len(self.asLines) != len(oOther.asLines):
284 return False;
285 for iLine, sLines in enumerate(self.asLines):
286 if sLines != oOther.asLines[iLine]:
287 return False;
288 return True;
289
290
291
292class Bs3Cg1Instruction(object):
293 """
294 An instruction with tests.
295 """
296
297 def __init__(self, oMap, oInstr, oTests):
298 self.oMap = oMap # type: iai.InstructionMap
299 self.oInstr = oInstr # type: iai.Instruction
300 self.oTests = oTests # type: Bs3Cg1EncodedTests
301
302 self.asOpcodes = oMap.asLeadOpcodes + [ '0x%02x' % (oInstr.getOpcodeByte(),) ];
303 self.sEncoding = iai.g_kdEncodings[oInstr.sEncoding][0];
304
305 for oOp in oInstr.aoOperands:
306 self.sEncoding += '_' + oOp.sType;
307 if oInstr.sSubOpcode and iai.g_kdSubOpcodes[oInstr.sSubOpcode][1]:
308 self.sEncoding += '_' + iai.g_kdSubOpcodes[oInstr.sSubOpcode][1];
309
310 if oInstr.fUnused:
311 if oInstr.sInvalidStyle == 'immediate' and oInstr.sSubOpcode:
312 self.sEncoding += '_MOD_EQ_3' if oInstr.sSubOpcode == '11 mr/reg' else '_MOD_NE_3';
313 elif oInstr.sInvalidStyle == 'intel-modrm':
314 if oInstr.sSubOpcode is None:
315 self.sEncoding = 'BS3CG1ENC_MODRM_Gv_Ev';
316 elif oInstr.sSubOpcode == '11 mr/reg':
317 self.sEncoding = 'BS3CG1ENC_MODRM_MOD_EQ_3';
318 elif oInstr.sSubOpcode == '!11 mr/reg':
319 self.sEncoding = 'BS3CG1ENC_MODRM_MOD_NE_3';
320 else:
321 raise Exception('Unhandled sSubOpcode=%s for sInvalidStyle=%s' % (oInstr.sSubOpcode, oInstr.sInvalidStyle));
322 elif oInstr.sInvalidStyle == 'vex.modrm':
323 self.sEncoding = 'BS3CG1ENC_VEX_MODRM';
324
325 self.asFlags = [];
326 if 'invalid_64' in oInstr.dHints:
327 self.asFlags.append('BS3CG1INSTR_F_INVALID_64BIT');
328 if oInstr.fUnused:
329 self.asFlags.append('BS3CG1INSTR_F_UNUSED');
330 elif oInstr.fInvalid:
331 self.asFlags.append('BS3CG1INSTR_F_INVALID');
332 if oInstr.sInvalidStyle and oInstr.sInvalidStyle.startswith('intel-'):
333 self.asFlags.append('BS3CG1INSTR_F_INTEL_DECODES_INVALID');
334 if 'vex_l_zero' in oInstr.dHints:
335 self.asFlags.append('BS3CG1INSTR_F_VEX_L_ZERO');
336 if 'vex_l_ignored' in oInstr.dHints:
337 self.asFlags.append('BS3CG1INSTR_F_VEX_L_IGNORED');
338
339 self.fAdvanceMnemonic = True; ##< Set by the caller.
340 if oInstr.sPrefix:
341 if oInstr.sPrefix == 'none':
342 self.sPfxKind = 'BS3CG1PFXKIND_NO_F2_F3_66';
343 else:
344 self.sPfxKind = 'BS3CG1PFXKIND_REQ_' + oInstr.sPrefix[-2:].upper();
345 elif oInstr.sEncoding == 'ModR/M':
346 if 'ignores_op_size' not in oInstr.dHints:
347 self.sPfxKind = 'BS3CG1PFXKIND_MODRM';
348 else:
349 self.sPfxKind = 'BS3CG1PFXKIND_MODRM_NO_OP_SIZES';
350 else:
351 self.sPfxKind = '0';
352
353 self.sCpu = 'BS3CG1CPU_';
354 assert len(oInstr.asCpuIds) in [0, 1], str(oInstr);
355 if oInstr.asCpuIds:
356 self.sCpu += oInstr.asCpuIds[0].upper().replace('.', '_');
357 elif oInstr.sMinCpu:
358 self.sCpu += 'GE_' + oInstr.sMinCpu;
359 else:
360 self.sCpu += 'ANY';
361
362 if oInstr.sXcptType:
363 self.sXcptType = 'BS3CG1XCPTTYPE_' + oInstr.sXcptType.upper();
364 else:
365 self.sXcptType = 'BS3CG1XCPTTYPE_NONE';
366
367 def getOperands(self):
368 """ Returns comma separated string of operand values for g_abBs3Cg1Operands. """
369 return ', '.join(['(uint8_t)BS3CG1OP_%s' % (oOp.sType,) for oOp in self.oInstr.aoOperands]);
370
371 def getOpcodeMap(self):
372 """ Returns the opcode map number for the BS3CG1INSTR structure. """
373 sEncoding = self.oInstr.aoMaps[0].sEncoding;
374 if sEncoding == 'legacy': return 0;
375 if sEncoding == 'vex1': return 1;
376 if sEncoding == 'vex2': return 2;
377 if sEncoding == 'vex3': return 3;
378 if sEncoding == 'xop8': return 8;
379 if sEncoding == 'xop9': return 9;
380 if sEncoding == 'xop10': return 10;
381 assert False, sEncoding;
382 return 3;
383
384 def getInstructionEntry(self):
385 """ Returns an array of BS3CG1INSTR member initializers. """
386 assert len(self.oInstr.sMnemonic) < 16;
387 sOperands = ', '.join([oOp.sType for oOp in self.oInstr.aoOperands]);
388 if sOperands:
389 sOperands = ' /* ' + sOperands + ' */';
390 return [
391 ' /* cbOpcodes = */ %s, /* %s */' % (len(self.asOpcodes), ' '.join(self.asOpcodes),),
392 ' /* cOperands = */ %s,%s' % (len(self.oInstr.aoOperands), sOperands,),
393 ' /* cchMnemonic = */ %s, /* %s */' % (len(self.oInstr.sMnemonic), self.oInstr.sMnemonic,),
394 ' /* fAdvanceMnemonic = */ %s,' % ('true' if self.fAdvanceMnemonic else 'false',),
395 ' /* offTests = */ %s,' % (self.oTests.offTests,),
396 ' /* enmEncoding = */ (unsigned)%s,' % (self.sEncoding,),
397 ' /* uOpcodeMap = */ (unsigned)%s,' % (self.getOpcodeMap(),),
398 ' /* enmPrefixKind = */ (unsigned)%s,' % (self.sPfxKind,),
399 ' /* enmCpuTest = */ (unsigned)%s,' % (self.sCpu,),
400 ' /* enmXcptType = */ (unsigned)%s,' % (self.sXcptType,),
401 ' /* uUnused = */ 0,',
402 ' /* fFlags = */ %s' % (' | '.join(self.asFlags) if self.asFlags else '0'),
403 ];
404
405
406class Bs3CpuGenerated1Generator(object):
407 """
408 The generator code for bs3-cpu-generated-1.
409 """
410
411 def __init__(self):
412 self.aoInstructions = [] # type: Bs3Cg1Instruction
413 self.aoTests = [] # type: Bs3Cg1EncodedTests
414 self.cbTests = 0;
415
416 def addTests(self, oTests, oInstr): # type: (Bs3Cg1EncodedTests, iai.Instruction) -> Bs3Cg1EncodedTests
417 """
418 Adds oTests to self.aoTests, setting the oTests.offTests member.
419 Checks for and eliminates duplicates.
420 Returns the tests to use.
421 """
422 # Check for duplicates.
423 for oExisting in self.aoTests:
424 if oTests.isEqual(oExisting):
425 oExisting.aoInstructions.append(oInstr);
426 return oExisting;
427
428 # New test, so add it.
429 oTests.offTests = self.cbTests;
430 self.aoTests.append(oTests);
431 self.cbTests += oTests.cbTests;
432
433 assert not oTests.aoInstructions;
434 oTests.aoInstructions.append(oInstr);
435
436 return oTests;
437
438 def processInstruction(self):
439 """
440 Processes the IEM specified instructions.
441 Returns success indicator.
442 """
443
444 #
445 # Group instructions by mnemonic to reduce the number of sub-tests.
446 #
447 for oInstr in sorted(iai.g_aoAllInstructions,
448 key = lambda oInstr: oInstr.sMnemonic + ''.join([oOp.sType for oOp in oInstr.aoOperands])
449 + (oInstr.sOpcode if oInstr.sOpcode else 'zz')):
450 if oInstr.aoTests:
451 oTests = Bs3Cg1EncodedTests(oInstr);
452 oTests = self.addTests(oTests, oInstr);
453
454 for oMap in oInstr.aoMaps:
455 self.aoInstructions.append(Bs3Cg1Instruction(oMap, oInstr, oTests));
456
457 # Set fAdvanceMnemonic.
458 for iInstr, oInstr in enumerate(self.aoInstructions):
459 oInstr.fAdvanceMnemonic = iInstr + 1 >= len(self.aoInstructions) \
460 or oInstr.oInstr.sMnemonic != self.aoInstructions[iInstr + 1].oInstr.sMnemonic;
461
462 return True;
463
464 def generateCode(self, oOut):
465 """
466 Generates the C code.
467 Returns success indicator.
468 """
469
470 # First, a file header.
471 asLines = [
472 '/*',
473 ' * Autogenerated by $Id: bs3-cpu-generated-1-data.py 94130 2022-03-08 14:57:49Z vboxsync $ ',
474 ' * Do not edit!',
475 ' */',
476 '',
477 '/*',
478 ' * Copyright (C) 2017-2020 Oracle Corporation',
479 ' *',
480 ' * This file is part of VirtualBox Open Source Edition (OSE), as',
481 ' * available from http://www.virtualbox.org. This file is free software;',
482 ' * you can redistribute it and/or modify it under the terms of the GNU',
483 ' * General Public License (GPL) as published by the Free Software',
484 ' * Foundation, in version 2 as it comes in the "COPYING" file of the',
485 ' * VirtualBox OSE distribution. VirtualBox OSE is distributed in the',
486 ' * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.',
487 ' * ',
488 ' * The contents of this file may alternatively be used under the terms',
489 ' * of the Common Development and Distribution License Version 1.0',
490 ' * (CDDL) only, as it comes in the "COPYING.CDDL" file of the',
491 ' * VirtualBox OSE distribution, in which case the provisions of the',
492 ' * CDDL are applicable instead of those of the GPL.',
493 ' * ',
494 ' * You may elect to license modified versions of this file under the',
495 ' * terms and conditions of either the GPL or the CDDL or both.',
496 ' */',
497 '',
498 '',
499 '#include "bs3-cpu-generated-1.h"',
500 '',
501 '',
502 '#pragma data_seg ("BS3DATA16")',
503 ];
504
505 # Generate the g_achBs3Cg1Mnemonics array.
506 asLines += [
507 'const char BS3_FAR_DATA g_achBs3Cg1Mnemonics[] = ',
508 '{',
509 ];
510 fAdvanceMnemonic = True;
511 for oInstr in self.aoInstructions:
512 if fAdvanceMnemonic:
513 asLines.append(' \"%s\"' % (oInstr.oInstr.sMnemonic,));
514 fAdvanceMnemonic = oInstr.fAdvanceMnemonic;
515 asLines += [
516 '};',
517 '',
518 '',
519 ];
520
521 # Generate the g_abBs3Cg1Opcodes array.
522 asLines += [
523 'const uint8_t BS3_FAR_DATA g_abBs3Cg1Opcodes[] = ',
524 '{',
525 ];
526 for oInstr in self.aoInstructions:
527 asLines.append(' ' + ', '.join(oInstr.asOpcodes) + ',');
528 asLines += [
529 '};',
530 '',
531 '',
532 ];
533
534 # Generate the g_abBs3Cg1Opcodes array.
535 asLines += [
536 'const uint8_t BS3_FAR_DATA g_abBs3Cg1Operands[] = ',
537 '{',
538 ];
539 cOperands = 0;
540 for oInstr in self.aoInstructions:
541 if oInstr.oInstr.aoOperands:
542 cOperands += len(oInstr.oInstr.aoOperands);
543 asLines.append(' ' + oInstr.getOperands() + ', /* %s */' % (oInstr.oInstr.sStats,));
544 else:
545 asLines.append(' /* none */');
546 if not cOperands:
547 asLines.append(' 0 /* dummy */');
548 asLines += [
549 '};',
550 '',
551 '',
552 ];
553
554 # Generate the g_abBs3Cg1Operands array.
555 asLines += [
556 'const BS3CG1INSTR BS3_FAR_DATA g_aBs3Cg1Instructions[] = ',
557 '{',
558 ];
559 for oInstr in self.aoInstructions:
560 asLines.append(' {');
561 asLines += oInstr.getInstructionEntry();
562 asLines.append(' },');
563 asLines += [
564 '};',
565 'const uint16_t BS3_FAR_DATA g_cBs3Cg1Instructions = RT_ELEMENTS(g_aBs3Cg1Instructions);',
566 '',
567 '',
568 ];
569
570 # Generate the g_abBs3Cg1Tests array.
571 asLines += [
572 'const uint8_t BS3_FAR_DATA g_abBs3Cg1Tests[] = ',
573 '{',
574 ];
575 for oTests in self.aoTests:
576 asLines.append(' /*');
577 asLines.append(' * offTests=%s' % (oTests.offTests,));
578 asLines.append(' * Instructions: %s' % (', '.join([oInstr.sStats for oInstr in oTests.aoInstructions]),));
579 asLines.append(' */');
580 asLines += oTests.asLines;
581 asLines += [
582 '};',
583 '',
584 ];
585
586
587 #/** The test data that BS3CG1INSTR.
588 # * In order to simplify generating these, we use a byte array. */
589 #extern const uint8_t BS3_FAR_DATA g_abBs3Cg1Tests[];
590
591
592 oOut.write('\n'.join(asLines));
593 return True;
594
595
596 def usage(self):
597 """ Prints usage. """
598 print('usage: bs3-cpu-generated-1-data.py [output file|-]');
599 return 0;
600
601 def main(self, asArgs):
602 """
603 C-like main function.
604 Returns exit code.
605 """
606
607 #
608 # Quick argument parsing.
609 #
610 if len(asArgs) == 1:
611 sOutFile = '-';
612 elif len(asArgs) != 2:
613 print('syntax error! Expected exactly one argument.');
614 return 2;
615 elif asArgs[1] in [ '-h', '-?', '--help' ]:
616 return self.usage();
617 else:
618 sOutFile = asArgs[1];
619
620 #
621 # Process the instructions specified in the IEM sources.
622 #
623 if self.processInstruction():
624
625 #
626 # Open the output file and generate the code.
627 #
628 if sOutFile == '-':
629 oOut = sys.stdout;
630 else:
631 try:
632 oOut = open(sOutFile, 'w'); # pylint: disable=consider-using-with
633 except Exception as oXcpt:
634 print('error! Failed open "%s" for writing: %s' % (sOutFile, oXcpt,));
635 return 1;
636 if self.generateCode(oOut):
637 return 0;
638
639 return 1;
640
641
642if __name__ == '__main__':
643 sys.exit(Bs3CpuGenerated1Generator().main(sys.argv));
644
Note: See TracBrowser for help on using the repository browser.

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