VirtualBox

Changeset 98910 in vbox for trunk/src


Ignore:
Timestamp:
Mar 11, 2023 1:59:59 AM (22 months ago)
Author:
vboxsync
Message:

VMM/IEM: More work on processing MC blocks. bugref:10369

Location:
trunk/src/VBox/VMM
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsCommon.cpp.h

    r98797 r98910  
    986986                IEM_MC_CALL_VOID_AIMPL_3(pImpl->pfnNormalU32, pu32Dst, u32Src, pEFlags);
    987987
    988                 if ((pImpl != &g_iemAImpl_test) && (pImpl != &g_iemAImpl_cmp))
     988                if (pImpl != &g_iemAImpl_test && pImpl != &g_iemAImpl_cmp)
    989989                    IEM_MC_CLEAR_HIGH_GREG_U64_BY_REF(pu32Dst);
    990990                IEM_MC_ADVANCE_RIP_AND_FINISH();
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsPython.py

    r98905 r98910  
    17481748    Statement in a microcode block.
    17491749    """
    1750 
    17511750    def __init__(self, sName, asParams):
    17521751        self.sName    = sName;     ##< 'IEM_MC_XXX' or 'C++'.
     
    17721771
    17731772class McStmtCond(McStmt):
    1774     """ Base class for conditional statements (IEM_MC_IF_XXX). """
    1775 
     1773    """
     1774    Base class for conditional statements (IEM_MC_IF_XXX).
     1775    """
    17761776    def __init__(self, sName, asParams):
    17771777        McStmt.__init__(self, sName, asParams);
     
    18051805        assert sRefType in ('none', 'local');
    18061806
     1807
     1808class McStmtCall(McStmt):
     1809    """ IEM_MC_CALL_* """
     1810    def __init__(self, sName, asParams, iFnParam, iRcNameParam = -1):
     1811        McStmt.__init__(self, sName, asParams);
     1812        self.idxFn       = iFnParam;
     1813        self.idxParams   = iFnParam + 1;
     1814        self.sFn         = asParams[iFnParam];
     1815        self.iRcName     = None if iRcNameParam < 0 else asParams[iRcNameParam];
     1816
    18071817class McCppGeneric(McStmt):
    18081818    """
    18091819    Generic C++/C statement.
    18101820    """
    1811 
    18121821    def __init__(self, sCode, fDecode, sName = 'C++'):
    18131822        McStmt.__init__(self, sName, [sCode,]);
     
    18471856    C++/C Preprocessor directive.
    18481857    """
    1849 
    18501858    def __init__(self, sCode):
    18511859        McCppGeneric.__init__(self, sCode, False, sName = 'C++/preproc');
     
    19581966        oSelf.checkStmtParamCount(sName, asParams, 3);
    19591967        return McStmtVar(sName, asParams, asParams[0], asParams[1], sConstValue = asParams[2]);
     1968
     1969    @staticmethod
     1970    def parseMcCallAImpl(oSelf, sName, asParams):
     1971        """ IEM_MC_CALL_AIMPL_3|4 """
     1972        cArgs = int(sName[-1]);
     1973        oSelf.checkStmtParamCount(sName, asParams, 2 + cArgs);
     1974        return McStmtCall(sName, asParams, 1, 0);
     1975
     1976    @staticmethod
     1977    def parseMcCallVoidAImpl(oSelf, sName, asParams):
     1978        """ IEM_MC_CALL_VOID_AIMPL_2|3 """
     1979        cArgs = int(sName[-1]);
     1980        oSelf.checkStmtParamCount(sName, asParams, 1 + cArgs);
     1981        return McStmtCall(sName, asParams, 0);
     1982
     1983    @staticmethod
     1984    def parseMcCallAvxAImpl(oSelf, sName, asParams):
     1985        """ IEM_MC_CALL_AVX_AIMPL_2|3 """
     1986        cArgs = int(sName[-1]);
     1987        oSelf.checkStmtParamCount(sName, asParams, 1 + cArgs);
     1988        return McStmtCall(sName, asParams, 0);
     1989
     1990    @staticmethod
     1991    def parseMcCallFpuAImpl(oSelf, sName, asParams):
     1992        """ IEM_MC_CALL_FPU_AIMPL_1|2|3 """
     1993        cArgs = int(sName[-1]);
     1994        oSelf.checkStmtParamCount(sName, asParams, 1 + cArgs);
     1995        return McStmtCall(sName, asParams, 0);
     1996
     1997    @staticmethod
     1998    def parseMcCallMmxAImpl(oSelf, sName, asParams):
     1999        """ IEM_MC_CALL_MMX_AIMPL_2|3 """
     2000        cArgs = int(sName[-1]);
     2001        oSelf.checkStmtParamCount(sName, asParams, 1 + cArgs);
     2002        return McStmtCall(sName, asParams, 0);
     2003
     2004    @staticmethod
     2005    def parseMcCallSseAImpl(oSelf, sName, asParams):
     2006        """ IEM_MC_CALL_SSE_AIMPL_2|3 """
     2007        cArgs = int(sName[-1]);
     2008        oSelf.checkStmtParamCount(sName, asParams, 1 + cArgs);
     2009        return McStmtCall(sName, asParams, 0);
     2010
     2011    @staticmethod
     2012    def parseMcCallCImpl(oSelf, sName, asParams):
     2013        """ IEM_MC_CALL_CIMPL_0|1|2|3|4|5 """
     2014        cArgs = int(sName[-1]);
     2015        oSelf.checkStmtParamCount(sName, asParams, 1 + cArgs);
     2016        return McStmtCall(sName, asParams, 0);
    19602017
    19612018    @staticmethod
     
    22622319                offNextEnd = sRawCode.find(';', offEnd + 1);
    22632320                fDecode    = (   sRawCode.find('IEM_OPCODE_', off, max(offEnd, offNextEnd)) >= 0
    2264                               or sRawCode.find('IEMOP_HLP_DONE_', off, max(offEnd, offNextEnd)) >= 0);
     2321                              or sRawCode.find('IEMOP_HLP_DONE_', off, max(offEnd, offNextEnd)) >= 0
     2322                              or sRawCode.find('IEMOP_HLP_DECODED_', off, offEnd) >= 0
     2323                              or sRawCode.find('IEMOP_HLP_RAISE_UD_IF_MISSING_GUEST_FEATURE', off, offEnd) >= 0
     2324                           );
    22652325
    22662326                if not oMatch:
     
    23742434    'IEM_MC_BSWAP_LOCAL_U64':                                    McBlock.parseMcGeneric,
    23752435    'IEM_MC_CALC_RM_EFF_ADDR':                                   McBlock.parseMcGeneric,
    2376     'IEM_MC_CALL_AIMPL_3':                                       McBlock.parseMcGeneric,
    2377     'IEM_MC_CALL_AIMPL_4':                                       McBlock.parseMcGeneric,
    2378     'IEM_MC_CALL_AVX_AIMPL_2':                                   McBlock.parseMcGeneric,
    2379     'IEM_MC_CALL_AVX_AIMPL_3':                                   McBlock.parseMcGeneric,
    2380     'IEM_MC_CALL_CIMPL_0':                                       McBlock.parseMcGeneric,
    2381     'IEM_MC_CALL_CIMPL_1':                                       McBlock.parseMcGeneric,
    2382     'IEM_MC_CALL_CIMPL_2':                                       McBlock.parseMcGeneric,
    2383     'IEM_MC_CALL_CIMPL_3':                                       McBlock.parseMcGeneric,
    2384     'IEM_MC_CALL_CIMPL_4':                                       McBlock.parseMcGeneric,
    2385     'IEM_MC_CALL_CIMPL_5':                                       McBlock.parseMcGeneric,
    2386     'IEM_MC_CALL_FPU_AIMPL_1':                                   McBlock.parseMcGeneric,
    2387     'IEM_MC_CALL_FPU_AIMPL_2':                                   McBlock.parseMcGeneric,
    2388     'IEM_MC_CALL_FPU_AIMPL_3':                                   McBlock.parseMcGeneric,
    2389     'IEM_MC_CALL_MMX_AIMPL_2':                                   McBlock.parseMcGeneric,
    2390     'IEM_MC_CALL_MMX_AIMPL_3':                                   McBlock.parseMcGeneric,
    2391     'IEM_MC_CALL_SSE_AIMPL_2':                                   McBlock.parseMcGeneric,
    2392     'IEM_MC_CALL_SSE_AIMPL_3':                                   McBlock.parseMcGeneric,
    2393     'IEM_MC_CALL_VOID_AIMPL_0':                                  McBlock.parseMcGeneric,
    2394     'IEM_MC_CALL_VOID_AIMPL_1':                                  McBlock.parseMcGeneric,
    2395     'IEM_MC_CALL_VOID_AIMPL_2':                                  McBlock.parseMcGeneric,
    2396     'IEM_MC_CALL_VOID_AIMPL_3':                                  McBlock.parseMcGeneric,
    2397     'IEM_MC_CALL_VOID_AIMPL_4':                                  McBlock.parseMcGeneric,
     2436    'IEM_MC_CALL_AIMPL_3':                                       McBlock.parseMcCallAImpl,
     2437    'IEM_MC_CALL_AIMPL_4':                                       McBlock.parseMcCallAImpl,
     2438    'IEM_MC_CALL_AVX_AIMPL_2':                                   McBlock.parseMcCallAvxAImpl,
     2439    'IEM_MC_CALL_AVX_AIMPL_3':                                   McBlock.parseMcCallAvxAImpl,
     2440    'IEM_MC_CALL_CIMPL_0':                                       McBlock.parseMcCallCImpl,
     2441    'IEM_MC_CALL_CIMPL_1':                                       McBlock.parseMcCallCImpl,
     2442    'IEM_MC_CALL_CIMPL_2':                                       McBlock.parseMcCallCImpl,
     2443    'IEM_MC_CALL_CIMPL_3':                                       McBlock.parseMcCallCImpl,
     2444    'IEM_MC_CALL_CIMPL_4':                                       McBlock.parseMcCallCImpl,
     2445    'IEM_MC_CALL_CIMPL_5':                                       McBlock.parseMcCallCImpl,
     2446    'IEM_MC_CALL_FPU_AIMPL_1':                                   McBlock.parseMcCallFpuAImpl,
     2447    'IEM_MC_CALL_FPU_AIMPL_2':                                   McBlock.parseMcCallFpuAImpl,
     2448    'IEM_MC_CALL_FPU_AIMPL_3':                                   McBlock.parseMcCallFpuAImpl,
     2449    'IEM_MC_CALL_MMX_AIMPL_2':                                   McBlock.parseMcCallMmxAImpl,
     2450    'IEM_MC_CALL_MMX_AIMPL_3':                                   McBlock.parseMcCallMmxAImpl,
     2451    'IEM_MC_CALL_SSE_AIMPL_2':                                   McBlock.parseMcCallSseAImpl,
     2452    'IEM_MC_CALL_SSE_AIMPL_3':                                   McBlock.parseMcCallSseAImpl,
     2453    'IEM_MC_CALL_VOID_AIMPL_0':                                  McBlock.parseMcCallVoidAImpl,
     2454    'IEM_MC_CALL_VOID_AIMPL_1':                                  McBlock.parseMcCallVoidAImpl,
     2455    'IEM_MC_CALL_VOID_AIMPL_2':                                  McBlock.parseMcCallVoidAImpl,
     2456    'IEM_MC_CALL_VOID_AIMPL_3':                                  McBlock.parseMcCallVoidAImpl,
     2457    'IEM_MC_CALL_VOID_AIMPL_4':                                  McBlock.parseMcCallVoidAImpl,
    23982458    'IEM_MC_CLEAR_EFL_BIT':                                      McBlock.parseMcGeneric,
    23992459    'IEM_MC_CLEAR_FSW_EX':                                       McBlock.parseMcGeneric,
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h

    r98904 r98910  
    1164411644                IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
    1164511645                IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
    11646                 if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSse2)
    11647                     return IEMOP_RAISE_INVALID_OPCODE();
     11646                IEMOP_HLP_RAISE_UD_IF_MISSING_GUEST_FEATURE(pVCpu, fSse2);
    1164811647
    1164911648                IEM_MC_FETCH_GREG_U32(u32Value, IEM_GET_MODRM_REG(pVCpu, bRm));
     
    1166011659                IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffDst, bRm, 0);
    1166111660                IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
    11662                 if (!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSse2)
    11663                     return IEMOP_RAISE_INVALID_OPCODE();
     11661                IEMOP_HLP_RAISE_UD_IF_MISSING_GUEST_FEATURE(pVCpu, fSse2);
    1166411662
    1166511663                IEM_MC_FETCH_GREG_U64(u64Value, IEM_GET_MODRM_REG(pVCpu, bRm));
  • trunk/src/VBox/VMM/VMMAll/IEMAllThreadedPython.py

    r98904 r98910  
    4848
    4949
     50g_kdTypeInfo = {
     51    # type name:    (cBits, fSigned,)
     52    'int8_t':       (    8,    True, ),
     53    'int16_t':      (   16,    True, ),
     54    'int32_t':      (   32,    True, ),
     55    'int64_t':      (   64,    True, ),
     56    'uint8_t':      (    8,   False, ),
     57    'uint16_t':     (   16,   False, ),
     58    'uint32_t':     (   32,   False, ),
     59    'uint64_t':     (   64,   False, ),
     60    'uintptr_t':    (   64,   False, ), # ASSUMES 64-bit host pointer size.
     61    'bool':         (    1,   False, ),
     62    'IEMMODE':      (    8,   False, ),
     63};
     64
     65g_kdIemFieldToType = {
     66    # Illegal ones:
     67    'offInstrNextByte':     ( None, ),
     68    'cbInstrBuf':           ( None, ),
     69    'pbInstrBuf':           ( None, ),
     70    'uInstrBufPc':          ( None, ),
     71    'cbInstrBufTotal':      ( None, ),
     72    'offCurInstrStart':     ( None, ),
     73    'cbOpcode':             ( None, ),
     74    'offOpcode':            ( None, ),
     75    'offModRm':             ( None, ),
     76    # Okay ones.
     77    'fPrefixes':            ( 'uint32_t', ),
     78    'uRexReg':              ( 'uint8_t', ),
     79    'uRexB':                ( 'uint8_t', ),
     80    'uRexIndex':            ( 'uint8_t', ),
     81    'iEffSeg':              ( 'uint8_t', ),
     82    'enmEffOpSize':         ( 'IEMMODE', ),
     83    'enmDefAddrMode':       ( 'IEMMODE', ),
     84    'enmEffAddrMode':       ( 'IEMMODE', ),
     85    'enmDefOpSize':         ( 'IEMMODE', ),
     86    'idxPrefix':            ( 'uint8_t', ),
     87    'uVex3rdReg':           ( 'uint8_t', ),
     88    'uVexLength':           ( 'uint8_t', ),
     89    'fEvexStuff':           ( 'uint8_t', ),
     90    'uFpuOpcode':           ( 'uint16_t', ),
     91};
     92
     93class ThreadedParamRef(object):
     94    """
     95    A parameter reference for a threaded function.
     96    """
     97
     98    def __init__(self, sOrgRef, sType, oStmt, iParam, offParam = 0):
     99        self.sUseExpr = '';                         ##< The expression for getting the parameter in the threaded function.
     100        self.sOrgRef  = sOrgRef;                    ##< The name / reference in the original code.
     101        self.sStdRef  = ''.join(sOrgRef.split());   ##< Normalized name to deal with spaces in macro invocations and such.
     102        self.sType    = sType;                      ##< The type (typically derived).
     103        self.oStmt    = oStmt;                      ##< The statement making the reference.
     104        self.iParam   = iParam;                     ##< The parameter containing the references.
     105        self.offParam = offParam;                   ##< The offset in the parameter of the reference.
     106
     107
    50108class ThreadedFunction(object):
    51109    """
     
    56114        self.oMcBlock               = oMcBlock  # type: IEMAllInstructionsPython.McBlock
    57115        ## Dictionary of local variables (IEM_MC_LOCAL[_CONST]) and call arguments (IEM_MC_ARG*).
    58         self.dVariables = {}           # type: dict(str,McStmtVar)
    59         ###
    60         #self.aoParams    = []          # type:
     116        self.dVariables  = {}           # type: dict(str,McStmtVar)
     117        ##
     118        self.aoParamRefs = []           # type: list(ThreadedParamRef)
     119        self.dParamRefs  = {}           # type: dict(str,list(ThreadedParamRef))
     120        self.cMinParams  = 0;           ##< Minimum number of parameters to the threaded function.
    61121
    62122    @staticmethod
     
    64124        """ Gets a dummy instance. """
    65125        return ThreadedFunction(iai.McBlock('null', 999999999, 999999999, 'nil', 999999999));
     126
     127    def raiseProblem(self, sMessage):
     128        """ Raises a problem. """
     129        raise Exception('%s:%s: error: %s' % (self.oMcBlock.sSrcFile, self.oMcBlock.iBeginLine, sMessage, ));
    66130
    67131    def getIndexName(self):
     
    72136            return 'kIemThreadedFunc_%s' % ( sName, );
    73137        return 'kIemThreadedFunc_%s_%s' % ( sName, self.oMcBlock.iInFunction, );
     138
     139    def analyzeReferenceToType(self, sRef):
     140        """
     141        Translates a variable or structure reference to a type.
     142        Returns type name.
     143        Raises exception if unable to figure it out.
     144        """
     145        ch0 = sRef[0];
     146        if ch0 == 'u':
     147            if sRef.startswith('u32'):
     148                return 'uint32_t';
     149            if sRef.startswith('u8') or sRef == 'uReg':
     150                return 'uint8_t';
     151            if sRef.startswith('u64'):
     152                return 'uint64_t';
     153            if sRef.startswith('u16'):
     154                return 'uint16_t';
     155        elif ch0 == 'b':
     156            return 'uint8_t';
     157        elif ch0 == 'f':
     158            return 'bool';
     159        elif ch0 == 'i':
     160            if sRef.startswith('i8'):
     161                return 'int8_t';
     162            if sRef.startswith('i16'):
     163                return 'int32_t';
     164            if sRef.startswith('i32'):
     165                return 'int32_t';
     166            if sRef.startswith('i64'):
     167                return 'int64_t';
     168            if sRef in ('iReg', 'iSegReg', 'iSrcReg', 'iDstReg'):
     169                return 'uint8_t';
     170        elif ch0 == 'p':
     171            if sRef.find('-') < 0:
     172                return 'uintptr_t';
     173            if sRef.startswith('pVCpu->iem.s.'):
     174                sField = sRef[len('pVCpu->iem.s.') : ];
     175                if sField in g_kdIemFieldToType:
     176                    if g_kdIemFieldToType[sField][0]:
     177                        return g_kdIemFieldToType[sField][0];
     178                    self.raiseProblem('Reference out-of-bounds decoder field: %s' % (sRef,));
     179        elif ch0 == 'G' and sRef.startswith('GCPtr'):
     180            return 'uint64_t';
     181        elif sRef == 'cShift': ## @todo risky
     182            return 'uint8_t';
     183        self.raiseProblem('Unknown reference: %s' % (sRef,));
     184        return None; # Shut up pylint 2.16.2.
     185
     186    def analyzeConsolidateThreadedParamRefs(self):
     187        """
     188        Consolidate threaded function parameter references into a dictionary
     189        with lists of the references to each variable/field.
     190        """
     191        # Gather unique parameters.
     192        self.dParamRefs = {};
     193        for oRef in self.aoParamRefs:
     194            if oRef.sStdRef not in self.dParamRefs:
     195                self.dParamRefs[oRef.sStdRef] = [oRef,];
     196            else:
     197                self.dParamRefs[oRef.sStdRef].append(oRef);
     198
     199        # Organize them by size too for the purpose of optimize them.
     200        dBySize = {}        # type: dict(str,str)
     201        for sStdRef, aoRefs in self.dParamRefs.items():
     202            cBits = g_kdTypeInfo[aoRefs[0].sType][0];
     203            assert(cBits <= 64);
     204            if cBits not in dBySize:
     205                dBySize[cBits] = [sStdRef,]
     206            else:
     207                dBySize[cBits].append(sStdRef);
     208
     209        # Pack the parameters as best as we can, starting with the largest ones
     210        # and ASSUMING a 64-bit parameter size.
     211        self.cMinParams = 0;
     212        offParam        = 0;
     213        for cBits in sorted(dBySize.keys(), reverse = True):
     214            for sStdRef in dBySize[cBits]:
     215                if offParam < 64:
     216                    offParam        += cBits;
     217                else:
     218                    self.cMinParams += 1;
     219                    offParam         = cBits;
     220                assert(offParam <= 64);
     221                _ = sStdRef;
     222        if offParam > 0:
     223            self.cMinParams += 1;
     224
     225        # Currently there are a few that requires 4 parameters, list these so we can figure out why:
     226        if self.cMinParams >= 4:
     227            print('debug: cMinParams=%s cRawParams=%s - %s:%d'
     228                  % (self.cMinParams, len(self.dParamRefs), self.oMcBlock.sSrcFile, self.oMcBlock.iBeginLine,));
     229
     230        return True;
     231
     232    ksHexDigits = '0123456789abcdefABCDEF';
     233
     234    def analyzeFindThreadedParamRefs(self, aoStmts):
     235        """
     236        Scans the statements for things that have to passed on to the threaded
     237        function (populates self.aoParamRefs).
     238        """
     239        for oStmt in aoStmts:
     240            # Some statements we can skip alltogether.
     241            if isinstance(oStmt, (iai.McStmtVar, iai.McCppPreProc)):
     242                continue;
     243            if not oStmt.asParams:
     244                continue;
     245            if oStmt.isCppStmt() and oStmt.fDecode:
     246                continue;
     247
     248            # Inspect the target of calls to see if we need to pass down a
     249            # function pointer or function table pointer for it to work.
     250            aiSkipParams = {};
     251            if isinstance(oStmt, iai.McStmtCall):
     252                if oStmt.sFn[0] == 'p':
     253                    self.aoParamRefs.append(ThreadedParamRef(oStmt.sFn, 'uintptr_t', oStmt, oStmt.idxFn));
     254                elif (    oStmt.sFn[0] != 'i'
     255                      and not oStmt.sFn.startswith('IEMTARGETCPU_EFL_BEHAVIOR_SELECT')
     256                      and not oStmt.sFn.startswith('IEM_SELECT_HOST_OR_FALLBACK') ):
     257                    self.raiseProblem('Bogus function name in %s: %s' % (oStmt.sName, oStmt.sFn,));
     258                aiSkipParams[oStmt.idxFn] = True;
     259
     260            # Check all the parameters for bogus references.
     261            for iParam, sParam in enumerate(oStmt.asParams):
     262                if iParam not in aiSkipParams  and  sParam not in self.dVariables:
     263                    # The parameter may contain a C expression, so we have to try
     264                    # extract the relevant bits, i.e. variables and fields while
     265                    # ignoring operators and parentheses.
     266                    offParam = 0;
     267                    while offParam < len(sParam):
     268                        # Is it the start of an C identifier? If so, find the end, but don't stop on field separators (->, .).
     269                        ch = sParam[offParam];
     270                        if ch.isalpha() or ch == '_':
     271                            offStart = offParam;
     272                            offParam += 1;
     273                            while offParam < len(sParam):
     274                                ch = sParam[offParam];
     275                                if not ch.isalnum() and ch != '_' and ch != '.':
     276                                    if ch != '-' or sParam[offParam + 1] != '>':
     277                                        # Special hack for the 'CTX_SUFF(pVM)' bit in pVCpu->CTX_SUFF(pVM)->xxxx:
     278                                        if (    ch == '('
     279                                            and sParam[offStart : offParam + len('(pVM)->')] == 'pVCpu->CTX_SUFF(pVM)->'):
     280                                            offParam += len('(pVM)->') - 1;
     281                                        else:
     282                                            break;
     283                                    offParam += 1;
     284                                offParam += 1;
     285                            sRef = sParam[offStart : offParam];
     286
     287                            # For register references, we pass the full register indexes instead as macros
     288                            # like IEM_GET_MODRM_REG implicitly references pVCpu->iem.s.uRexReg and the
     289                            # threaded function will be more efficient if we just pass the register index
     290                            # as a 4-bit param.
     291                            if (   sRef.startswith('IEM_GET_MODRM')
     292                                or sRef.startswith('IEM_GET_EFFECTIVE_VVVV') ):
     293                                offParam = iai.McBlock.skipSpacesAt(sParam, offParam, len(sParam));
     294                                if sParam[offParam] != '(':
     295                                    self.raiseProblem('Expected "(" following %s in "%s"' % (sRef, oStmt.renderCode(),));
     296                                (asMacroParams, offCloseParam) = iai.McBlock.extractParams(sParam, offParam);
     297                                if asMacroParams is None:
     298                                    self.raiseProblem('Unable to find ")" for %s in "%s"' % (sRef, oStmt.renderCode(),));
     299                                self.aoParamRefs.append(ThreadedParamRef(sRef, 'uint8_t', oStmt, iParam, offStart));
     300                                offParam = offCloseParam + 1;
     301
     302                            # We can skip known variables.
     303                            elif sRef in self.dVariables:
     304                                pass;
     305
     306                            # Skip certain macro invocations.
     307                            elif sRef in ('IEM_GET_HOST_CPU_FEATURES',
     308                                          'IEM_GET_GUEST_CPU_FEATURES',
     309                                          'IEM_IS_GUEST_CPU_AMD'):
     310                                offParam = iai.McBlock.skipSpacesAt(sParam, offParam, len(sParam));
     311                                if sParam[offParam] != '(':
     312                                    self.raiseProblem('Expected "(" following %s in "%s"' % (sRef, oStmt.renderCode(),));
     313                                (asMacroParams, offCloseParam) = iai.McBlock.extractParams(sParam, offParam);
     314                                if asMacroParams is None:
     315                                    self.raiseProblem('Unable to find ")" for %s in "%s"' % (sRef, oStmt.renderCode(),));
     316                                offParam = offCloseParam + 1;
     317                                while offParam < len(sParam) and (sParam[offParam].isalnum() or sParam[offParam] in '_.'):
     318                                    offParam += 1;
     319
     320                            # Skip constants, globals, types (casts), sizeof and macros.
     321                            elif (   sRef.startswith('IEM_OP_PRF_')
     322                                  or sRef.startswith('IEM_ACCESS_')
     323                                  or sRef.startswith('X86_GREG_')
     324                                  or sRef.startswith('X86_SREG_')
     325                                  or sRef.startswith('X86_EFL_')
     326                                  or sRef.startswith('X86_FSW_')
     327                                  or sRef.startswith('X86_FCW_')
     328                                  or sRef.startswith('g_')
     329                                  or sRef in ( 'int8_t',    'int16_t',    'int32_t',
     330                                               'INT8_C',    'INT16_C',    'INT32_C',    'INT64_C',
     331                                               'UINT8_C',   'UINT16_C',   'UINT32_C',   'UINT64_C',
     332                                               'UINT8_MAX', 'UINT16_MAX', 'UINT32_MAX', 'UINT64_MAX',
     333                                               'sizeof',    'NOREF',      'RT_NOREF',   'IEMMODE_64BIT' ) ):
     334                                pass;
     335
     336                            # Skip certain macro invocations.
     337                            # Any variable (non-field) and decoder fields in IEMCPU will need to be parameterized.
     338                            elif (   (    '.' not in sRef
     339                                      and '-' not in sRef
     340                                      and sRef not in ('pVCpu', ) )
     341                                  or iai.McBlock.koReIemDecoderVars.search(sRef) is not None):
     342                                self.aoParamRefs.append(ThreadedParamRef(sRef, self.analyzeReferenceToType(sRef),
     343                                                                         oStmt, iParam, offStart));
     344                        # Number.
     345                        elif ch.isdigit():
     346                            if (    ch == '0'
     347                                and offParam + 2 <= len(sParam)
     348                                and sParam[offParam + 1] in 'xX'
     349                                and sParam[offParam + 2] in self.ksHexDigits ):
     350                                offParam += 2;
     351                                while offParam < len(sParam) and sParam[offParam] in self.ksHexDigits:
     352                                    offParam += 1;
     353                            else:
     354                                while offParam < len(sParam) and sParam[offParam].isdigit():
     355                                    offParam += 1;
     356                        # Whatever else.
     357                        else:
     358                            offParam += 1;
     359
     360            # Traverse the branches of conditionals.
     361            if isinstance(oStmt, iai.McStmtCond):
     362                self.analyzeFindThreadedParamRefs(oStmt.aoIfBranch);
     363                self.analyzeFindThreadedParamRefs(oStmt.aoElseBranch);
     364        return True;
    74365
    75366    def analyzeFindVariablesAndCallArgs(self, aoStmts):
     
    103394        self.analyzeFindVariablesAndCallArgs(aoStmts);
    104395
    105 
    106         return True;
    107 
     396        # Now scan the code for variables and field references that needs to
     397        # be passed to the threaded function because they are related to the
     398        # instruction decoding.
     399        self.analyzeFindThreadedParamRefs(aoStmts);
     400        self.analyzeConsolidateThreadedParamRefs();
     401
     402        return True;
    108403
    109404    def generateInputCode(self):
     
    140435        # Wrap MC blocks into threaded functions and analyze these.
    141436        self.aoThreadedFuncs = [ThreadedFunction(oMcBlock) for oMcBlock in iai.g_aoMcBlocks];
     437        dRawParamCounts = {};
     438        dMinParamCounts = {};
    142439        for oThreadedFunction in self.aoThreadedFuncs:
    143440            oThreadedFunction.analyze();
     441            dRawParamCounts[len(oThreadedFunction.dParamRefs)] = dRawParamCounts.get(len(oThreadedFunction.dParamRefs), 0) + 1;
     442            dMinParamCounts[oThreadedFunction.cMinParams]      = dMinParamCounts.get(oThreadedFunction.cMinParams,      0) + 1;
     443        print('debug: param count distribution, raw and optimized:', file = sys.stderr);
     444        for cCount in sorted(list(dRawParamCounts.keys()) + list(set(dMinParamCounts.keys()) - set(dRawParamCounts.keys()))):
     445            print('debug:     %s params: %4s raw, %4s min'
     446                  % (cCount, dRawParamCounts.get(cCount, 0), dMinParamCounts.get(cCount, 0)),
     447                  file = sys.stderr);
    144448
    145449        return True;
  • trunk/src/VBox/VMM/include/IEMOpHlp.h

    r98103 r98910  
    591591    } while (0)
    592592
     593/**
     594 * Check for a CPUMFEATURES member to be true, raise \#UD if clear.
     595 */
     596#define IEMOP_HLP_RAISE_UD_IF_MISSING_GUEST_FEATURE(pVCpu, a_fFeature) \
     597    do \
     598    { \
     599        if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->a_fFeature) \
     600        { /* likely */ } \
     601        else \
     602            return IEMOP_RAISE_INVALID_OPCODE(); \
     603    } while (0)
     604
    593605VBOXSTRICTRC    iemOpHlpCalcRmEffAddr(PVMCPUCC pVCpu, uint8_t bRm, uint8_t cbImm, PRTGCPTR pGCPtrEff) RT_NOEXCEPT;
    594606VBOXSTRICTRC    iemOpHlpCalcRmEffAddrEx(PVMCPUCC pVCpu, uint8_t bRm, uint8_t cbImm, PRTGCPTR pGCPtrEff, int8_t offRsp) RT_NOEXCEPT;
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