1 | #!/usr/bin/env python
|
---|
2 | # -*- coding: utf-8 -*-
|
---|
3 | # $Id: bs3-cpu-generated-1-data.py 66055 2017-03-10 21:00:14Z vboxsync $
|
---|
4 | # pylint: disable=invalid-name
|
---|
5 |
|
---|
6 | """
|
---|
7 | Generates testcases from @optest specifications in IEM.
|
---|
8 | """
|
---|
9 |
|
---|
10 | from __future__ import print_function;
|
---|
11 |
|
---|
12 | __copyright__ = \
|
---|
13 | """
|
---|
14 | Copyright (C) 2017 Oracle Corporation
|
---|
15 |
|
---|
16 | This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
17 | available from http://www.virtualbox.org. This file is free software;
|
---|
18 | you can redistribute it and/or modify it under the terms of the GNU
|
---|
19 | General Public License (GPL) as published by the Free Software
|
---|
20 | Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
21 | VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
22 | hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
23 |
|
---|
24 | The contents of this file may alternatively be used under the terms
|
---|
25 | of the Common Development and Distribution License Version 1.0
|
---|
26 | (CDDL) only, as it comes in the "COPYING.CDDL" file of the
|
---|
27 | VirtualBox OSE distribution, in which case the provisions of the
|
---|
28 | CDDL are applicable instead of those of the GPL.
|
---|
29 |
|
---|
30 | You may elect to license modified versions of this file under the
|
---|
31 | terms and conditions of either the GPL or the CDDL or both.
|
---|
32 | """
|
---|
33 | __version__ = "$Revision: 66055 $"
|
---|
34 |
|
---|
35 | # Standard python imports.
|
---|
36 | import os;
|
---|
37 | import sys;
|
---|
38 |
|
---|
39 | # Only the main script needs to modify the path.
|
---|
40 | g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)));
|
---|
41 | g_ksVmmAllDir = os.path.join(os.path.dirname(g_ksValidationKitDir), 'VMM', 'VMMAll')
|
---|
42 | sys.path.append(g_ksVmmAllDir);
|
---|
43 |
|
---|
44 | import IEMAllInstructionsPython as iai; # pylint: disable=import-error
|
---|
45 |
|
---|
46 |
|
---|
47 | # Python 3 hacks:
|
---|
48 | if sys.version_info[0] >= 3:
|
---|
49 | long = int; # pylint: disable=redefined-builtin,invalid-name
|
---|
50 |
|
---|
51 |
|
---|
52 | class 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.sValue.sOp == '==':
|
---|
76 | sByte = '(BS3CG1PRED_%s << BS3CG1SEL_OP_PRED_SHIFT) | BS3CG1SEL_OP_IS_TRUE' % (sConstant,);
|
---|
77 | elif oSelector.sValue.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 _compileContextModifers(aoOperations): # (list(iai.TestInOut))
|
---|
107 | """
|
---|
108 | Compile a list of iai.TestInOut context modifiers.
|
---|
109 | """
|
---|
110 | asRet = [];
|
---|
111 | for oOperation in aoOperations:
|
---|
112 | oType = iai.TestInOut.kdTypes[oOperation.sType];
|
---|
113 | aaoValues = oType.get(oOperation.sValue);
|
---|
114 | assert len(aaoValues) == 1 or len(aaoValues) == 2;
|
---|
115 |
|
---|
116 | sOp = oOperation.sOp;
|
---|
117 | if sOp == '&|=':
|
---|
118 | sOp = '|=' if len(aaoValues) == 1 else '&~=';
|
---|
119 |
|
---|
120 | for fSignExtend, abValue in aaoValues:
|
---|
121 | cbValue = len(abValue);
|
---|
122 |
|
---|
123 | # The opcode byte.
|
---|
124 | sOpcode = Bs3Cg1TestEncoder.kdOperators[sOp];
|
---|
125 | sOpcode += ' | ';
|
---|
126 | if oOperation.sField in Bs3Cg1TestEncoder.kdSmallFields:
|
---|
127 | sOpcode += Bs3Cg1TestEncoder.kdSmallFields[oOperation.sField];
|
---|
128 | else:
|
---|
129 | sOpcode += 'BS3CG1_CTXOP_DST_ESC';
|
---|
130 | sOpcode += ' | ';
|
---|
131 | if cbValue in Bs3Cg1TestEncoder.kdSmallSizes:
|
---|
132 | sOpcode += Bs3Cg1TestEncoder.kdSmallSizes[cbValue];
|
---|
133 | else:
|
---|
134 | sOpcode += 'BS3CG1_CTXOP_SIZE_ESC';
|
---|
135 | if fSignExtend:
|
---|
136 | sOpcode += '| BS3CG1_CTXOP_SIGN_EXT';
|
---|
137 | asRet.append(sOpcode);
|
---|
138 |
|
---|
139 | # Escaped field identifier.
|
---|
140 | if oOperation.sField not in Bs3Cg1TestEncoder.kdSmallFields:
|
---|
141 | asRet.append('BS3CG1DST_%s' % (oOperation.sField.upper().replace('.', '_'),));
|
---|
142 |
|
---|
143 | # Escaped size byte?
|
---|
144 | if cbValue not in Bs3Cg1TestEncoder.kdSmallSizes:
|
---|
145 | if cbValue >= 256 or cbValue not in [ 1, 2, 4, 6, 8, 12, 16, 32, 64, 128, ]:
|
---|
146 | raise Exception('Invalid value size: %s' % (cbValue,));
|
---|
147 | asRet.append('0x%02x' % (cbValue,));
|
---|
148 |
|
---|
149 | # The value bytes.
|
---|
150 | for b in abValue:
|
---|
151 | asRet.append('0x%02x' % (b,));
|
---|
152 |
|
---|
153 | sOp = '|=';
|
---|
154 |
|
---|
155 | return asRet;
|
---|
156 |
|
---|
157 | def _constructHeader(self):
|
---|
158 | """
|
---|
159 | Returns C byte expression strings for BS3CG1TESTHDR.
|
---|
160 | """
|
---|
161 | cbSelectors = len(self.asSelectors);
|
---|
162 | if cbSelectors >= 256:
|
---|
163 | raise Exception('Too many selectors: %s bytes, max 255 bytes' % (cbSelectors,))
|
---|
164 |
|
---|
165 | cbInputs = len(self.asInputs);
|
---|
166 | if cbInputs >= 4096:
|
---|
167 | raise Exception('Too many input context modifiers: %s bytes, max 4095 bytes' % (cbInputs,))
|
---|
168 |
|
---|
169 | cbOutputs = len(self.asOutputs);
|
---|
170 | if cbOutputs >= 2048:
|
---|
171 | raise Exception('Too many output context modifiers: %s bytes, max 2047 bytes' % (cbOutputs,))
|
---|
172 |
|
---|
173 | return [
|
---|
174 | '%#04x' % (cbSelectors,), # 8-bit
|
---|
175 | '%#05x & 0xff' % (cbInputs,), # first 8 bits of cbInputs
|
---|
176 | '(%#05x >> 8) | ((%#05x & 0xf) << 4)' % (cbInputs, cbOutputs,), # last 4 bits of cbInputs, lower 4 bits of cbOutputs.
|
---|
177 | '(%#05x >> 4) | (%#05x << 7)' % (cbOutputs, self.fLast), # last 7 bits of cbOutputs and 1 bit fLast.
|
---|
178 | ];
|
---|
179 |
|
---|
180 | def encodeTest(self, oTest): # type: (iai.InstructionTest)
|
---|
181 | """
|
---|
182 | Does the encoding.
|
---|
183 | """
|
---|
184 | self.asSelectors = self._compileSelectors(oTest.aoSelectors);
|
---|
185 | self.asInputs = self._compileContextModifers(oTest.aoInputs);
|
---|
186 | self.asOutputs = self._compileContextModifers(oTest.aoOutputs);
|
---|
187 | self.asHdr = self._constructHeader();
|
---|
188 |
|
---|
189 |
|
---|
190 | class Bs3Cg1EncodedTests(object):
|
---|
191 | """
|
---|
192 | Encodes the tests for an instruction.
|
---|
193 | """
|
---|
194 |
|
---|
195 | def __init__(self, oInstr):
|
---|
196 | self.offTests = -1;
|
---|
197 | self.cbTests = 0;
|
---|
198 | self.asLines = [];
|
---|
199 |
|
---|
200 | # Encode the tests.
|
---|
201 | for iTest, oTest in enumerate(oInstr.aoTests):
|
---|
202 | oEncodedTest = Bs3Cg1TestEncoder(iTest + 1 == len(oInstr.aoTests));
|
---|
203 | oEncodedTest.encodeTest(oTest);
|
---|
204 |
|
---|
205 | self.cbTests += len(oEncodedTest.asHdr) + len(oEncodedTest.asSelectors) \
|
---|
206 | + len(oEncodedTest.asInputs) + len(oEncodedTest.asOutputs);
|
---|
207 |
|
---|
208 | self.asLines += self.bytesToLines(' /*hdr:*/ ', oEncodedTest.asHdr);
|
---|
209 | if oEncodedTest.asSelectors:
|
---|
210 | self.asLines += self.bytesToLines(' /*sel:*/ ', oEncodedTest.asSelectors);
|
---|
211 | if oEncodedTest.asInputs:
|
---|
212 | self.asLines += self.bytesToLines(' /* in:*/ ', oEncodedTest.asInputs);
|
---|
213 | if oEncodedTest.asOutputs:
|
---|
214 | self.asLines += self.bytesToLines(' /*out:*/ ', oEncodedTest.asOutputs);
|
---|
215 |
|
---|
216 | @staticmethod
|
---|
217 | def bytesToLines(sPrefix, asBytes):
|
---|
218 | """
|
---|
219 | Formats a series of bytes into one or more lines.
|
---|
220 | A byte ending with a newline indicates that we should start a new line,
|
---|
221 | and prefix it by len(sPrefix) spaces.
|
---|
222 |
|
---|
223 | Returns list of lines.
|
---|
224 | """
|
---|
225 | asRet = [];
|
---|
226 | sLine = sPrefix;
|
---|
227 | for sByte in asBytes:
|
---|
228 | if sByte[-1] == '\n':
|
---|
229 | sLine += sByte[:-1] + ',';
|
---|
230 | asRet.append(sLine);
|
---|
231 | sLine = ' ' * len(sPrefix);
|
---|
232 | else:
|
---|
233 | if len(sLine) + 2 + len(sByte) > 132 and len(sLine) > len(sPrefix):
|
---|
234 | asRet.append(sLine[:-1]);
|
---|
235 | sLine = ' ' * len(sPrefix);
|
---|
236 | sLine += sByte + ', ';
|
---|
237 |
|
---|
238 |
|
---|
239 | if len(sLine) > len(sPrefix):
|
---|
240 | asRet.append(sLine);
|
---|
241 | return asRet;
|
---|
242 |
|
---|
243 |
|
---|
244 | def isEqual(self, oOther):
|
---|
245 | """ Compares two encoded tests. """
|
---|
246 | if self.cbTests != oOther.cbTests:
|
---|
247 | return False;
|
---|
248 | if len(self.asLines) != len(oOther.asLines):
|
---|
249 | return False;
|
---|
250 | for iLine, sLines in enumerate(self.asLines):
|
---|
251 | if sLines != oOther.asLines[iLine]:
|
---|
252 | return False;
|
---|
253 | return True;
|
---|
254 |
|
---|
255 |
|
---|
256 |
|
---|
257 | class Bs3Cg1Instruction(object):
|
---|
258 | """
|
---|
259 | An instruction with tests.
|
---|
260 | """
|
---|
261 |
|
---|
262 | def __init__(self, oMap, oInstr, oTests):
|
---|
263 | self.oMap = oMap; # type: iai.InstructionMap
|
---|
264 | self.oInstr = oInstr; # type: iai.Instruction
|
---|
265 | self.oTests = oTests; # type: Bs3Cg1EncodedTests
|
---|
266 |
|
---|
267 | self.asOpcodes = oMap.asLeadOpcodes + [ '0x%02x' % (oInstr.getOpcodeByte(),) ];
|
---|
268 | self.sEncoding = iai.g_kdEncodings[oInstr.sEncoding][0];
|
---|
269 | for oOp in oInstr.aoOperands:
|
---|
270 | self.sEncoding += '_' + oOp.sType;
|
---|
271 | self.asFlags = [];
|
---|
272 | self.fAdvanceMnemonic = True; ##< Set by the caller.
|
---|
273 | if self.sEncoding == 'ModR/M':
|
---|
274 | if 'ignores_op_size' not in oInstr.dHints:
|
---|
275 | self.sPfxKind = 'BS3CGPFXKIND_MODRM';
|
---|
276 | else:
|
---|
277 | self.sPfxKind = 'BS3CGPFXKIND_MODRM_NO_OP_SIZES';
|
---|
278 | else:
|
---|
279 | self.sPfxKind = '0';
|
---|
280 |
|
---|
281 |
|
---|
282 | def getOperands(self):
|
---|
283 | """ Returns comma separated string of operand values for g_abBs3Cg1Operands. """
|
---|
284 | return ', '.join(['(uint8_t)BS3CG1OP_%s' % (oOp.sType,) for oOp in self.oInstr.aoOperands]);
|
---|
285 |
|
---|
286 | def getInstructionEntry(self):
|
---|
287 | """ Returns an array of BS3CG1INSTR member initializers. """
|
---|
288 | return [
|
---|
289 | ' /* cbOpcodes = */ %s,' % (len(self.asOpcodes),),
|
---|
290 | ' /* cOperands = */ %s,' % (len(self.oInstr.aoOperands),),
|
---|
291 | ' /* cchMnemonic = */ %s,' % (len(self.oInstr.sMnemonic),),
|
---|
292 | ' /* fAdvanceMnemonic = */ %s,' % ('true' if self.fAdvanceMnemonic else 'false',),
|
---|
293 | ' /* offTests = */ %s,' % (self.oTests.offTests,),
|
---|
294 | ' /* enmEncoding = */ (unsigned)%s,' % (self.sEncoding,),
|
---|
295 | ' /* enmPfxKind = */ (unsigned)%s,' % (self.sPfxKind,),
|
---|
296 | ' /* uUnused = */ 0,',
|
---|
297 | ' /* fFlags = */ %s' % (' | '.join(self.asFlags) if self.asFlags else '0'),
|
---|
298 | ];
|
---|
299 |
|
---|
300 |
|
---|
301 | class Bs3CpuGenerated1Generator(object):
|
---|
302 | """
|
---|
303 | The generator code for bs3-cpu-generated-1.
|
---|
304 | """
|
---|
305 |
|
---|
306 | def __init__(self):
|
---|
307 | self.aoInstructions = []; # type: Bs3Cg1Instruction
|
---|
308 | self.aoTests = []; # type: Bs3Cg1EncodedTests
|
---|
309 | self.cbTests = 0;
|
---|
310 |
|
---|
311 | def addTests(self, oTests):
|
---|
312 | """
|
---|
313 | Adds oTests to self.aoTests, setting the oTests.offTests member.
|
---|
314 | Checks for and eliminates duplicates.
|
---|
315 | Returns the tests to use.
|
---|
316 | """
|
---|
317 | # Check for duplicates.
|
---|
318 | for oExisting in self.aoTests:
|
---|
319 | if oTests.isEqual(oExisting):
|
---|
320 | return oExisting;
|
---|
321 |
|
---|
322 | # New test, so add it.
|
---|
323 | oTests.offTests = self.cbTests;
|
---|
324 | self.aoTests.append(oTests);
|
---|
325 | self.cbTests += oTests.cbTests;
|
---|
326 |
|
---|
327 | return oTests;
|
---|
328 |
|
---|
329 | def processInstruction(self):
|
---|
330 | """
|
---|
331 | Processes the IEM specified instructions.
|
---|
332 | Returns success indicator.
|
---|
333 | """
|
---|
334 |
|
---|
335 | #
|
---|
336 | # Group instructions by mnemonic to reduce the number of sub-tests.
|
---|
337 | #
|
---|
338 | for oInstr in sorted(iai.g_aoAllInstructions,
|
---|
339 | key = lambda oInstr: oInstr.sMnemonic + ''.join([oOp.sType for oOp in oInstr.aoOperands])
|
---|
340 | + (oInstr.sOpcode if oInstr.sOpcode else 'zz')):
|
---|
341 | if oInstr.aoTests:
|
---|
342 | oTests = Bs3Cg1EncodedTests(oInstr);
|
---|
343 | oTests = self.addTests(oTests);
|
---|
344 |
|
---|
345 | for oMap in oInstr.aoMaps:
|
---|
346 | self.aoInstructions.append(Bs3Cg1Instruction(oMap, oInstr, oTests));
|
---|
347 |
|
---|
348 | # Set fAdvanceMnemonic.
|
---|
349 | for iInstr, oInstr in enumerate(self.aoInstructions):
|
---|
350 | oInstr.fAdvanceMnemonic = iInstr + 1 >= len(self.aoInstructions) \
|
---|
351 | or oInstr.oInstr.sMnemonic != self.aoInstructions[iInstr + 1].oInstr.sMnemonic;
|
---|
352 |
|
---|
353 | return True;
|
---|
354 |
|
---|
355 | def generateCode(self, oOut):
|
---|
356 | """
|
---|
357 | Generates the C code.
|
---|
358 | Returns success indicator.
|
---|
359 | """
|
---|
360 |
|
---|
361 | # First, a file header.
|
---|
362 | asLines = [
|
---|
363 | '/*',
|
---|
364 | ' * Autogenerated by $Id: bs3-cpu-generated-1-data.py 66055 2017-03-10 21:00:14Z vboxsync $ ',
|
---|
365 | ' * Do not edit!',
|
---|
366 | ' */',
|
---|
367 | '',
|
---|
368 | '/*',
|
---|
369 | ' * Copyright (C) 2017 Oracle Corporation',
|
---|
370 | ' *',
|
---|
371 | ' * This file is part of VirtualBox Open Source Edition (OSE), as',
|
---|
372 | ' * available from http://www.virtualbox.org. This file is free software;',
|
---|
373 | ' * you can redistribute it and/or modify it under the terms of the GNU',
|
---|
374 | ' * General Public License (GPL) as published by the Free Software',
|
---|
375 | ' * Foundation, in version 2 as it comes in the "COPYING" file of the',
|
---|
376 | ' * VirtualBox OSE distribution. VirtualBox OSE is distributed in the',
|
---|
377 | ' * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.',
|
---|
378 | ' * ',
|
---|
379 | ' * The contents of this file may alternatively be used under the terms',
|
---|
380 | ' * of the Common Development and Distribution License Version 1.0',
|
---|
381 | ' * (CDDL) only, as it comes in the "COPYING.CDDL" file of the',
|
---|
382 | ' * VirtualBox OSE distribution, in which case the provisions of the',
|
---|
383 | ' * CDDL are applicable instead of those of the GPL.',
|
---|
384 | ' * ',
|
---|
385 | ' * You may elect to license modified versions of this file under the',
|
---|
386 | ' * terms and conditions of either the GPL or the CDDL or both.',
|
---|
387 | ' */',
|
---|
388 | '',
|
---|
389 | '',
|
---|
390 | '#include "bs3-cpu-generated-1.h"',
|
---|
391 | '',
|
---|
392 | '',
|
---|
393 | '#pragma data_seg ("BS3DATA16")',
|
---|
394 | ];
|
---|
395 |
|
---|
396 | # Generate the g_achBs3Cg1Mnemonics array.
|
---|
397 | asLines += [
|
---|
398 | 'const char BS3_FAR_DATA g_achBs3Cg1Mnemonics[] = ',
|
---|
399 | '{',
|
---|
400 | ];
|
---|
401 | for oInstr in self.aoInstructions:
|
---|
402 | asLines.append(' \"%s\"' % (oInstr.oInstr.sMnemonic,));
|
---|
403 | asLines += [
|
---|
404 | '};',
|
---|
405 | '',
|
---|
406 | '',
|
---|
407 | ];
|
---|
408 |
|
---|
409 | # Generate the g_abBs3Cg1Opcodes array.
|
---|
410 | asLines += [
|
---|
411 | 'const uint8_t BS3_FAR_DATA g_abBs3Cg1Opcodes[] = ',
|
---|
412 | '{',
|
---|
413 | ];
|
---|
414 | for oInstr in self.aoInstructions:
|
---|
415 | asLines.append(' ' + ', '.join(oInstr.asOpcodes) + ',');
|
---|
416 | asLines += [
|
---|
417 | '};',
|
---|
418 | '',
|
---|
419 | '',
|
---|
420 | ];
|
---|
421 |
|
---|
422 | # Generate the g_abBs3Cg1Opcodes array.
|
---|
423 | asLines += [
|
---|
424 | 'const uint8_t BS3_FAR_DATA g_abBs3Cg1Operands[] = ',
|
---|
425 | '{',
|
---|
426 | ];
|
---|
427 | for oInstr in self.aoInstructions:
|
---|
428 | asLines.append(' ' + oInstr.getOperands() + ',');
|
---|
429 | asLines += [
|
---|
430 | '};',
|
---|
431 | '',
|
---|
432 | '',
|
---|
433 | ];
|
---|
434 |
|
---|
435 | # Generate the g_abBs3Cg1Operands array.
|
---|
436 | asLines += [
|
---|
437 | 'const BS3CG1INSTR BS3_FAR_DATA g_aBs3Cg1Instructions[] = ',
|
---|
438 | '{',
|
---|
439 | ];
|
---|
440 | for oInstr in self.aoInstructions:
|
---|
441 | asLines.append(' {');
|
---|
442 | asLines += oInstr.getInstructionEntry();
|
---|
443 | asLines.append(' },');
|
---|
444 | asLines += [
|
---|
445 | '};',
|
---|
446 | 'const uint16_t BS3_FAR_DATA g_cBs3Cg1Instructions = RT_ELEMENTS(g_aBs3Cg1Instructions);',
|
---|
447 | '',
|
---|
448 | '',
|
---|
449 | ];
|
---|
450 |
|
---|
451 | # Generate the g_abBs3Cg1Tests array.
|
---|
452 | asLines += [
|
---|
453 | 'const uint8_t BS3_FAR_DATA g_abBs3Cg1Tests[] = ',
|
---|
454 | '{',
|
---|
455 | ];
|
---|
456 | for oTests in self.aoTests:
|
---|
457 | asLines.append(' /* offTests=%s */' % (oTests.offTests,));
|
---|
458 | asLines += oTests.asLines;
|
---|
459 | asLines += [
|
---|
460 | '};',
|
---|
461 | '',
|
---|
462 | ];
|
---|
463 |
|
---|
464 |
|
---|
465 | #/** The test data that BS3CG1INSTR.
|
---|
466 | # * In order to simplify generating these, we use a byte array. */
|
---|
467 | #extern const uint8_t BS3_FAR_DATA g_abBs3Cg1Tests[];
|
---|
468 |
|
---|
469 |
|
---|
470 | oOut.write('\n'.join(asLines));
|
---|
471 | return True;
|
---|
472 |
|
---|
473 |
|
---|
474 | def usage(self):
|
---|
475 | """ Prints usage. """
|
---|
476 | print('usage: bs3-cpu-generated-1-data.py [output file|-]');
|
---|
477 | return 0;
|
---|
478 |
|
---|
479 | def main(self, asArgs):
|
---|
480 | """
|
---|
481 | C-like main function.
|
---|
482 | Returns exit code.
|
---|
483 | """
|
---|
484 |
|
---|
485 | #
|
---|
486 | # Quick argument parsing.
|
---|
487 | #
|
---|
488 | if len(asArgs) == 1:
|
---|
489 | sOutFile = '-';
|
---|
490 | elif len(asArgs) != 2:
|
---|
491 | print('syntax error! Expected exactly one argument.');
|
---|
492 | return 2;
|
---|
493 | elif asArgs[1] in [ '-h', '-?', '--help' ]:
|
---|
494 | return self.usage();
|
---|
495 | else:
|
---|
496 | sOutFile = asArgs[1];
|
---|
497 |
|
---|
498 | #
|
---|
499 | # Process the instructions specified in the IEM sources.
|
---|
500 | #
|
---|
501 | if self.processInstruction():
|
---|
502 |
|
---|
503 | #
|
---|
504 | # Open the output file and generate the code.
|
---|
505 | #
|
---|
506 | if sOutFile == '-':
|
---|
507 | oOut = sys.stdout;
|
---|
508 | else:
|
---|
509 | try:
|
---|
510 | oOut = open(sOutFile, 'w');
|
---|
511 | except Exception as oXcpt:
|
---|
512 | print('error! Failed open "%s" for writing: %s' % (sOutFile, oXcpt,));
|
---|
513 | return 1;
|
---|
514 | if self.generateCode(oOut):
|
---|
515 | return 0;
|
---|
516 |
|
---|
517 | return 1;
|
---|
518 |
|
---|
519 |
|
---|
520 | if __name__ == '__main__':
|
---|
521 | sys.exit(Bs3CpuGenerated1Generator().main(sys.argv));
|
---|
522 |
|
---|
523 |
|
---|