VirtualBox

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

Last change on this file since 103068 was 100733, checked in by vboxsync, 17 months ago

VMM/IEM,ValKit: Shortened the IEMAllInstruction* file names to IEMAllInst*. This makes it easier to see the distinguishing bits of the name in the narrow buffer list widget here (this has been driving me nuts for months). Sorry for any conflicts this causes. bugref:10369

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