VirtualBox

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

Last change on this file since 98103 was 98103, checked in by vboxsync, 22 months ago

Copyright year updates by scm.

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