Changeset 108898 in vbox for trunk/src/VBox/VMM/VMMAll/target-armv8/bsd-spec-analyze.py
- Timestamp:
- Apr 8, 2025 6:09:19 PM (2 weeks ago)
- svn:sync-xref-src-repo-rev:
- 168355
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/target-armv8/bsd-spec-analyze.py
r108876 r108898 1379 1379 1380 1380 def __init__(self): 1381 self.oDecoderRoot = None; 1381 self.oDecoderRoot = None; 1382 self.asRootIndexExpr = None; 1382 1383 1383 1384 … … 1387 1388 """ 1388 1389 self.oDecoderRoot = DecoderNode(sorted(g_aoAllArmInstructions, 1389 key = operator.attrgetter('fFixedMask', 'fFixedValue', 'sName')) ,1390 key = operator.attrgetter('fFixedMask', 'fFixedValue', 'sName'))[:384], 1390 1391 0, 0); 1391 1392 self.oDecoderRoot.constructNextLevel(0, sys.maxsize); … … 1469 1470 ' {', 1470 1471 ]); 1471 asTail = [1472 ' }',1473 ' ', # ASSUMES if condition1474 ' LogFlow(("Invalid instruction %%#x at %%x\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));',1475 ' return IEMOP_RAISE_INVALID_OPCODE_RET();',1472 sIndent = ' '; 1473 asTail = [ 1474 ' LogFlow(("Invalid instruction %%#x at %%x\\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));', 1475 ' IEMOP_RAISE_INVALID_OPCODE_RET();', 1476 '}', 1476 1477 ]; 1477 1478 … … 1487 1488 '%s return iemImpl_%s(%s);' % (sIndent, sCName, ', '.join(asArgs),), 1488 1489 '%s#else' % (sIndent,), 1489 '%s RT_NOREF(%s);' % (sIndent, ', '.join(asArgs ) if asArgs else 'uOpcode'),1490 '%s RT_NOREF(%s);' % (sIndent, ', '.join(asArgs + ['pVCpu', 'uOpcode',]),), 1490 1491 '%s return VERR_IEM_INSTR_NOT_IMPLEMENTED;' % (sIndent,), 1491 1492 '%s#endif' % (sIndent,), … … 1516 1517 ]; 1517 1518 asLines += [ 1518 ' return iemDecodeA64_Invalid( uOpcode);',1519 ' return iemDecodeA64_Invalid(pVCpu, uOpcode);', 1519 1520 '}', 1520 1521 ]; … … 1530 1531 1531 1532 # First recurse. 1532 for oChildNode in oNode.dChildren.values(): 1533 cLeafEntries = 0; 1534 cMultiIfEntries = 0; 1535 for idx in sorted(oNode.dChildren): 1536 oChildNode = oNode.dChildren[idx]; 1533 1537 if oChildNode.dChildren: 1534 1538 asLines += self.generateDecoderCode(oChildNode, uDepth + 1); … … 1536 1540 assert len(oChildNode.aoInstructions) > 1; 1537 1541 asLines += self.generateDecoderCodeMultiIfFunc(oChildNode, uDepth + 1); 1542 cMultiIfEntries += 1; 1538 1543 else: 1539 1544 assert len(oChildNode.aoInstructions) == 1; 1540 1545 assert oChildNode.fChildMask in [DecoderNode.kChildMaskOpcodeValueIf, 0]; 1541 1542 # Generate the function. 1543 ## @todo add some table stats here. 1546 cLeafEntries += 1; 1547 1548 # Generate the function. For the top level we just do the table, as 1549 # the functions are static and we need the interpreter code to be able 1550 # to address the symbol and this is the speedier way. 1551 cTabEntries = 1 << oNode.fChildMask.bit_count(); 1544 1552 asLines += [ 1545 1553 '', 1546 '/* %08x/%08x level %u */' % (oNode.fCheckedMask, oNode.fCheckedValue, uDepth,),1547 'FNIEMOP_DEF_1(%s, uint32_t, uOpcode)' % (oNode.getFuncName(uDepth),),1548 '{',1549 ' static PFIEMOPU32 const s_apfn[] = ',1550 ' {',1554 '/* %08x/%08x level %u - mask=%#x entries=%#x valid=%%%u (%#x) leaf=%%%u (%#x) multi-if=%%%u (%#x) */' 1555 % (oNode.fCheckedMask, oNode.fCheckedValue, uDepth, oNode.fChildMask, cTabEntries, 1556 int(round(len(oNode.dChildren) * 100.0 / cTabEntries)), len(oNode.dChildren), 1557 int(round(cLeafEntries * 100.0 / cTabEntries)), cLeafEntries, 1558 int(round(cMultiIfEntries * 100.0 / cTabEntries)), cMultiIfEntries, ), 1551 1559 ]; 1560 if uDepth > 0: 1561 asLines += [ 1562 'FNIEMOP_DEF_1(%s, uint32_t, uOpcode)' % (oNode.getFuncName(uDepth),), 1563 '{', 1564 ' static PFIEMOPU32 const s_apfn[] = ', 1565 ' {', 1566 ]; 1567 sTabNm = 's_apfn'; 1568 sIndent = ' '; 1569 else: 1570 asLines += [ 1571 'PFIEMOPU32 const g_apfnIemInterpretOnlyA64[] = ', 1572 '{', 1573 ]; 1574 sTabNm = 'g_apfnIemInterpretOnlyA64'; 1575 sIndent = ''; 1552 1576 1553 1577 idxPrev = -1; 1554 for idx, oChildNode in oNode.dChildren.items(): 1578 for idx in sorted(oNode.dChildren): 1579 oChildNode = oNode.dChildren[idx]; 1555 1580 idxPrev += 1; 1556 1581 while idxPrev < idx: 1557 asLines.append( ' iemDecodeA64_Invalid,');1582 asLines.append(sIndent + ' iemDecodeA64_Invalid, // %s' % (idxPrev,)); 1558 1583 idxPrev += 1; 1559 asLines.append(' %s,' % (oChildNode.getFuncName(uDepth + 1),)); 1584 asLines.append('%s %s,' % (sIndent, oChildNode.getFuncName(uDepth + 1),)); 1585 1586 while idxPrev + 1 < cTabEntries: 1587 idxPrev += 1; 1588 asLines.append(sIndent + ' iemDecodeA64_Invalid, // %s' % (idxPrev,)); 1560 1589 1561 1590 asLines += [ 1562 ' };',1563 ' AssertCompile(RT_ELEMENTS(s_apfn) == %#x);' % (1 << oNode.fChildMask.bit_count()),1591 '%s};' % (sIndent,), 1592 '%sAssertCompile(RT_ELEMENTS(%s) == %#x);' % (sIndent, sTabNm, cTabEntries,), 1564 1593 '', 1565 1594 ]; … … 1569 1598 assert aaiAlgo, 'fChildMask=%s #children=%s instrs=%s' % (oNode.fChildMask, len(oNode.dChildren), oNode.aoInstructions,); 1570 1599 asIdx = [ 1600 ' /* fMask=%#010x -> %#010x */' % (oNode.fChildMask, cTabEntries - 1), 1571 1601 ' uintptr_t const idx = ((uOpcode >> %2u) & %#010x) /* bit %2u L %u -> 0 */' 1572 1602 % (aaiAlgo[0][0], aaiAlgo[0][2], aaiAlgo[0][0], aaiAlgo[0][2].bit_count(), ), … … 1576 1606 % (iSrcBit - iDstBit, fMask << iDstBit, iSrcBit, fMask.bit_count(), iDstBit)); 1577 1607 asIdx[-1] += ';'; 1578 asLines += asIdx; 1579 1580 # Make the call and complete the function. 1581 asLines += [ 1582 ' return s_apfn[idx](pVCpu, uOpcode);', 1583 '}' 1584 ]; 1608 1609 # Make the call and complete the function. For the top level, we save 1610 # the expression so we can later put it in a header file. 1611 if uDepth > 0: 1612 asLines += asIdx; 1613 asLines += [ 1614 ' return s_apfn[idx](pVCpu, uOpcode);', 1615 '}' 1616 ]; 1617 else: 1618 self.asRootIndexExpr = asIdx; 1585 1619 return asLines; 1586 1620 1587 def generateDecoderCpp(self, iPartNo):1621 def generateDecoderCpp(self, sFilename, iPartNo): 1588 1622 """ Generates the decoder data & code. """ 1589 _ = iPartNo; 1623 _ = iPartNo; _ = sFilename; 1590 1624 asLines = self.generateLicenseHeader(); 1591 1625 asLines.extend([ … … 1593 1627 '#define VMCPU_INCL_CPUM_GST_CTX', 1594 1628 '#include "IEMInternal.h"', 1595 '#include "vm.h"', 1629 '#include <VBox/vmm/vm.h>', 1630 '#include "VBox/err.h"', 1596 1631 '', 1597 1632 '#include "iprt/armv8.h"', 1598 1633 '', 1634 '#include "IEMMc.h"', 1599 1635 '', 1636 '', 1637 '/** Invalid instruction decoder function. */', 1638 'FNIEMOP_DEF_1(iemDecodeA64_Invalid, uint32_t, uOpcode)', 1639 '{', 1640 ' LogFlow(("Invalid instruction %%#x at %%x\\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));', 1641 ' IEMOP_RAISE_INVALID_OPCODE_RET();', 1642 '}', 1600 1643 ]); 1601 1602 1644 1603 1645 asLines += self.generateDecoderFunctions(); … … 1606 1648 asLines += self.generateDecoderCode(self.oDecoderRoot, 0); 1607 1649 1608 1650 return (True, asLines); 1651 1652 def generateDecoderHdr(self, sFilename, iPartNo): 1653 """ Generates the decoder header file. """ 1654 _ = iPartNo; 1655 1656 asLines = self.generateLicenseHeader(); 1657 sBlockerName = re.sub('[.-]', '_', os.path.basename(sFilename)); 1658 asLines += [ 1659 '#ifndef VMM_INCLUDED_SRC_VMMAll_target_armv8_%s' % (sBlockerName,), 1660 '#define VMM_INCLUDED_SRC_VMMAll_target_armv8_%s' % (sBlockerName,), 1661 '#ifndef RT_WITHOUT_PRAGMA_ONCE', 1662 '# pragma once', 1663 '#endif', 1664 '', 1665 '/** The top-level aarch64 decoder table for the IEM interpreter. */', 1666 'extern PFIEMOPU32 const g_apfnIemInterpretOnlyA64[%#x];' % (1 << self.oDecoderRoot.fChildMask.bit_count()), 1667 '', 1668 '/**', 1669 ' * Calculates the index for @a uOpcode in g_apfnIemInterpretOnlyA64.', 1670 ' */', 1671 'DECL_FORCE_INLINE(uintptr_t) iemInterpretOnlyA64CalcIndex(uint32_t uOpcode)', 1672 '{', 1673 ]; 1674 assert self.asRootIndexExpr; # Must be called after generateDecoderCpp()! 1675 asLines += self.asRootIndexExpr; 1676 asLines += [ 1677 ' return idx;', 1678 '}', 1679 '', 1680 '#endif /* !VMM_INCLUDED_SRC_VMMAll_target_armv8_%s */' % (sBlockerName,), 1681 ]; 1609 1682 return (True, asLines); 1610 1683 … … 1612 1685 def main(self, asArgs): 1613 1686 """ Main function. """ 1614 1615 #for _ in MaskIterator(0xffc0ff00, 4, 12, {}):1616 # pass;1617 #return 2;1618 1687 1619 1688 # … … 1651 1720 default = '', 1652 1721 help = 'Specification directory to prefix the specficiation files with.'); 1653 oArgParser.add_argument('--out-decoder ',1722 oArgParser.add_argument('--out-decoder-cpp', 1654 1723 metavar = 'file-decoder.cpp', 1655 1724 dest = 'sFileDecoderCpp', … … 1657 1726 default = '-', 1658 1727 help = 'The output C++ file for the decoder.'); 1728 oArgParser.add_argument('--out-decoder-hdr', 1729 metavar = 'file-decoder.h', 1730 dest = 'sFileDecoderH', 1731 action = 'store', 1732 default = '-', 1733 help = 'The output header file for the decoder.'); 1659 1734 # debug: 1660 1735 oArgParser.add_argument('--print-instructions', … … 1689 1764 # 1690 1765 aaoOutputFiles = [ 1691 ( oOptions.sFileDecoderCpp, self. generateDecoderCpp, 0, ), 1766 ( oOptions.sFileDecoderCpp, self.generateDecoderCpp, 0, ), 1767 ( oOptions.sFileDecoderH, self.generateDecoderHdr, 0, ), # Must be after generateDecoderCpp! 1692 1768 ]; 1693 1769 fRc = True; … … 1702 1778 return 1; 1703 1779 1704 (fRc2, asLines) = fnGenMethod( iPartNo);1780 (fRc2, asLines) = fnGenMethod(sOutFile, iPartNo); 1705 1781 fRc = fRc2 and fRc; 1706 1782 … … 1749 1825 print('----', flush = True); 1750 1826 1827 1751 1828 if __name__ == '__main__': 1752 #for fOrgMask in (0x11c00,):1753 # print('Test %#x:' % (fOrgMask,));1754 # for x in MaskIterator(fOrgMask, 16, ~0xfffee000):1755 # print('MaskIterator: fMask=%#05x cBits=%2s aaiAlgo=%s' % (x[0],x[1],x[2]));1756 #sys.exit(1);1757 1758 1829 fProfileIt = False; 1759 1830 oProfiler = cProfile.Profile() if fProfileIt else None;
Note:
See TracChangeset
for help on using the changeset viewer.