Changeset 108952 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Apr 11, 2025 11:20:09 PM (4 weeks ago)
- svn:sync-xref-src-repo-rev:
- 168470
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/target-armv8/bsd-spec-analyze.py
r108945 r108952 353 353 354 354 355 355 356 # 356 357 # The ARM instruction AST stuff. … … 510 511 def clone(self): 511 512 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; 512 522 513 523 @staticmethod … … 603 613 return ArmAstUnaryOp(self.sOp, self.oExpr.clone()); 604 614 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 605 622 @staticmethod 606 623 def needParentheses(oNode): … … 628 645 return ArmAstSquareOp(self.oVar.clone(), [oValue.clone() for oValue in self.aoValues]); 629 646 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 630 657 def toString(self): 631 658 return '%s<%s>' % (self.oVar.toString(), ','.join([oValue.toString() for oValue in self.aoValues]),); … … 643 670 def clone(self): 644 671 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; 645 681 646 682 def toString(self): … … 685 721 return ArmAstFunction(self.sName, [oArg.clone() for oArg in self.aoArgs]); 686 722 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 687 733 def toString(self): 688 734 return '%s(%s)' % (self.sName, ','.join([oArg.toString() for oArg in self.aoArgs]),); … … 702 748 def clone(self): 703 749 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; 704 756 705 757 def toString(self): … … 720 772 return ArmAstBool(self.fValue); 721 773 774 def isSame(self, oOther): 775 if isinstance(oOther, ArmAstBase): 776 if self.fValue == oOther.fValue: 777 return True; 778 return False; 779 722 780 def toString(self): 723 781 return 'true' if self.fValue is True else 'false'; … … 726 784 _ = oHelper; 727 785 return 'true' if self.fValue is True else 'false'; 786 728 787 729 788 class ArmAstInteger(ArmAstBase): … … 734 793 def clone(self): 735 794 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; 736 801 737 802 def toString(self): … … 746 811 return '%#x' % (self.iValue,); 747 812 813 748 814 class ArmAstSet(ArmAstBase): 749 815 def __init__(self, aoValues): … … 754 820 return ArmAstSet([oValue.clone() for oValue in self.aoValues]); 755 821 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 756 831 def toString(self): 757 832 return '(%s)' % (', '.join([oValue.toString() for oValue in self.aoValues]),); … … 760 835 _ = oHelper; 761 836 raise Exception('ArmAstSet does not support conversion to C expression: %s' % (self.toString())); 837 762 838 763 839 class ArmAstValue(ArmAstBase): … … 768 844 def clone(self): 769 845 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; 770 852 771 853 def toString(self): … … 899 981 self.sName = sName; 900 982 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; 903 985 self.oCondition = oCondition; 904 986 … … 1133 1215 ## The instruction groups. 1134 1216 g_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. 1226 g_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 }; 1135 1248 1136 1249 … … 1252 1365 1253 1366 oCondition = ArmAstBase.fromJson(oJson['condition']); 1367 aoCorrectionConditions = g_dArmEncodingCorrectionConditions.get(sInstrNm) 1368 if aoCorrectionConditions: 1369 oCondition = addAndConditionsFromList(oCondition, aoCorrectionConditions); 1254 1370 1255 1371 (aoFields, fFields) = ArmEncodesetField.encodesetFromJson(oJson['encoding']); … … 1267 1383 (oCondition, fMod) = transferConditionsToEncoding(oCondition, aoFields, collections.defaultdict(list), sInstrNm); 1268 1384 #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(),)); 1270 1387 _ = fMod; 1271 1388 … … 1300 1417 1301 1418 return True; 1419 1420 1421 def 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 1447 def 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 1302 1453 1303 1454 def transferConditionsToEncoding(oCondition, aoFields, dPendingNotEq, sInstrNm, uDepth = 0, fMod = False): … … 1338 1489 for oField in aoFields: # ArmEncodesetField 1339 1490 if oField.sName and oField.sName == sFieldName: 1340 # ArmAstInteger (unlikely):1491 # ArmAstInteger - not used by spec, only corrections: 1341 1492 if isinstance(oValue, ArmAstInteger): 1342 1493 if oField.fFixed != 0: … … 1357 1508 break; 1358 1509 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)); 1361 1512 if oCondition.sOp == '==': 1362 1513 oField.fValue = oValue.iValue; … … 1395 1546 if oCondition.sOp == '&&': 1396 1547 oCondition.oLeft = recursiveRemove(oCondition.oLeft, aoToRemove); 1397 oCondition.oRight = recursiveRemove(oCondition.o Left, aoToRemove);1548 oCondition.oRight = recursiveRemove(oCondition.oRight, aoToRemove); 1398 1549 if oCondition.oLeft.isBoolAndTrue(): return oCondition.oRight; 1399 1550 if oCondition.oRight.isBoolAndTrue(): return oCondition.oLeft; … … 1427 1578 oField.fFixed |= fFixed; 1428 1579 1429 1430 1580 # Remove the associated conditions (they'll be leaves). 1431 1581 oCondition = recursiveRemove(oCondition, [oCondition for _, _, _, oCondition in atOccurences]); … … 1495 1645 #print("oBrk=%s" % (oBrk,)) 1496 1646 1497 if oOptions.fPrintInstructions :1647 if oOptions.fPrintInstructions or oOptions.fPrintInstructionsWithEncoding or oOptions.fPrintInstructionsWithConditions: 1498 1648 for oInstr in g_aoAllArmInstructions: 1499 1649 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(),)); 1500 1657 1501 1658 # Gather stats on fixed bits: … … 2145 2302 Returns the lines for a license header. 2146 2303 """ 2304 sDashYear = '-%s' % datetime.date.today().year; 2305 if sDashYear == '-2025': 2306 sDashYear = ''; 2147 2307 return [ 2148 2308 '/*', … … 2156 2316 '', 2157 2317 '/*', 2158 ' * Copyright (C) 2025 -' + str(datetime.date.today().year)+ ' Oracle and/or its affiliates.',2318 ' * Copyright (C) 2025' + sDashYear + ' Oracle and/or its affiliates.', 2159 2319 ' *', 2160 2320 ' * This file is part of VirtualBox base platform packages, as', … … 2293 2453 ]; 2294 2454 asTail = [ 2295 ' Log Flow(("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));', 2296 2456 ' IEMOP_RAISE_INVALID_OPCODE_RET();', 2297 2457 '}', … … 2321 2481 2322 2482 asTail = [ 2323 sIndent + ' Log Flow(("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));', 2324 2484 sIndent + ' IEMOP_RAISE_INVALID_OPCODE_RET();', 2325 2485 sIndent + '}', … … 2329 2489 # Log and call implementation. 2330 2490 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),), 2332 2493 '#ifdef IEM_INSTR_IMPL_%s__%s' % (sInstrSet, sCName,), 2333 2494 '%s IEM_INSTR_IMPL_%s__%s(%s);' % (sIndent, sInstrSet, sCName, ', '.join(asArgs),), … … 2486 2647 'FNIEMOP_DEF_1(iemDecode%s_Invalid, uint32_t, uOpcode)' % (sInstrSet,), 2487 2648 '{', 2488 ' Log Flow(("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));', 2489 2650 ' IEMOP_RAISE_INVALID_OPCODE_RET();', 2490 2651 '}', … … 2583 2744 dest = 'sFileDecoderCpp', 2584 2745 action = 'store', 2585 default = '-',2746 default = None, 2586 2747 help = 'The output C++ file for the decoder.'); 2587 2748 oArgParser.add_argument('--out-decoder-hdr', … … 2589 2750 dest = 'sFileDecoderHdr', 2590 2751 action = 'store', 2591 default = '-',2752 default = None, 2592 2753 help = 'The output header file for the decoder.'); 2593 2754 oArgParser.add_argument('--out-stub-hdr', … … 2595 2756 dest = 'sFileStubHdr', 2596 2757 action = 'store', 2597 default = '-',2758 default = None, 2598 2759 help = 'The output header file for the implementation stubs.'); 2599 2760 # debug: … … 2603 2764 default = False, 2604 2765 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.'); 2605 2776 oArgParser.add_argument('--print-fixed-mask-stats', 2606 2777 dest = 'fPrintFixedMaskStats', … … 2621 2792 if LoadArmOpenSourceSpecification(oOptions): 2622 2793 # 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. 2629 2795 # 2630 2796 aaoOutputFiles = [ … … 2633 2799 ( oOptions.sFileStubHdr, self.generateA64ImplementationStubHdr, 0, ), 2634 2800 ]; 2801 2802 cOutputFiles = 0; 2803 for sOutFile, _, _ in aaoOutputFiles: 2804 cOutputFiles += sOutFile is not None; 2805 2635 2806 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(); 2652 2834 if fRc: 2653 2835 return 0;
Note:
See TracChangeset
for help on using the changeset viewer.