VirtualBox

Ignore:
Timestamp:
Apr 8, 2025 6:09:19 PM (2 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168355
Message:

VMM/IEM: Working on the ARM bsd/opensource spec reader & decoder generator. Still work in progress. jiraref:VBP-1598

File:
1 edited

Legend:

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

    r108876 r108898  
    13791379
    13801380    def __init__(self):
    1381         self.oDecoderRoot = None;
     1381        self.oDecoderRoot    = None;
     1382        self.asRootIndexExpr = None;
    13821383
    13831384
     
    13871388        """
    13881389        self.oDecoderRoot = DecoderNode(sorted(g_aoAllArmInstructions,
    1389                                                key = operator.attrgetter('fFixedMask', 'fFixedValue', 'sName')),
     1390                                               key = operator.attrgetter('fFixedMask', 'fFixedValue', 'sName'))[:384],
    13901391                                        0, 0);
    13911392        self.oDecoderRoot.constructNextLevel(0, sys.maxsize);
     
    14691470                    '    {',
    14701471                ]);
    1471                 asTail = [
    1472                     '    }',
    1473                     '',  # ASSUMES if condition
    1474                     '    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                    '}',
    14761477                ];
    14771478
     
    14871488                '%s    return iemImpl_%s(%s);' % (sIndent, sCName, ', '.join(asArgs),),
    14881489                '%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',]),),
    14901491                '%s    return VERR_IEM_INSTR_NOT_IMPLEMENTED;' % (sIndent,),
    14911492                '%s#endif' % (sIndent,),
     
    15161517            ];
    15171518        asLines += [
    1518             '    return iemDecodeA64_Invalid(uOpcode);',
     1519            '    return iemDecodeA64_Invalid(pVCpu, uOpcode);',
    15191520            '}',
    15201521        ];
     
    15301531
    15311532        # 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];
    15331537            if oChildNode.dChildren:
    15341538                asLines += self.generateDecoderCode(oChildNode, uDepth + 1);
     
    15361540                assert len(oChildNode.aoInstructions) > 1;
    15371541                asLines += self.generateDecoderCodeMultiIfFunc(oChildNode, uDepth + 1);
     1542                cMultiIfEntries += 1;
    15381543            else:
    15391544                assert len(oChildNode.aoInstructions) == 1;
    15401545                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();
    15441552        asLines += [
    15451553            '',
    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, ),
    15511559        ];
     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 = '';
    15521576
    15531577        idxPrev = -1;
    1554         for idx, oChildNode in oNode.dChildren.items():
     1578        for idx in sorted(oNode.dChildren):
     1579            oChildNode = oNode.dChildren[idx];
    15551580            idxPrev += 1;
    15561581            while idxPrev < idx:
    1557                 asLines.append('        iemDecodeA64_Invalid,');
     1582                asLines.append(sIndent + '    iemDecodeA64_Invalid, // %s' % (idxPrev,));
    15581583                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,));
    15601589
    15611590        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,),
    15641593            '',
    15651594        ];
     
    15691598        assert aaiAlgo, 'fChildMask=%s #children=%s instrs=%s' % (oNode.fChildMask, len(oNode.dChildren), oNode.aoInstructions,);
    15701599        asIdx = [
     1600            '    /* fMask=%#010x -> %#010x */' % (oNode.fChildMask, cTabEntries - 1),
    15711601            '    uintptr_t const idx = ((uOpcode >> %2u) & %#010x) /* bit %2u L %u -> 0 */'
    15721602            % (aaiAlgo[0][0], aaiAlgo[0][2], aaiAlgo[0][0], aaiAlgo[0][2].bit_count(), ),
     
    15761606                         % (iSrcBit - iDstBit, fMask << iDstBit, iSrcBit, fMask.bit_count(), iDstBit));
    15771607        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;
    15851619        return asLines;
    15861620
    1587     def generateDecoderCpp(self, iPartNo):
     1621    def generateDecoderCpp(self, sFilename, iPartNo):
    15881622        """ Generates the decoder data & code. """
    1589         _ = iPartNo;
     1623        _ = iPartNo; _ = sFilename;
    15901624        asLines = self.generateLicenseHeader();
    15911625        asLines.extend([
     
    15931627            '#define VMCPU_INCL_CPUM_GST_CTX',
    15941628            '#include "IEMInternal.h"',
    1595             '#include "vm.h"',
     1629            '#include <VBox/vmm/vm.h>',
     1630            '#include "VBox/err.h"',
    15961631            '',
    15971632            '#include "iprt/armv8.h"',
    15981633            '',
     1634            '#include "IEMMc.h"',
    15991635            '',
     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            '}',
    16001643        ]);
    1601 
    16021644
    16031645        asLines += self.generateDecoderFunctions();
     
    16061648        asLines += self.generateDecoderCode(self.oDecoderRoot, 0);
    16071649
    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        ];
    16091682        return (True, asLines);
    16101683
     
    16121685    def main(self, asArgs):
    16131686        """ Main function. """
    1614 
    1615         #for _ in MaskIterator(0xffc0ff00, 4, 12, {}):
    1616         #    pass;
    1617         #return 2;
    16181687
    16191688        #
     
    16511720                                default = '',
    16521721                                help    = 'Specification directory to prefix the specficiation files with.');
    1653         oArgParser.add_argument('--out-decoder',
     1722        oArgParser.add_argument('--out-decoder-cpp',
    16541723                                metavar = 'file-decoder.cpp',
    16551724                                dest    = 'sFileDecoderCpp',
     
    16571726                                default = '-',
    16581727                                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.');
    16591734        # debug:
    16601735        oArgParser.add_argument('--print-instructions',
     
    16891764            #
    16901765            aaoOutputFiles = [
    1691                  ( oOptions.sFileDecoderCpp,      self. generateDecoderCpp, 0, ),
     1766                 ( oOptions.sFileDecoderCpp,      self.generateDecoderCpp, 0, ),
     1767                 ( oOptions.sFileDecoderH,        self.generateDecoderHdr, 0, ), # Must be after generateDecoderCpp!
    16921768            ];
    16931769            fRc = True;
     
    17021778                        return 1;
    17031779
    1704                 (fRc2, asLines) = fnGenMethod(iPartNo);
     1780                (fRc2, asLines) = fnGenMethod(sOutFile, iPartNo);
    17051781                fRc = fRc2 and fRc;
    17061782
     
    17491825    print('----', flush = True);
    17501826
     1827
    17511828if __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 
    17581829    fProfileIt = False;
    17591830    oProfiler = cProfile.Profile() if fProfileIt else None;
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