VirtualBox

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

Last change on this file since 96407 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 24.4 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: bs3-cpu-generated-1-data.py 96407 2022-08-22 17:43:14Z 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 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: 96407 $"
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 96407 2022-08-22 17:43:14Z vboxsync $ ',
484 ' * Do not edit!',
485 ' */',
486 '',
487 '/*',
488 ' * Copyright (C) 2017-2020 Oracle Corporation',
489 ' *',
490 ' * This file is part of VirtualBox Open Source Edition (OSE), as',
491 ' * available from http://www.virtualbox.org. This file is free software;',
492 ' * you can redistribute it and/or modify it under the terms of the GNU',
493 ' * General Public License (GPL) as published by the Free Software',
494 ' * Foundation, in version 2 as it comes in the "COPYING" file of the',
495 ' * VirtualBox OSE distribution. VirtualBox OSE is distributed in the',
496 ' * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.',
497 ' * ',
498 ' * The contents of this file may alternatively be used under the terms',
499 ' * of the Common Development and Distribution License Version 1.0',
500 ' * (CDDL) only, as it comes in the "COPYING.CDDL" file of the',
501 ' * VirtualBox OSE distribution, in which case the provisions of the',
502 ' * CDDL are applicable instead of those of the GPL.',
503 ' * ',
504 ' * You may elect to license modified versions of this file under the',
505 ' * terms and conditions of either the GPL or the CDDL or both.',
506 ' */',
507 '',
508 '',
509 '#include "bs3-cpu-generated-1.h"',
510 '',
511 '',
512 '#pragma data_seg ("BS3DATA16")',
513 ];
514
515 # Generate the g_achBs3Cg1Mnemonics array.
516 asLines += [
517 'const char BS3_FAR_DATA g_achBs3Cg1Mnemonics[] = ',
518 '{',
519 ];
520 fAdvanceMnemonic = True;
521 for oInstr in self.aoInstructions:
522 if fAdvanceMnemonic:
523 asLines.append(' \"%s\"' % (oInstr.oInstr.sMnemonic,));
524 fAdvanceMnemonic = oInstr.fAdvanceMnemonic;
525 asLines += [
526 '};',
527 '',
528 '',
529 ];
530
531 # Generate the g_abBs3Cg1Opcodes array.
532 asLines += [
533 'const uint8_t BS3_FAR_DATA g_abBs3Cg1Opcodes[] = ',
534 '{',
535 ];
536 for oInstr in self.aoInstructions:
537 asLines.append(' ' + ', '.join(oInstr.asOpcodes) + ',');
538 asLines += [
539 '};',
540 '',
541 '',
542 ];
543
544 # Generate the g_abBs3Cg1Opcodes array.
545 asLines += [
546 'const uint8_t BS3_FAR_DATA g_abBs3Cg1Operands[] = ',
547 '{',
548 ];
549 cOperands = 0;
550 for oInstr in self.aoInstructions:
551 if oInstr.oInstr.aoOperands:
552 cOperands += len(oInstr.oInstr.aoOperands);
553 asLines.append(' ' + oInstr.getOperands() + ', /* %s */' % (oInstr.oInstr.sStats,));
554 else:
555 asLines.append(' /* none */');
556 if not cOperands:
557 asLines.append(' 0 /* dummy */');
558 asLines += [
559 '};',
560 '',
561 '',
562 ];
563
564 # Generate the g_abBs3Cg1Operands array.
565 asLines += [
566 'const BS3CG1INSTR BS3_FAR_DATA g_aBs3Cg1Instructions[] = ',
567 '{',
568 ];
569 for oInstr in self.aoInstructions:
570 asLines.append(' {');
571 asLines += oInstr.getInstructionEntry();
572 asLines.append(' },');
573 asLines += [
574 '};',
575 'const uint16_t BS3_FAR_DATA g_cBs3Cg1Instructions = RT_ELEMENTS(g_aBs3Cg1Instructions);',
576 '',
577 '',
578 ];
579
580 # Generate the g_abBs3Cg1Tests array.
581 asLines += [
582 'const uint8_t BS3_FAR_DATA g_abBs3Cg1Tests[] = ',
583 '{',
584 ];
585 for oTests in self.aoTests:
586 asLines.append(' /*');
587 asLines.append(' * offTests=%s' % (oTests.offTests,));
588 asLines.append(' * Instructions: %s' % (', '.join([oInstr.sStats for oInstr in oTests.aoInstructions]),));
589 asLines.append(' */');
590 asLines += oTests.asLines;
591 asLines += [
592 '};',
593 '',
594 ];
595
596
597 #/** The test data that BS3CG1INSTR.
598 # * In order to simplify generating these, we use a byte array. */
599 #extern const uint8_t BS3_FAR_DATA g_abBs3Cg1Tests[];
600
601
602 oOut.write('\n'.join(asLines));
603 return True;
604
605
606 def usage(self):
607 """ Prints usage. """
608 print('usage: bs3-cpu-generated-1-data.py [output file|-]');
609 return 0;
610
611 def main(self, asArgs):
612 """
613 C-like main function.
614 Returns exit code.
615 """
616
617 #
618 # Quick argument parsing.
619 #
620 if len(asArgs) == 1:
621 sOutFile = '-';
622 elif len(asArgs) != 2:
623 print('syntax error! Expected exactly one argument.');
624 return 2;
625 elif asArgs[1] in [ '-h', '-?', '--help' ]:
626 return self.usage();
627 else:
628 sOutFile = asArgs[1];
629
630 #
631 # Process the instructions specified in the IEM sources.
632 #
633 if self.processInstruction():
634
635 #
636 # Open the output file and generate the code.
637 #
638 if sOutFile == '-':
639 oOut = sys.stdout;
640 else:
641 try:
642 oOut = open(sOutFile, 'w'); # pylint: disable=consider-using-with
643 except Exception as oXcpt:
644 print('error! Failed open "%s" for writing: %s' % (sOutFile, oXcpt,));
645 return 1;
646 if self.generateCode(oOut):
647 return 0;
648
649 return 1;
650
651
652if __name__ == '__main__':
653 sys.exit(Bs3CpuGenerated1Generator().main(sys.argv));
654
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