Changeset 98873 in vbox for trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py
- Timestamp:
- Mar 8, 2023 1:51:04 AM (22 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py
r98842 r98873 46 46 __version__ = "$Revision$" 47 47 48 # pylint: disable=anomalous-backslash-in-string 48 # pylint: disable=anomalous-backslash-in-string,too-many-lines 49 49 50 50 # Standard python imports. 51 import os 52 import re 53 import sys 51 import os; 52 import re; 53 import sys; 54 import traceback; 54 55 55 56 ## Only the main script needs to modify the path. … … 1740 1741 1741 1742 1743 class McBlock(object): 1744 """ 1745 Microcode block (IEM_MC_BEGIN ... IEM_MC_END). 1746 """ 1747 1748 def __init__(self, sSrcFile, iBeginLine, offBeginLine, sFunction, iInFunction): 1749 self.sSrcFile = sSrcFile; ##< The source file containing the block. 1750 self.iBeginLine = iBeginLine; ##< The line with the IEM_MC_BEGIN statement. 1751 self.offBeginLine = offBeginLine; ##< The offset of the IEM_MC_BEGIN statement within the line. 1752 self.iEndLine = -1; ##< The line with the IEM_MC_END statement. 1753 self.offEndLine = 0; ##< The offset of the IEM_MC_END statement within the line. 1754 self.sFunction = sFunction; ##< The function the block resides in. 1755 self.iInFunction = iInFunction; ##< The block number wihtin the function. 1756 self.asLines = [] # type: list(str) ##< The raw lines the block is made up of. 1757 1758 def complete(self, iEndLine, offEndLine, asLines): 1759 """ 1760 Completes the microcode block. 1761 """ 1762 assert self.iEndLine == -1; 1763 self.iEndLine = iEndLine; 1764 self.offEndLine = offEndLine; 1765 self.asLines = asLines; 1766 1767 1768 ## List of microcode blocks. 1769 g_aoMcBlocks = [] # type: list(McBlock) 1770 1771 1772 1742 1773 class ParserException(Exception): 1743 1774 """ Parser exception """ … … 1746 1777 1747 1778 1748 class SimpleParser(object): 1779 class SimpleParser(object): # pylint: disable=too-many-instance-attributes 1749 1780 """ 1750 1781 Parser of IEMAllInstruction*.cpp.h instruction specifications. … … 1756 1787 kiCommentMulti = 1; 1757 1788 ## @} 1789 1790 class Macro(object): 1791 """ Macro """ 1792 def __init__(self, sName, asArgs, sBody, iLine): 1793 self.sName = sName; ##< The macro name. 1794 self.asArgs = asArgs; ##< None if simple macro, list of parameters otherwise. 1795 self.sBody = sBody; 1796 self.iLine = iLine; 1797 self.oReArgMatch = re.compile(r'(\s*##\s*|\b)(' + '|'.join(asArgs) + r')(\s*##\s*|\b)') if asArgs else None; 1798 1799 @staticmethod 1800 def _needSpace(ch): 1801 """ This is just to make the expanded output a bit prettier. """ 1802 return ch.isspace() and ch != '('; 1803 1804 def expandMacro(self, oParent, asArgs = None): 1805 """ Expands the macro body with the given arguments. """ 1806 _ = oParent; 1807 sBody = self.sBody; 1808 1809 if self.oReArgMatch: 1810 assert len(asArgs) == len(self.asArgs); 1811 #oParent.debug('%s: %s' % (self.sName, self.oReArgMatch.pattern,)); 1812 1813 dArgs = { self.asArgs[iArg]: sValue for iArg, sValue in enumerate(asArgs) }; 1814 oMatch = self.oReArgMatch.search(sBody); 1815 while oMatch: 1816 sName = oMatch.group(2); 1817 #oParent.debug('%s %s..%s (%s)' % (sName, oMatch.start(), oMatch.end(),oMatch.group())); 1818 sValue = dArgs[sName]; 1819 sPre = ''; 1820 if not oMatch.group(1) and oMatch.start() > 0 and self._needSpace(sBody[oMatch.start()]): 1821 sPre = ' '; 1822 sPost = ''; 1823 if not oMatch.group(3) and oMatch.end() < len(sBody) and self._needSpace(sBody[oMatch.end()]): 1824 sPost = ' '; 1825 sBody = sBody[ : oMatch.start()] + sPre + sValue + sPost + sBody[oMatch.end() : ]; 1826 oMatch = self.oReArgMatch.search(sBody, oMatch.start() + len(sValue)); 1827 else: 1828 assert not asArgs; 1829 1830 return sBody; 1831 1758 1832 1759 1833 def __init__(self, sSrcFile, asLines, sDefaultMap): … … 1764 1838 self.sComment = ''; 1765 1839 self.iCommentLine = 0; 1766 self.aoCurInstrs = []; 1840 self.aoCurInstrs = [] # type: list(Instruction) 1841 self.sCurFunction = None # type: str 1842 self.iMcBlockInFunc = 0; 1843 self.oCurMcBlock = None # type: McBlock 1844 self.dMacros = {} # type: Dict[str,SimpleParser.Macro] 1845 self.oReMacros = None # type: re ##< Regular expression matching invocations of anything in self.dMacros. 1767 1846 1768 1847 assert sDefaultMap in g_dInstructionMaps; … … 1772 1851 self.cTotalStubs = 0; 1773 1852 self.cTotalTagged = 0; 1853 self.cTotalMcBlocks = 0; 1774 1854 1775 1855 self.oReMacroName = re.compile('^[A-Za-z_][A-Za-z0-9_]*$'); … … 1781 1861 self.oReFunTable = re.compile('^(IEM_STATIC|static) +const +PFNIEMOP +g_apfn[A-Za-z0-9_]+ *\[ *\d* *\] *= *$'); 1782 1862 self.oReComment = re.compile('//.*?$|/\*.*?\*/'); ## Full comments. 1863 self.oReHashDefine = re.compile('^\s*#\s*define\s+(.*)$'); 1864 self.oReHashDefine2 = re.compile('(?s)\A\s*([A-Za-z_][A-Za-z0-9_]*)\(([^)]*)\)\s*(.*)\Z'); ##< With arguments. 1865 self.oReHashDefine3 = re.compile('(?s)\A\s*([A-Za-z_][A-Za-z0-9_]*)[^(]\s*(.*)\Z'); ##< Simple, no arguments. 1866 self.oReHashUndef = re.compile('^\s*#\s*undef\s+(.*)$'); 1867 self.oReMcBeginEnd = re.compile(r'\bIEM_MC_(BEGIN|END)\s*\('); 1868 1783 1869 self.fDebug = True; 1870 self.fDebugMc = False; 1871 self.fDebugPreProc = False; 1784 1872 1785 1873 self.dTagHandlers = { … … 1876 1964 """ 1877 1965 if self.fDebug: 1878 print('debug: %s' % (sMessage,) );1966 print('debug: %s' % (sMessage,), file = sys.stderr); 1879 1967 1880 1968 def stripComments(self, sLine): … … 2126 2214 return True; 2127 2215 2128 def doneInstructions(self, iLineInComment = None ):2216 def doneInstructions(self, iLineInComment = None, fEndOfFunction = False): 2129 2217 """ 2130 2218 Done with current instruction. … … 2139 2227 self.sComment = ''; 2140 2228 self.aoCurInstrs = []; 2229 if fEndOfFunction: 2230 #self.debug('%s: sCurFunction=None' % (self.iLine, )); 2231 self.sCurFunction = None; 2232 self.iMcBlockInFunc = 0; 2141 2233 return True; 2142 2234 … … 3385 3477 sForm, sUpper, sLower, sDisHints, sIemHints, asOperands); 3386 3478 3387 def checkCodeForMacro(self, sCode): 3479 def workerIemMcBegin(self, sCode, offBeginStatementInLine): 3480 """ 3481 Process a IEM_MC_BEGIN macro invocation. 3482 """ 3483 if self.fDebugMc: 3484 self.debug('IEM_MC_BEGIN on %s off %s' % (self.iLine, offBeginStatementInLine,)); 3485 3486 # Check preconditions. 3487 if not self.sCurFunction: 3488 self.raiseError('IEM_MC_BEGIN w/o current function (%s)' % (sCode,)); 3489 if self.oCurMcBlock: 3490 self.raiseError('IEM_MC_BEGIN before IEM_MC_END. Previous IEM_MC_BEGIN at line %u' % (self.oCurMcBlock.iBeginLine,)); 3491 3492 # Start a new block. 3493 self.oCurMcBlock = McBlock(self.sSrcFile, self.iLine, offBeginStatementInLine, self.sCurFunction, self.iMcBlockInFunc); 3494 g_aoMcBlocks.append(self.oCurMcBlock); 3495 self.cTotalMcBlocks += 1; 3496 self.iMcBlockInFunc += 1; 3497 return True; 3498 3499 def workerIemMcEnd(self, offEndStatementInLine): 3500 """ 3501 Process a IEM_MC_END macro invocation. 3502 """ 3503 if self.fDebugMc: 3504 self.debug('IEM_MC_END on %s off %s' % (self.iLine, offEndStatementInLine,)); 3505 3506 # Check preconditions. 3507 if not self.oCurMcBlock: 3508 self.raiseError('IEM_MC_END w/o IEM_MC_BEGIN.'); 3509 3510 # 3511 # Complete and discard the current block. 3512 # 3513 # HACK ALERT! For blocks orginating from macro expansion the start and 3514 # end line will be the same, but the line has multiple 3515 # newlines inside it. So, we have to do some extra tricks 3516 # to get the lines out of there. We ASSUME macros aren't 3517 # messy, but keep IEM_MC_BEGIN/END on separate lines. 3518 # 3519 if self.iLine > self.oCurMcBlock.iBeginLine: 3520 asLines = self.asLines[self.oCurMcBlock.iBeginLine - 1 : self.iLine]; 3521 if not asLines[0].strip().startswith('IEM_MC_BEGIN'): 3522 self.raiseError('IEM_MC_BEGIN is not the first word on the line'); 3523 else: 3524 sRawLine = self.asLines[self.iLine - 1]; 3525 3526 off = sRawLine.find('\n', offEndStatementInLine); 3527 if off > 0: 3528 sRawLine = sRawLine[:off + 1]; 3529 3530 off = sRawLine.rfind('\n', 0, self.oCurMcBlock.offBeginLine) + 1; 3531 sRawLine = sRawLine[off:]; 3532 if not sRawLine.strip().startswith('IEM_MC_BEGIN'): 3533 sRawLine = sRawLine[self.oCurMcBlock.offBeginLine - off:] 3534 3535 asLines = [sLine + '\n' for sLine in sRawLine.split('\n')]; 3536 3537 self.oCurMcBlock.complete(self.iLine, offEndStatementInLine, asLines); 3538 self.oCurMcBlock = None; 3539 return True; 3540 3541 def checkCodeForMacro(self, sCode, offLine): 3388 3542 """ 3389 3543 Checks code for relevant macro invocation. … … 3396 3550 asArgs = self.findAndParseFirstMacroInvocation(sCode, 3397 3551 [ 'FNIEMOP_DEF', 3552 'FNIEMOPRM_DEF', 3398 3553 'FNIEMOP_STUB', 3399 3554 'FNIEMOP_STUB_1', … … 3401 3556 'FNIEMOP_UD_STUB_1' ]); 3402 3557 if asArgs is not None: 3403 sFunction = asArgs[1]; 3558 self.sCurFunction = asArgs[1]; 3559 #self.debug('%s: sCurFunction=%s' % (self.iLine, self.sCurFunction,)); 3404 3560 3405 3561 if not self.aoCurInstrs: … … 3410 3566 else: 3411 3567 self.error('%s: already seen a FNIEMOP_XXX macro for %s' % (asArgs[0], oInstr,) ); 3412 self.setInstrunctionAttrib('sFunction', sFunction);3568 self.setInstrunctionAttrib('sFunction', asArgs[1]); 3413 3569 self.setInstrunctionAttrib('fStub', asArgs[0].find('STUB') > 0, fOverwrite = True); 3414 3570 self.setInstrunctionAttrib('fUdStub', asArgs[0].find('UD_STUB') > 0, fOverwrite = True); 3415 3571 if asArgs[0].find('STUB') > 0: 3416 self.doneInstructions(); 3572 self.doneInstructions(fEndOfFunction = True); 3573 return True; 3574 3575 # Check for worker function definitions, so we can get a context for MC blocks. 3576 asArgs = self.findAndParseFirstMacroInvocation(sCode, 3577 [ 'FNIEMOP_DEF_1', 3578 'FNIEMOP_DEF_2', ]); 3579 if asArgs is not None: 3580 self.sCurFunction = asArgs[1]; 3581 #self.debug('%s: sCurFunction=%s (%s)' % (self.iLine, self.sCurFunction, asArgs[0])); 3417 3582 return True; 3418 3583 … … 3438 3603 # IEMOP_MNEMONIC* 3439 3604 # 3440 3441 # IEMOP_MNEMONIC(a_Stats, a_szMnemonic) IEMOP_INC_STATS(a_Stats) 3442 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC'); 3443 if asArgs is not None: 3444 if len(self.aoCurInstrs) == 1: 3445 oInstr = self.aoCurInstrs[0]; 3446 if oInstr.sStats is None: 3447 oInstr.sStats = asArgs[1]; 3448 self.deriveMnemonicAndOperandsFromStats(oInstr, asArgs[1]); 3449 3450 # IEMOP_MNEMONIC0EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_fDisHints, a_fIemHints) 3451 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC0EX'); 3452 if asArgs is not None: 3453 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[6], asArgs[7], 3454 []); 3455 # IEMOP_MNEMONIC1EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_fDisHints, a_fIemHints) 3456 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC1EX'); 3457 if asArgs is not None: 3458 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[7], asArgs[8], 3459 [asArgs[6],]); 3460 # IEMOP_MNEMONIC2EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_fDisHints, a_fIemHints) 3461 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC2EX'); 3462 if asArgs is not None: 3463 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[8], asArgs[9], 3464 [asArgs[6], asArgs[7]]); 3465 # IEMOP_MNEMONIC3EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_fDisHints, a_fIemHints) 3466 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC3EX'); 3467 if asArgs is not None: 3468 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[9], 3469 asArgs[10], [asArgs[6], asArgs[7], asArgs[8],]); 3470 # IEMOP_MNEMONIC4EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_Op4, a_fDisHints, 3471 # a_fIemHints) 3472 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC4EX'); 3473 if asArgs is not None: 3474 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[10], 3475 asArgs[11], [asArgs[6], asArgs[7], asArgs[8], asArgs[9],]); 3476 3477 # IEMOP_MNEMONIC0(a_Form, a_Upper, a_Lower, a_fDisHints, a_fIemHints) 3478 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC0'); 3479 if asArgs is not None: 3480 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], []); 3481 # IEMOP_MNEMONIC1(a_Form, a_Upper, a_Lower, a_Op1, a_fDisHints, a_fIemHints) 3482 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC1'); 3483 if asArgs is not None: 3484 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[5], asArgs[6], [asArgs[4],]); 3485 # IEMOP_MNEMONIC2(a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_fDisHints, a_fIemHints) 3486 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC2'); 3487 if asArgs is not None: 3488 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[6], asArgs[7], 3489 [asArgs[4], asArgs[5],]); 3490 # IEMOP_MNEMONIC3(a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_fDisHints, a_fIemHints) 3491 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC3'); 3492 if asArgs is not None: 3493 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[7], asArgs[8], 3494 [asArgs[4], asArgs[5], asArgs[6],]); 3495 # IEMOP_MNEMONIC4(a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_Op4, a_fDisHints, a_fIemHints) 3496 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC4'); 3497 if asArgs is not None: 3498 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[8], asArgs[9], 3499 [asArgs[4], asArgs[5], asArgs[6], asArgs[7],]); 3605 if sCode.find('IEMOP_MNEMONIC') >= 0: 3606 # IEMOP_MNEMONIC(a_Stats, a_szMnemonic) IEMOP_INC_STATS(a_Stats) 3607 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC'); 3608 if asArgs is not None: 3609 if len(self.aoCurInstrs) == 1: 3610 oInstr = self.aoCurInstrs[0]; 3611 if oInstr.sStats is None: 3612 oInstr.sStats = asArgs[1]; 3613 self.deriveMnemonicAndOperandsFromStats(oInstr, asArgs[1]); 3614 3615 # IEMOP_MNEMONIC0EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_fDisHints, a_fIemHints) 3616 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC0EX'); 3617 if asArgs is not None: 3618 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[6], 3619 asArgs[7], []); 3620 # IEMOP_MNEMONIC1EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_fDisHints, a_fIemHints) 3621 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC1EX'); 3622 if asArgs is not None: 3623 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[7], 3624 asArgs[8], [asArgs[6],]); 3625 # IEMOP_MNEMONIC2EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_fDisHints, a_fIemHints) 3626 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC2EX'); 3627 if asArgs is not None: 3628 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[8], 3629 asArgs[9], [asArgs[6], asArgs[7]]); 3630 # IEMOP_MNEMONIC3EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_fDisHints, 3631 # a_fIemHints) 3632 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC3EX'); 3633 if asArgs is not None: 3634 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[9], 3635 asArgs[10], [asArgs[6], asArgs[7], asArgs[8],]); 3636 # IEMOP_MNEMONIC4EX(a_Stats, a_szMnemonic, a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_Op4, a_fDisHints, 3637 # a_fIemHints) 3638 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC4EX'); 3639 if asArgs is not None: 3640 self.workerIemOpMnemonicEx(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], asArgs[10], 3641 asArgs[11], [asArgs[6], asArgs[7], asArgs[8], asArgs[9],]); 3642 3643 # IEMOP_MNEMONIC0(a_Form, a_Upper, a_Lower, a_fDisHints, a_fIemHints) 3644 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC0'); 3645 if asArgs is not None: 3646 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[4], asArgs[5], []); 3647 # IEMOP_MNEMONIC1(a_Form, a_Upper, a_Lower, a_Op1, a_fDisHints, a_fIemHints) 3648 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC1'); 3649 if asArgs is not None: 3650 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[5], asArgs[6], [asArgs[4],]); 3651 # IEMOP_MNEMONIC2(a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_fDisHints, a_fIemHints) 3652 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC2'); 3653 if asArgs is not None: 3654 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[6], asArgs[7], 3655 [asArgs[4], asArgs[5],]); 3656 # IEMOP_MNEMONIC3(a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_fDisHints, a_fIemHints) 3657 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC3'); 3658 if asArgs is not None: 3659 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[7], asArgs[8], 3660 [asArgs[4], asArgs[5], asArgs[6],]); 3661 # IEMOP_MNEMONIC4(a_Form, a_Upper, a_Lower, a_Op1, a_Op2, a_Op3, a_Op4, a_fDisHints, a_fIemHints) 3662 asArgs = self.findAndParseMacroInvocation(sCode, 'IEMOP_MNEMONIC4'); 3663 if asArgs is not None: 3664 self.workerIemOpMnemonic(asArgs[0], asArgs[1], asArgs[2], asArgs[3], asArgs[8], asArgs[9], 3665 [asArgs[4], asArgs[5], asArgs[6], asArgs[7],]); 3666 3667 # 3668 # IEM_MC_BEGIN + IEM_MC_END. 3669 # We must support multiple instances per code snippet. 3670 # 3671 offCode = sCode.find('IEM_MC_'); 3672 if offCode >= 0: 3673 for oMatch in self.oReMcBeginEnd.finditer(sCode, offCode): 3674 if oMatch.group(1) == 'END': 3675 self.workerIemMcEnd(offLine + oMatch.start()); 3676 else: 3677 self.workerIemMcBegin(sCode, offLine + oMatch.start()); 3678 return True; 3500 3679 3501 3680 return False; 3502 3681 3682 def workerPreProcessRecreateMacroRegex(self): 3683 """ 3684 Recreates self.oReMacros when self.dMacros changes. 3685 """ 3686 if self.dMacros: 3687 sRegex = ''; 3688 for sName, oMacro in self.dMacros.items(): 3689 if sRegex: 3690 sRegex += '|' + sName; 3691 else: 3692 sRegex = '\\b(' + sName; 3693 if oMacro.asArgs is not None: 3694 sRegex += '\s*\('; 3695 else: 3696 sRegex += '\\b'; 3697 sRegex += ')'; 3698 self.oReMacros = re.compile(sRegex); 3699 else: 3700 self.oReMacros = None; 3701 return True; 3702 3703 def workerPreProcessDefine(self, sRest): 3704 """ 3705 Handles a macro #define, the sRest is what follows after the directive word. 3706 """ 3707 3708 # 3709 # If using line continutation, just concat all the lines together, 3710 # preserving the newline character but not the escaping. 3711 # 3712 iLineStart = self.iLine; 3713 while sRest.endswith('\\\n') and self.iLine < len(self.asLines): 3714 sRest = sRest[0:-2].rstrip() + '\n' + self.asLines[self.iLine]; 3715 self.iLine += 1; 3716 #self.debug('workerPreProcessDefine: sRest=%s<EOS>' % (sRest,)); 3717 3718 # 3719 # Use regex to split out the name, argument list and body. 3720 # If this fails, we assume it's a simple macro. 3721 # 3722 oMatch = self.oReHashDefine2.match(sRest); 3723 if oMatch: 3724 asArgs = [sParam.strip() for sParam in oMatch.group(2).split(',')]; 3725 sBody = oMatch.group(3); 3726 else: 3727 oMatch = self.oReHashDefine3.match(sRest); 3728 if not oMatch: 3729 self.debug('workerPreProcessDefine: wtf? sRest=%s' % (sRest,)); 3730 return self.error('bogus macro definition: %s' % (sRest,)); 3731 asArgs = None; 3732 sBody = oMatch.group(2); 3733 sName = oMatch.group(1); 3734 assert sName == sName.strip(); 3735 #self.debug('workerPreProcessDefine: sName=%s asArgs=%s sBody=%s<EOS>' % (sName, asArgs, sBody)); 3736 3737 # 3738 # Is this of any interest to us? We do NOT support MC blocks wihtin 3739 # nested macro expansion, just to avoid lots of extra work. 3740 # 3741 if sBody.find("IEM_MC_BEGIN") < 0: 3742 #self.debug('workerPreProcessDefine: irrelevant (%s: %s)' % (sName, sBody)); 3743 return True; 3744 3745 # 3746 # Add the macro. 3747 # 3748 if self.fDebugPreProc: 3749 self.debug('#define %s on line %u' % (sName, self.iLine,)); 3750 self.dMacros[sName] = SimpleParser.Macro(sName, asArgs, sBody, iLineStart); 3751 return self.workerPreProcessRecreateMacroRegex(); 3752 3753 def workerPreProcessUndef(self, sRest): 3754 """ 3755 Handles a macro #undef, the sRest is what follows after the directive word. 3756 """ 3757 # Quick comment strip and isolate the name. 3758 offSlash = sRest.find('/'); 3759 if offSlash > 0: 3760 sRest = sRest[:offSlash]; 3761 sName = sRest.strip(); 3762 3763 # Remove the macro if we're clocking it. 3764 if sName in self.dMacros: 3765 if self.fDebugPreProc: 3766 self.debug('#undef %s on line %u' % (sName, self.iLine,)); 3767 del self.dMacros[sName]; 3768 return self.workerPreProcessRecreateMacroRegex(); 3769 3770 return True; 3771 3772 def checkPreProcessorDirectiveForDefineUndef(self, sLine): 3773 """ 3774 Handles a preprocessor directive. 3775 """ 3776 oMatch = self.oReHashDefine.match(sLine); 3777 if oMatch: 3778 return self.workerPreProcessDefine(oMatch.group(1) + '\n'); 3779 3780 oMatch = self.oReHashUndef.match(sLine); 3781 if oMatch: 3782 return self.workerPreProcessUndef(oMatch.group(1) + '\n'); 3783 return False; 3784 3785 def expandMacros(self, sLine, oMatch): 3786 """ 3787 Expands macros we know about in the given line. 3788 Currently we ASSUME there is only one and that is what oMatch matched. 3789 """ 3790 # 3791 # Get our bearings. 3792 # 3793 offMatch = oMatch.start(); 3794 sName = oMatch.group(1); 3795 assert sName == sLine[oMatch.start() : oMatch.end()]; 3796 fWithArgs = sName.endswith('('); 3797 if fWithArgs: 3798 sName = sName[:-1].strip(); 3799 oMacro = self.dMacros[sName] # type: SimpleParser.Macro 3800 3801 # 3802 # Deal with simple macro invocations w/o parameters. 3803 # 3804 if not fWithArgs: 3805 if self.fDebugPreProc: 3806 self.debug('expanding simple macro %s on line %u' % (sName, self.iLine,)); 3807 return sLine[:offMatch] + oMacro.expandMacro(self) + sLine[oMatch.end():]; 3808 3809 # 3810 # Complicated macro with parameters. 3811 # Start by extracting the parameters. ASSUMES they are all on the same line! 3812 # 3813 cLevel = 1; 3814 offCur = oMatch.end(); 3815 offCurArg = offCur; 3816 asArgs = []; 3817 while True: 3818 ch = sLine[offCur]; 3819 if ch == '(': 3820 cLevel += 1; 3821 elif ch == ')': 3822 cLevel -= 1; 3823 if cLevel == 0: 3824 asArgs.append(sLine[offCurArg:offCur].strip()); 3825 break; 3826 elif ch == ',' and cLevel == 1: 3827 asArgs.append(sLine[offCurArg:offCur].strip()); 3828 offCurArg = offCur + 1; 3829 offCur += 1; 3830 if len(oMacro.asArgs) == 0 and len(asArgs) == 1 and asArgs[0] == '': # trick for empty parameter list. 3831 asArgs = []; 3832 if len(oMacro.asArgs) != len(asArgs): 3833 self.raiseError('expandMacros: Argument mismatch in %s invocation' % (oMacro.sName,)); 3834 3835 # 3836 # Do the expanding. 3837 # 3838 if self.fDebugPreProc: 3839 self.debug('expanding macro %s on line %u with arguments %s' % (sName, self.iLine, asArgs)); 3840 return sLine[:offMatch] + oMacro.expandMacro(self, asArgs) + sLine[offCur + 1 :]; 3503 3841 3504 3842 def parse(self): … … 3513 3851 sLine = self.asLines[self.iLine]; 3514 3852 self.iLine += 1; 3515 3516 # We only look for comments, so only lines with a slash might possibly 3517 # influence the parser state. 3853 #self.debug('line %u: %s' % (self.iLine, sLine[:-1])); 3854 3855 # Expand macros we know about if we're currently in code. 3856 if self.iState == self.kiCode and self.oReMacros: 3857 oMatch = self.oReMacros.search(sLine); 3858 if oMatch: 3859 sLine = self.expandMacros(sLine, oMatch); 3860 if self.fDebugPreProc: 3861 self.debug('line %d: expanded\n%s ==>\n%s' % (self.iLine, self.asLines[self.iLine - 1], sLine[:-1],)); 3862 self.asLines[self.iLine - 1] = sLine; 3863 3864 # Look for comments. 3518 3865 offSlash = sLine.find('/'); 3519 3866 if offSlash >= 0: … … 3522 3869 while offLine < len(sLine): 3523 3870 if self.iState == self.kiCode: 3524 offHit = sLine.find('/*', offLine); # only multiline comments for now. 3871 # Look for substantial multiline comment so we pass the following MC as a whole line: 3872 # IEM_MC_ARG_CONST(uint8_t, bImmArg, /*=*/ bImm, 2); 3873 # Note! We ignore C++ comments here, assuming these aren't used in lines with C-style comments. 3874 offHit = sLine.find('/*', offLine); 3875 while offHit >= 0: 3876 offEnd = sLine.find('*/', offHit + 2); 3877 if offEnd < 0 or offEnd - offHit >= 16: # 16 chars is a bit random. 3878 break; 3879 offHit = sLine.find('/*', offEnd); 3880 3525 3881 if offHit >= 0: 3526 self.checkCodeForMacro(sLine[offLine:offHit] );3882 self.checkCodeForMacro(sLine[offLine:offHit], offLine); 3527 3883 self.sComment = ''; 3528 3884 self.iCommentLine = self.iLine; … … 3530 3886 offLine = offHit + 2; 3531 3887 else: 3532 self.checkCodeForMacro(sLine[offLine:] );3888 self.checkCodeForMacro(sLine[offLine:], offLine); 3533 3889 offLine = len(sLine); 3534 3890 … … 3547 3903 # C++ line comment. 3548 3904 elif offSlash > 0: 3549 self.checkCodeForMacro(sLine[:offSlash] );3905 self.checkCodeForMacro(sLine[:offSlash], 0); 3550 3906 3551 3907 # No slash, but append the line if in multi-line comment. … … 3554 3910 self.sComment += sLine; 3555 3911 3912 # No slash, but check if this is a macro #define or #undef, since we 3913 # need to be able to selectively expand the ones containing MC blocks. 3914 elif self.iState == self.kiCode and sLine.lstrip().startswith('#'): 3915 if self.fDebugPreProc: 3916 self.debug('line %d: pre-proc' % (self.iLine,)); 3917 self.checkPreProcessorDirectiveForDefineUndef(sLine); 3918 3556 3919 # No slash, but check code line for relevant macro. 3557 elif self.iState == self.kiCode and sLine.find('IEMOP_') >= 0: 3920 elif ( self.iState == self.kiCode 3921 and (sLine.find('IEMOP_') >= 0 or sLine.find('FNIEMOPRM_DEF') >= 0 or sLine.find('IEM_MC') >= 0)): 3558 3922 #self.debug('line %d: macro' % (self.iLine,)); 3559 self.checkCodeForMacro(sLine );3923 self.checkCodeForMacro(sLine, 0); 3560 3924 3561 3925 # If the line is a '}' in the first position, complete the instructions. 3562 3926 elif self.iState == self.kiCode and sLine[0] == '}': 3563 3927 #self.debug('line %d: }' % (self.iLine,)); 3564 self.doneInstructions( );3928 self.doneInstructions(fEndOfFunction = True); 3565 3929 3566 3930 # Look for instruction table on the form 'IEM_STATIC const PFNIEMOP g_apfnVexMap3' … … 3569 3933 self.parseFunctionTable(sLine); 3570 3934 3571 self.doneInstructions( );3572 self.debug('%3s%% / %3s stubs out of %4s instructions in %s'3573 % (self.cTotalStubs * 100 // self.cTotalInstr, self.cTotalStubs, self.cTotalInstr, 3935 self.doneInstructions(fEndOfFunction = True); 3936 self.debug('%3s%% / %3s stubs out of %4s instructions and %4s MC blocks in %s' 3937 % (self.cTotalStubs * 100 // self.cTotalInstr, self.cTotalStubs, self.cTotalInstr, self.cTotalMcBlocks, 3574 3938 os.path.basename(self.sSrcFile),)); 3575 3939 return self.printErrors(); … … 3584 3948 # 3585 3949 try: 3586 oFile = open(sSrcFile, "r"); # pylint: disable=consider-using-with 3950 oFile = open(sSrcFile, "r"); # pylint: disable=consider-using-with,unspecified-encoding 3587 3951 except Exception as oXcpt: 3588 3952 raise Exception("failed to open %s for reading: %s" % (sSrcFile, oXcpt,)); … … 3598 3962 # 3599 3963 try: 3600 cErrors = SimpleParser(sSrcFile, asLines, sDefaultMap).parse(); 3964 oParser = SimpleParser(sSrcFile, asLines, sDefaultMap); 3965 return (oParser.parse(), oParser) ; 3601 3966 except ParserException as oXcpt: 3602 print(str(oXcpt) );3967 print(str(oXcpt), file = sys.stderr); 3603 3968 raise; 3604 3605 return cErrors;3606 3969 3607 3970 … … 3649 4012 ## List of all main instruction files and their default maps. 3650 4013 g_aasAllInstrFilesAndDefaultMap = ( 4014 ( 'IEMAllInstructionsCommon.cpp.h', 'one', ), 3651 4015 ( 'IEMAllInstructionsOneByte.cpp.h', 'one', ), 3652 4016 ( 'IEMAllInstructionsTwoByte0f.cpp.h', 'two0f', ), … … 3659 4023 ); 3660 4024 3661 def parseAll():4025 def __parseFilesWorker(asFilesAndDefaultMap): 3662 4026 """ 3663 4027 Parses all the IEMAllInstruction*.cpp.h files. 3664 4028 4029 Returns a list of the parsers on success. 3665 4030 Raises exception on failure. 3666 4031 """ 3667 sSrcDir = os.path.dirname(os.path.abspath(__file__)); 3668 cErrors = 0; 3669 for sName, sDefaultMap in g_aasAllInstrFilesAndDefaultMap: 3670 cErrors += __parseFileByName(os.path.join(sSrcDir, sName), sDefaultMap); 4032 sSrcDir = os.path.dirname(os.path.abspath(__file__)); 4033 cErrors = 0; 4034 aoParsers = []; 4035 for sFilename, sDefaultMap in asFilesAndDefaultMap: 4036 if not os.path.split(sFilename)[0] and not os.path.exists(sFilename): 4037 sFilename = os.path.join(sSrcDir, sFilename); 4038 cThisErrors, oParser = __parseFileByName(sFilename, sDefaultMap); 4039 cErrors += cThisErrors; 4040 aoParsers.append(oParser); 3671 4041 cErrors += __doTestCopying(); 3672 4042 cErrors += __applyOnlyTest(); … … 3676 4046 for oInstr in g_aoAllInstructions: 3677 4047 cTotalStubs += oInstr.fStub; 3678 print('debug: %3s%% / %3s stubs out of %4s instructions in total' 3679 % (cTotalStubs * 100 // len(g_aoAllInstructions), cTotalStubs, len(g_aoAllInstructions),)); 4048 print('debug: %3s%% / %3s stubs out of %4s instructions and %4s MC blocks in total' 4049 % (cTotalStubs * 100 // len(g_aoAllInstructions), cTotalStubs, len(g_aoAllInstructions), len(g_aoMcBlocks),), 4050 file = sys.stderr); 3680 4051 3681 4052 if cErrors != 0: 3682 4053 raise Exception('%d parse errors' % (cErrors,)); 3683 return True; 3684 4054 return aoParsers; 4055 4056 4057 def parseFiles(asFiles): 4058 """ 4059 Parses a selection of IEMAllInstruction*.cpp.h files. 4060 4061 Returns a list of the parsers on success. 4062 Raises exception on failure. 4063 """ 4064 # Look up default maps for the files and call __parseFilesWorker to do the job. 4065 asFilesAndDefaultMap = []; 4066 for sFilename in asFiles: 4067 sName = os.path.split(sFilename)[1].lower(); 4068 sMap = None; 4069 for asCur in g_aasAllInstrFilesAndDefaultMap: 4070 if asCur[0].lower() == sName: 4071 sMap = asCur[1]; 4072 break; 4073 if not sMap: 4074 raise Exception('Unable to classify file: %s' % (sFilename,)); 4075 asFilesAndDefaultMap.append((sFilename, sMap)); 4076 4077 return __parseFilesWorker(asFilesAndDefaultMap); 4078 4079 4080 def parseAll(): 4081 """ 4082 Parses all the IEMAllInstruction*.cpp.h files. 4083 4084 Returns a list of the parsers on success. 4085 Raises exception on failure. 4086 """ 4087 return __parseFilesWorker(g_aasAllInstrFilesAndDefaultMap); 3685 4088 3686 4089 … … 3849 4252 except Exception as oXcpt: 3850 4253 print('error: parseAll failed: %s' % (oXcpt,), file = sys.stderr); 4254 traceback.print_exc(file = sys.stderr); 3851 4255 return 1; 3852 4256 … … 3872 4276 # 3873 4277 asHeaderLines = []; 3874 print("debug: maps=%s\n" % (', '.join([oMap.sName for oMap in aoDisasmMaps]),) );4278 print("debug: maps=%s\n" % (', '.join([oMap.sName for oMap in aoDisasmMaps]),), file = sys.stderr); 3875 4279 for oMap in aoDisasmMaps: 3876 4280 sName = oMap.sName;
Note:
See TracChangeset
for help on using the changeset viewer.