VirtualBox

Changeset 108952 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Apr 11, 2025 11:20:09 PM (4 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168470
Message:

VMM/IEM: Fixes and tweaks. jiraref:VBP-1598

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/target-armv8/bsd-spec-analyze.py

    r108945 r108952  
    353353
    354354
     355
    355356#
    356357# The ARM instruction AST stuff.
     
    510511    def clone(self):
    511512        return ArmAstBinaryOp(self.oLeft.clone(), self.sOp, self.oRight.clone());
     513
     514    def isSame(self, oOther):
     515        if isinstance(oOther, ArmAstBinaryOp):
     516            if self.sOp == oOther.sOp:
     517                if self.oLeft.isSame(oOther.oLeft):
     518                    if self.oRight.isSame(oOther.oRight):
     519                        return True;
     520            ## @todo switch sides and whatnot.
     521        return False;
    512522
    513523    @staticmethod
     
    603613        return ArmAstUnaryOp(self.sOp, self.oExpr.clone());
    604614
     615    def isSame(self, oOther):
     616        if isinstance(oOther, ArmAstUnaryOp):
     617            if self.sOp == oOther.sOp:
     618                if self.oExpr.isSame(oOther.oExpr):
     619                    return True;
     620        return False;
     621
    605622    @staticmethod
    606623    def needParentheses(oNode):
     
    628645        return ArmAstSquareOp(self.oVar.clone(), [oValue.clone() for oValue in self.aoValues]);
    629646
     647    def isSame(self, oOther):
     648        if isinstance(oOther, ArmAstSquareOp):
     649            if self.oVar.isSame(oOther.oVar):
     650                if len(self.aoValues) == len(oOther.aoValues):
     651                    for idx, oMyValue in enumerate(self.aoValues):
     652                        if not oMyValue.isSame(oOther.aoValues[idx]):
     653                            return False;
     654                    return True;
     655        return False;
     656
    630657    def toString(self):
    631658        return '%s<%s>' % (self.oVar.toString(), ','.join([oValue.toString() for oValue in self.aoValues]),);
     
    643670    def clone(self):
    644671        return ArmAstConcat([oValue.clone() for oValue in self.aoValues]);
     672
     673    def isSame(self, oOther):
     674        if isinstance(oOther, ArmAstConcat):
     675            if len(self.aoValues) == len(oOther.aoValues):
     676                for idx, oMyValue in enumerate(self.aoValues):
     677                    if not oMyValue.isSame(oOther.aoValues[idx]):
     678                        return False;
     679                return True;
     680        return False;
    645681
    646682    def toString(self):
     
    685721        return ArmAstFunction(self.sName, [oArg.clone() for oArg in self.aoArgs]);
    686722
     723    def isSame(self, oOther):
     724        if isinstance(oOther, ArmAstFunction):
     725            if self.sName == oOther.sName:
     726                if len(self.aoArgs) == len(oOther.aoArgs):
     727                    for idx, oMyArg in enumerate(self.aoArgs):
     728                        if not oMyArg.isSame(oOther.aoArgs[idx]):
     729                            return False;
     730                    return True;
     731        return False;
     732
    687733    def toString(self):
    688734        return '%s(%s)' % (self.sName, ','.join([oArg.toString() for oArg in self.aoArgs]),);
     
    702748    def clone(self):
    703749        return ArmAstIdentifier(self.sName);
     750
     751    def isSame(self, oOther):
     752        if isinstance(oOther, ArmAstIdentifier):
     753            if self.sName == oOther.sName:
     754                return True;
     755        return False;
    704756
    705757    def toString(self):
     
    720772        return ArmAstBool(self.fValue);
    721773
     774    def isSame(self, oOther):
     775        if isinstance(oOther, ArmAstBase):
     776            if self.fValue == oOther.fValue:
     777                return True;
     778        return False;
     779
    722780    def toString(self):
    723781        return 'true' if self.fValue is True else 'false';
     
    726784        _ = oHelper;
    727785        return 'true' if self.fValue is True else 'false';
     786
    728787
    729788class ArmAstInteger(ArmAstBase):
     
    734793    def clone(self):
    735794        return ArmAstInteger(self.iValue);
     795
     796    def isSame(self, oOther):
     797        if isinstance(oOther, ArmAstInteger):
     798            if self.iValue == oOther.iValue:
     799                return True;
     800        return False;
    736801
    737802    def toString(self):
     
    746811        return '%#x' % (self.iValue,);
    747812
     813
    748814class ArmAstSet(ArmAstBase):
    749815    def __init__(self, aoValues):
     
    754820        return ArmAstSet([oValue.clone() for oValue in self.aoValues]);
    755821
     822    def isSame(self, oOther):
     823        if isinstance(oOther, ArmAstSet):
     824            if len(self.aoValues) == len(oOther.aoValues):
     825                for idx, oMyValue in enumerate(self.aoValues):
     826                    if not oMyValue.isSame(oOther.aoValues[idx]):
     827                        return False;
     828                return True;
     829        return False;
     830
    756831    def toString(self):
    757832        return '(%s)' % (', '.join([oValue.toString() for oValue in self.aoValues]),);
     
    760835        _ = oHelper;
    761836        raise Exception('ArmAstSet does not support conversion to C expression: %s' % (self.toString()));
     837
    762838
    763839class ArmAstValue(ArmAstBase):
     
    768844    def clone(self):
    769845        return ArmAstValue(self.sValue);
     846
     847    def isSame(self, oOther):
     848        if isinstance(oOther, ArmAstValue):
     849            if self.sValue == oOther.sValue:
     850                return True;
     851        return False;
    770852
    771853    def toString(self):
     
    899981        self.sName           = sName;
    900982        self.oParent         = oParent;
    901         self.aoFields        = aoFields;
    902         self.fFields         = fFields;  ##< Not necessarily correct for Instructions!
     983        self.aoFields        = aoFields     # type: List[ArmEncodesetField]
     984        self.fFields         = fFields;
    903985        self.oCondition      = oCondition;
    904986
     
    11331215## The instruction groups.
    11341216g_dArmInstructionGroups = {}                                    # type: Dict[ArmInstructionGroup]
     1217
     1218
     1219## Instruction corrections expressed as a list required conditionals.
     1220#
     1221# In addition to supplying missing conditionals (IsFeatureImplemented(FEAT_XXX)
     1222# and missing fixed encoding values (field == <fixed-value>).
     1223#
     1224# The reason why this is a list and not an expression, is that it easier to skip
     1225# stuff that's already present in newer specification and avoiding duplicate tests.
     1226g_dArmEncodingCorrectionConditions = {
     1227    # The sdot and udot vector instructions are missing the 'size' restrictions in the 2024-12 specs.
     1228    'sdot_z_zzz_': (ArmAstBinaryOp(ArmAstIdentifier('size'), '!=', ArmAstValue("'00'")),
     1229                    ArmAstBinaryOp(ArmAstIdentifier('size'), '!=', ArmAstValue("'01'")),),
     1230    'udot_z_zzz_': (ArmAstBinaryOp(ArmAstIdentifier('size'), '!=', ArmAstValue("'00'")),
     1231                    ArmAstBinaryOp(ArmAstIdentifier('size'), '!=', ArmAstValue("'01'")),),
     1232    # These instructions are FEAT_MTE && FEAT_MOPS. The 2024-12 specs missed the former condition.
     1233    'SETGEN_SET_memcms':  (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1234    'SETGETN_SET_memcms': (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1235    'SETGET_SET_memcms':  (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1236    'SETGE_SET_memcms':   (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1237    'SETGMN_SET_memcms':  (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1238    'SETGMTN_SET_memcms': (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1239    'SETGMT_SET_memcms':  (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1240    'SETGM_SET_memcms':   (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1241    'SETGPN_SET_memcms':  (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1242    'SETGPTN_SET_memcms': (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1243    'SETGPT_SET_memcms':  (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1244    'SETGP_SET_memcms':   (ArmAstFunction('IsFeatureImplemented', [ArmAstIdentifier('FEAT_MTE'),]),),
     1245
     1246    ## @todo fexpa_z_z: s/FEAT_SME2p2/FEAT_SSVE_FEXPA/ (2024-12 vs 2025-03); Not relevant since we don't support either.
     1247};
    11351248
    11361249
     
    12521365
    12531366            oCondition = ArmAstBase.fromJson(oJson['condition']);
     1367            aoCorrectionConditions = g_dArmEncodingCorrectionConditions.get(sInstrNm)
     1368            if aoCorrectionConditions:
     1369                oCondition = addAndConditionsFromList(oCondition, aoCorrectionConditions);
    12541370
    12551371            (aoFields, fFields) = ArmEncodesetField.encodesetFromJson(oJson['encoding']);
     
    12671383            (oCondition, fMod) = transferConditionsToEncoding(oCondition, aoFields, collections.defaultdict(list), sInstrNm);
    12681384            #if fMod:
    1269             #    print('debug transfer: %s: %s  ---->  %s' % (sInstrNm, sCondBefore, oCondition.toString()));
     1385            #    print('debug transfer: %s: %s' % (sInstrNm, sCondBefore,));
     1386            #    print('              %*s %s' % (len(sInstrNm) + 3, '--->', oCondition.toString(),));
    12701387            _ = fMod;
    12711388
     
    13001417
    13011418    return True;
     1419
     1420
     1421def addAndConditionsFromList(oTree, aoAndConditions):
     1422    """
     1423    Adds the conditions in aoAndConditions that are not already present in
     1424    oTree in an required (AND) form.
     1425
     1426    This is used when we add corrections, so that we avoid duplicate feature
     1427    checks and such.
     1428    """
     1429    if oTree.isBoolAndTrue():
     1430        return andConditionListToTree(aoAndConditions);
     1431
     1432    def isAndConditionPresent(oTree, oAndCondition):
     1433        if oAndCondition.isSame(oTree):
     1434            return True;
     1435        if isinstance(oTree, ArmAstBinaryOp) and oTree.sOp == '&&':
     1436            return isAndConditionPresent(oTree.oLeft, oAndCondition) or isAndConditionPresent(oTree.oRight, oAndCondition);
     1437        return False;
     1438
     1439    aoToAdd = [oTree,];
     1440    for oAndCondition in aoAndConditions:
     1441        if not isAndConditionPresent(oTree, oAndCondition):
     1442            aoToAdd.append(oAndCondition);
     1443
     1444    return andConditionListToTree(aoToAdd);
     1445
     1446
     1447def andConditionListToTree(aoAndConditions):
     1448    """ Creates AST tree of AND binary checks from aoAndConditions. """
     1449    if len(aoAndConditions) <= 1:
     1450        return aoAndConditions[0].clone();
     1451    return ArmAstBinaryOp(aoAndConditions[0].clone(), '&&', andConditionListToTree(aoAndConditions[1:]));
     1452
    13021453
    13031454def transferConditionsToEncoding(oCondition, aoFields, dPendingNotEq, sInstrNm, uDepth = 0, fMod = False):
     
    13381489                for oField in aoFields: # ArmEncodesetField
    13391490                    if oField.sName and oField.sName == sFieldName:
    1340                         # ArmAstInteger (unlikely):
     1491                        # ArmAstInteger - not used by spec, only corrections:
    13411492                        if isinstance(oValue, ArmAstInteger):
    13421493                            if oField.fFixed != 0:
     
    13571508                                break;
    13581509
    1359                             #print('debug transfer: %s: integer binaryop -> encoding: %s %s %#x/%#x'
    1360                             #      % (sInstrNm, oField.sName, oCondition.sOp, oValue.iValue, fFixed));
     1510                            print('debug transfer: %s: integer binaryop -> encoding: %s %s %#x/%#x'
     1511                                  % (sInstrNm, oField.sName, oCondition.sOp, oValue.iValue, fFixed));
    13611512                            if oCondition.sOp == '==':
    13621513                                oField.fValue = oValue.iValue;
     
    13951546                if oCondition.sOp == '&&':
    13961547                    oCondition.oLeft  = recursiveRemove(oCondition.oLeft, aoToRemove);
    1397                     oCondition.oRight = recursiveRemove(oCondition.oLeft, aoToRemove);
     1548                    oCondition.oRight = recursiveRemove(oCondition.oRight, aoToRemove);
    13981549                    if oCondition.oLeft.isBoolAndTrue():    return oCondition.oRight;
    13991550                    if oCondition.oRight.isBoolAndTrue():   return oCondition.oLeft;
     
    14271578                    oField.fFixed |= fFixed;
    14281579
    1429 
    14301580                    # Remove the associated conditions (they'll be leaves).
    14311581                    oCondition = recursiveRemove(oCondition, [oCondition for _, _, _, oCondition in atOccurences]);
     
    14951645    #print("oBrk=%s" % (oBrk,))
    14961646
    1497     if oOptions.fPrintInstructions:
     1647    if oOptions.fPrintInstructions or oOptions.fPrintInstructionsWithEncoding or oOptions.fPrintInstructionsWithConditions:
    14981648        for oInstr in g_aoAllArmInstructions:
    14991649            print('%08x/%08x %s %s' % (oInstr.fFixedMask, oInstr.fFixedValue, oInstr.getCName(), oInstr.sAsmDisplay));
     1650            if oOptions.fPrintInstructionsWithEncoding:
     1651                for oField in sorted(oInstr.aoFields, key = operator.attrgetter('iFirstBit')): # ArmEncodesetField
     1652                    print('  %2u L %2u: %010x/%010x%s%s'
     1653                          % (oField.iFirstBit, oField.cBitsWidth, oField.fFixed, oField.fValue,
     1654                             ' ' if oField.sName else '', oField.sName if oField.sName else '',));
     1655            if oOptions.fPrintInstructionsWithConditions and not oInstr.oCondition.isBoolAndTrue():
     1656                print('  condition: %s' % (oInstr.oCondition.toString(),));
    15001657
    15011658    # Gather stats on fixed bits:
     
    21452302        Returns the lines for a license header.
    21462303        """
     2304        sDashYear = '-%s' % datetime.date.today().year;
     2305        if sDashYear == '-2025':
     2306            sDashYear = '';
    21472307        return [
    21482308            '/*',
     
    21562316            '',
    21572317            '/*',
    2158             ' * Copyright (C) 2025-' + str(datetime.date.today().year) + ' Oracle and/or its affiliates.',
     2318            ' * Copyright (C) 2025' + sDashYear + ' Oracle and/or its affiliates.',
    21592319            ' *',
    21602320            ' * This file is part of VirtualBox base platform packages, as',
     
    22932453                ];
    22942454                asTail  = [
    2295                     '    LogFlow(("Invalid instruction %%#x at %%x\\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));',
     2455                    '    Log(("Invalid instruction %%#x at %%x\\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));',
    22962456                    '    IEMOP_RAISE_INVALID_OPCODE_RET();',
    22972457                    '}',
     
    23212481
    23222482                asTail = [
    2323                     sIndent + '    LogFlow(("Invalid instruction %%#x at %%x (cond)\\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));',
     2483                    sIndent + '    Log(("Invalid instruction %%#x at %%x (cond)\\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));',
    23242484                    sIndent + '    IEMOP_RAISE_INVALID_OPCODE_RET();',
    23252485                    sIndent + '}',
     
    23292489            # Log and call implementation.
    23302490            asLines += [
    2331                 '%s    LogFlow(("%%010x: %s%s\\n",%s));' % (sIndent, sCName, sLogFmt, ', '.join(['uOpcode',] + asArgs),),
     2491                '%s    LogFlow(("%%018x/%%010x: %s%s\\n", %s));'
     2492                % (sIndent, sCName, sLogFmt, ', '.join(['pVCpu->cpum.GstCtx.Pc.u64', 'uOpcode',] + asArgs),),
    23322493                '#ifdef IEM_INSTR_IMPL_%s__%s' % (sInstrSet, sCName,),
    23332494                '%s    IEM_INSTR_IMPL_%s__%s(%s);' % (sIndent, sInstrSet, sCName, ', '.join(asArgs),),
     
    24862647            'FNIEMOP_DEF_1(iemDecode%s_Invalid, uint32_t, uOpcode)' % (sInstrSet,),
    24872648            '{',
    2488             '    LogFlow(("Invalid instruction %%#x at %%x\\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));',
     2649            '    Log(("Invalid instruction %%#x at %%x\\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));',
    24892650            '    IEMOP_RAISE_INVALID_OPCODE_RET();',
    24902651            '}',
     
    25832744                                dest    = 'sFileDecoderCpp',
    25842745                                action  = 'store',
    2585                                 default = '-',
     2746                                default = None,
    25862747                                help    = 'The output C++ file for the decoder.');
    25872748        oArgParser.add_argument('--out-decoder-hdr',
     
    25892750                                dest    = 'sFileDecoderHdr',
    25902751                                action  = 'store',
    2591                                 default = '-',
     2752                                default = None,
    25922753                                help    = 'The output header file for the decoder.');
    25932754        oArgParser.add_argument('--out-stub-hdr',
     
    25952756                                dest    = 'sFileStubHdr',
    25962757                                action  = 'store',
    2597                                 default = '-',
     2758                                default = None,
    25982759                                help    = 'The output header file for the implementation stubs.');
    25992760        # debug:
     
    26032764                                default = False,
    26042765                                help    = 'List the instructions after loading.');
     2766        oArgParser.add_argument('--print-instructions-with-conditions',
     2767                                dest    = 'fPrintInstructionsWithConditions',
     2768                                action  = 'store_true',
     2769                                default = False,
     2770                                help    = 'List the instructions and conditions after loading.');
     2771        oArgParser.add_argument('--print-instructions-with-encoding',
     2772                                dest    = 'fPrintInstructionsWithEncoding',
     2773                                action  = 'store_true',
     2774                                default = False,
     2775                                help    = 'List the instructions and encoding details after loading.');
    26052776        oArgParser.add_argument('--print-fixed-mask-stats',
    26062777                                dest    = 'fPrintFixedMaskStats',
     
    26212792        if LoadArmOpenSourceSpecification(oOptions):
    26222793            #
    2623             # Sort out the decoding.
    2624             #
    2625             self.constructDecoder();
    2626 
    2627             #
    2628             # Output.
     2794            # Check if we're generating any output before constructing the decoder.
    26292795            #
    26302796            aaoOutputFiles = [
     
    26332799                 ( oOptions.sFileStubHdr,         self.generateA64ImplementationStubHdr, 0, ),
    26342800            ];
     2801
     2802            cOutputFiles = 0;
     2803            for sOutFile, _, _ in aaoOutputFiles:
     2804                cOutputFiles += sOutFile is not None;
     2805
    26352806            fRc = True;
    2636             for sOutFile, fnGenMethod, iPartNo in aaoOutputFiles:
    2637                 if sOutFile == '-':
    2638                     oOut = sys.stdout;
    2639                 else:
    2640                     try:
    2641                         oOut = open(sOutFile, 'w');                 # pylint: disable=consider-using-with,unspecified-encoding
    2642                     except Exception as oXcpt:
    2643                         print('error! Failed open "%s" for writing: %s' % (sOutFile, oXcpt,), file = sys.stderr);
    2644                         return 1;
    2645 
    2646                 (fRc2, asLines) = fnGenMethod(sOutFile, iPartNo);
    2647                 fRc = fRc2 and fRc;
    2648 
    2649                 oOut.write('\n'.join(asLines));
    2650                 if oOut != sys.stdout:
    2651                     oOut.close();
     2807            if cOutputFiles > 0:
     2808                #
     2809                # Sort out the decoding.
     2810                #
     2811                self.constructDecoder();
     2812
     2813                #
     2814                # Output.
     2815                #
     2816                for sOutFile, fnGenMethod, iPartNo in aaoOutputFiles:
     2817                    if not sOutFile:
     2818                        continue;
     2819                    if sOutFile == '-':
     2820                        oOut = sys.stdout;
     2821                    else:
     2822                        try:
     2823                            oOut = open(sOutFile, 'w');                 # pylint: disable=consider-using-with,unspecified-encoding
     2824                        except Exception as oXcpt:
     2825                            print('error! Failed open "%s" for writing: %s' % (sOutFile, oXcpt,), file = sys.stderr);
     2826                            return 1;
     2827
     2828                    (fRc2, asLines) = fnGenMethod(sOutFile, iPartNo);
     2829                    fRc = fRc2 and fRc;
     2830
     2831                    oOut.write('\n'.join(asLines));
     2832                    if oOut != sys.stdout:
     2833                        oOut.close();
    26522834            if fRc:
    26532835                return 0;
Note: See TracChangeset for help on using the changeset viewer.

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