VirtualBox

Ignore:
Timestamp:
Mar 8, 2023 1:51:04 AM (22 months ago)
Author:
vboxsync
Message:

VMM/IEM: Started extending IEMAllInstructionsPython.py to pick up IEM_MC_BEGIN/END blocks and added a new script for generating the threaded functions and producing the modified IEMAllInstructions*.cpp.h files. Also added IEMAllInstructionsThreadedRecompiler.cpp. bugref:10369

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py

    r98842 r98873  
    4646__version__ = "$Revision$"
    4747
    48 # pylint: disable=anomalous-backslash-in-string
     48# pylint: disable=anomalous-backslash-in-string,too-many-lines
    4949
    5050# Standard python imports.
    51 import os
    52 import re
    53 import sys
     51import os;
     52import re;
     53import sys;
     54import traceback;
    5455
    5556## Only the main script needs to modify the path.
     
    17401741
    17411742
     1743class 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.
     1769g_aoMcBlocks = [] # type: list(McBlock)
     1770
     1771
     1772
    17421773class ParserException(Exception):
    17431774    """ Parser exception """
     
    17461777
    17471778
    1748 class SimpleParser(object):
     1779class SimpleParser(object): # pylint: disable=too-many-instance-attributes
    17491780    """
    17501781    Parser of IEMAllInstruction*.cpp.h instruction specifications.
     
    17561787    kiCommentMulti      = 1;
    17571788    ## @}
     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
    17581832
    17591833    def __init__(self, sSrcFile, asLines, sDefaultMap):
     
    17641838        self.sComment       = '';
    17651839        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.
    17671846
    17681847        assert sDefaultMap in g_dInstructionMaps;
     
    17721851        self.cTotalStubs    = 0;
    17731852        self.cTotalTagged   = 0;
     1853        self.cTotalMcBlocks = 0;
    17741854
    17751855        self.oReMacroName   = re.compile('^[A-Za-z_][A-Za-z0-9_]*$');
     
    17811861        self.oReFunTable    = re.compile('^(IEM_STATIC|static) +const +PFNIEMOP +g_apfn[A-Za-z0-9_]+ *\[ *\d* *\] *= *$');
    17821862        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
    17831869        self.fDebug         = True;
     1870        self.fDebugMc       = False;
     1871        self.fDebugPreProc  = False;
    17841872
    17851873        self.dTagHandlers   = {
     
    18761964        """
    18771965        if self.fDebug:
    1878             print('debug: %s' % (sMessage,));
     1966            print('debug: %s' % (sMessage,), file = sys.stderr);
    18791967
    18801968    def stripComments(self, sLine):
     
    21262214        return True;
    21272215
    2128     def doneInstructions(self, iLineInComment = None):
     2216    def doneInstructions(self, iLineInComment = None, fEndOfFunction = False):
    21292217        """
    21302218        Done with current instruction.
     
    21392227        self.sComment     = '';
    21402228        self.aoCurInstrs  = [];
     2229        if fEndOfFunction:
     2230            #self.debug('%s: sCurFunction=None' % (self.iLine, ));
     2231            self.sCurFunction   = None;
     2232            self.iMcBlockInFunc = 0;
    21412233        return True;
    21422234
     
    33853477                                          sForm, sUpper, sLower, sDisHints, sIemHints, asOperands);
    33863478
    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):
    33883542        """
    33893543        Checks code for relevant macro invocation.
     
    33963550            asArgs = self.findAndParseFirstMacroInvocation(sCode,
    33973551                                                           [ 'FNIEMOP_DEF',
     3552                                                             'FNIEMOPRM_DEF',
    33983553                                                             'FNIEMOP_STUB',
    33993554                                                             'FNIEMOP_STUB_1',
     
    34013556                                                             'FNIEMOP_UD_STUB_1' ]);
    34023557            if asArgs is not None:
    3403                 sFunction = asArgs[1];
     3558                self.sCurFunction = asArgs[1];
     3559                #self.debug('%s: sCurFunction=%s' % (self.iLine, self.sCurFunction,));
    34043560
    34053561                if not self.aoCurInstrs:
     
    34103566                    else:
    34113567                        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]);
    34133569                self.setInstrunctionAttrib('fStub', asArgs[0].find('STUB') > 0, fOverwrite = True);
    34143570                self.setInstrunctionAttrib('fUdStub', asArgs[0].find('UD_STUB') > 0, fOverwrite = True);
    34153571                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]));
    34173582                return True;
    34183583
     
    34383603            # IEMOP_MNEMONIC*
    34393604            #
    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;
    35003679
    35013680        return False;
    35023681
     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 :];
    35033841
    35043842    def parse(self):
     
    35133851            sLine = self.asLines[self.iLine];
    35143852            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.
    35183865            offSlash = sLine.find('/');
    35193866            if offSlash >= 0:
     
    35223869                    while offLine < len(sLine):
    35233870                        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
    35253881                            if offHit >= 0:
    3526                                 self.checkCodeForMacro(sLine[offLine:offHit]);
     3882                                self.checkCodeForMacro(sLine[offLine:offHit], offLine);
    35273883                                self.sComment     = '';
    35283884                                self.iCommentLine = self.iLine;
     
    35303886                                offLine = offHit + 2;
    35313887                            else:
    3532                                 self.checkCodeForMacro(sLine[offLine:]);
     3888                                self.checkCodeForMacro(sLine[offLine:], offLine);
    35333889                                offLine = len(sLine);
    35343890
     
    35473903                # C++ line comment.
    35483904                elif offSlash > 0:
    3549                     self.checkCodeForMacro(sLine[:offSlash]);
     3905                    self.checkCodeForMacro(sLine[:offSlash], 0);
    35503906
    35513907            # No slash, but append the line if in multi-line comment.
     
    35543910                self.sComment += sLine;
    35553911
     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
    35563919            # 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)):
    35583922                #self.debug('line %d: macro' % (self.iLine,));
    3559                 self.checkCodeForMacro(sLine);
     3923                self.checkCodeForMacro(sLine, 0);
    35603924
    35613925            # If the line is a '}' in the first position, complete the instructions.
    35623926            elif self.iState == self.kiCode and sLine[0] == '}':
    35633927                #self.debug('line %d: }' % (self.iLine,));
    3564                 self.doneInstructions();
     3928                self.doneInstructions(fEndOfFunction = True);
    35653929
    35663930            # Look for instruction table on the form 'IEM_STATIC const PFNIEMOP g_apfnVexMap3'
     
    35693933                self.parseFunctionTable(sLine);
    35703934
    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,
    35743938                      os.path.basename(self.sSrcFile),));
    35753939        return self.printErrors();
     
    35843948    #
    35853949    try:
    3586         oFile = open(sSrcFile, "r");    # pylint: disable=consider-using-with
     3950        oFile = open(sSrcFile, "r");    # pylint: disable=consider-using-with,unspecified-encoding
    35873951    except Exception as oXcpt:
    35883952        raise Exception("failed to open %s for reading: %s" % (sSrcFile, oXcpt,));
     
    35983962    #
    35993963    try:
    3600         cErrors = SimpleParser(sSrcFile, asLines, sDefaultMap).parse();
     3964        oParser = SimpleParser(sSrcFile, asLines, sDefaultMap);
     3965        return (oParser.parse(), oParser) ;
    36013966    except ParserException as oXcpt:
    3602         print(str(oXcpt));
     3967        print(str(oXcpt), file = sys.stderr);
    36033968        raise;
    3604 
    3605     return cErrors;
    36063969
    36073970
     
    36494012## List of all main instruction files and their default maps.
    36504013g_aasAllInstrFilesAndDefaultMap = (
     4014    ( 'IEMAllInstructionsCommon.cpp.h',    'one',        ),
    36514015    ( 'IEMAllInstructionsOneByte.cpp.h',   'one',        ),
    36524016    ( 'IEMAllInstructionsTwoByte0f.cpp.h', 'two0f',      ),
     
    36594023);
    36604024
    3661 def parseAll():
     4025def __parseFilesWorker(asFilesAndDefaultMap):
    36624026    """
    36634027    Parses all the IEMAllInstruction*.cpp.h files.
    36644028
     4029    Returns a list of the parsers on success.
    36654030    Raises exception on failure.
    36664031    """
    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);
    36714041    cErrors += __doTestCopying();
    36724042    cErrors += __applyOnlyTest();
     
    36764046    for oInstr in g_aoAllInstructions:
    36774047        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);
    36804051
    36814052    if cErrors != 0:
    36824053        raise Exception('%d parse errors' % (cErrors,));
    3683     return True;
    3684 
     4054    return aoParsers;
     4055
     4056
     4057def 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
     4080def 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);
    36854088
    36864089
     
    38494252    except Exception as oXcpt:
    38504253        print('error: parseAll failed: %s' % (oXcpt,), file = sys.stderr);
     4254        traceback.print_exc(file = sys.stderr);
    38514255        return 1;
    38524256
     
    38724276    #
    38734277    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);
    38754279    for oMap in aoDisasmMaps:
    38764280        sName = oMap.sName;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette