VirtualBox

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


Ignore:
Timestamp:
Apr 8, 2025 12:21:04 AM (5 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168325
Message:

VMM/IEM: Working on the ARM bsd/opensource spec reader & decoder generator. Work in progress. Basic construction algo should be there now. jiraref:VBP-1598

File:
1 edited

Legend:

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

    r108868 r108875  
    10911091    );
    10921092
     1093    kChildMaskOpcodeValueIf          = 0x7fffffff;
     1094    kChildMaskMultipleOpcodeValueIfs = 0xffffffff;
     1095
    10931096    class TooExpensive(Exception):
    10941097        def __init__(self):
     
    11461149            if cInstructions <= 1:
    11471150                if self.aoInstructions[0].fFixedMask & ~self.fCheckedMask != 0:
     1151                    self.fChildMask = DecoderNode.kChildMaskOpcodeValueIf;
    11481152                    uCost = 16;                                                         # 16 = kCostOpcodeValueIf
     1153                else:
     1154                    assert self.fChildMask == 0;
    11491155
    11501156            # Special case: 2, 3 or 4 instructions - use a sequence of 'if ((uOpcode & fFixedMask) == fFixedValue)' checks.
    11511157            else:
    1152                 self.fChildMask = 0xffffffff;
     1158                self.fChildMask = DecoderNode.kChildMaskMultipleOpcodeValueIfs;
    11531159                for i, oInstr in enumerate(self.aoInstructions):
    11541160                    self.dChildren[i] = DecoderNode([oInstr], oInstr.fFixedMask, oInstr.fFixedMask);
     
    13481354        return uCostBest;
    13491355
     1356    def setInstrProps(self, uDepth):
     1357        """
     1358        Sets the fDecoderLeafCheckNeeded instruction property.
     1359        """
     1360        if not self.dChildren:
     1361            assert len(self.aoInstructions) != 1 or self.fChildMask in (0, DecoderNode.kChildMaskOpcodeValueIf);
     1362            assert len(self.aoInstructions) == 1 or self.fChildMask == DecoderNode.kChildMaskMultipleOpcodeValueIfs;
     1363            for oInstr in self.aoInstructions:
     1364                oInstr.fDecoderLeafCheckNeeded = self.fChildMask == DecoderNode.kChildMaskOpcodeValueIf;
     1365        else:
     1366            for oChildNode in self.dChildren.values():
     1367                oChildNode.setInstrProps(uDepth + 1);
     1368
     1369    def getFuncName(self, uDepth):
     1370        """
     1371        Returns the function name at the specific depth.
     1372        """
     1373        if self.dChildren or len(self.aoInstructions) > 1:
     1374            return 'iemDecodeA64_%08x_%08x_%u' % (self.fCheckedMask, self.fCheckedValue, uDepth,);
     1375        return 'iemDecodeA64_%s' % (self.aoInstructions[0].getCName(),);
    13501376
    13511377#
     
    13671393                                        0, 0);
    13681394        self.oDecoderRoot.constructNextLevel(0, sys.maxsize);
     1395
     1396        # Set the fDecoderLeafCheckNeeded property of the instructions.
     1397        self.oDecoderRoot.setInstrProps(0);
    13691398
    13701399
     
    14311460                '',
    14321461                '/* %08x/%08x: %s */' % (oInstr.fFixedMask, oInstr.fFixedValue, oInstr.sAsmDisplay,),
    1433                 'FNIEMOP_DEF_1(iemDecode_%s, uint32_t, uOpcode)' % (sCName,),
     1462                'FNIEMOP_DEF_1(iemDecodeA64_%s, uint32_t, uOpcode)' % (sCName,),
    14341463                '{',
    14351464            ]);
    14361465
    14371466            # The final decoding step, if needed.
     1467            sIndent = '';
     1468            asTail  = [];
    14381469            if oInstr.fDecoderLeafCheckNeeded:
    14391470                asLines.extend([
    1440                     '    if ((uOpcode & %#x) == %#x) { /* likely */ }' % (oInstr.fFixedMask, oInstr.fFixedValue,),
    1441                     '    else',
     1471                    '    if ((uOpcode & %#x) == %#x)' % (oInstr.fFixedMask, oInstr.fFixedValue,),
    14421472                    '    {',
    1443                     '        LogFlow(("Invalid instruction %%#x at %%x\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));',
    1444                     '        return IEMOP_RAISE_INVALID_OPCODE_RET();',
     1473                ]);
     1474                asTail = [
    14451475                    '    }',
    1446                 ]);
     1476                    '',  # ASSUMES if condition
     1477                    '    LogFlow(("Invalid instruction %%#x at %%x\n", uOpcode, pVCpu->cpum.GstCtx.Pc.u64));',
     1478                    '    return IEMOP_RAISE_INVALID_OPCODE_RET();',
     1479                ];
    14471480
    14481481            # Decode the fields and prepare for passing them as arguments.
     
    14511484            ## @todo Most of this should be done kept in the instruction.
    14521485
     1486            ## @todo check for feature and such as specified in the conditions.
    14531487            asLines.extend([
    1454                 '    LogFlow(("%s%s\\n"%s));' % (sCName, sLogFmt, ', '.join(asArgs),),
    1455                 '#ifdef HAS_IMPL_%s' % (sCName,),
    1456                 '    return iemImpl_%s(%s);' % (sCName, ', '.join(asArgs),),
    1457                 '#else',
    1458                 '    RT_NOREF(%s);' % (', '.join(asArgs) if asArgs else 'uOpcode') ,
    1459                 '    return VERR_IEM_INSTR_NOT_IMPLEMENTED;',
    1460                 '#endif',
    1461                 '}',
     1488                '%s    LogFlow(("%s%s\\n"%s));' % (sIndent, sCName, sLogFmt, ', '.join(asArgs),),
     1489                '%s#ifdef HAS_IMPL_%s' % (sIndent, sCName,),
     1490                '%s    return iemImpl_%s(%s);' % (sIndent, sCName, ', '.join(asArgs),),
     1491                '%s#else' % (sIndent,),
     1492                '%s    RT_NOREF(%s);' % (sIndent, ', '.join(asArgs) if asArgs else 'uOpcode') ,
     1493                '%s    return VERR_IEM_INSTR_NOT_IMPLEMENTED;' % (sIndent,),
     1494                '%s#endif' % (sIndent,),
     1495                '%s}' % (sIndent),
    14621496            ]);
     1497            asLines.extend(asTail);
    14631498        return asLines;
    14641499
     1500    def generateDecoderCodeMultiIfFunc(self, oNode, uDepth):
     1501        """
     1502        Handles a leaf node.
     1503        """
     1504        assert not oNode.dChildren;
     1505
     1506        asLines = [
     1507            '',
     1508            '/* %08x/%08x level %u */' % (oNode.fCheckedMask, oNode.fCheckedValue, uDepth,),
     1509            'FNIEMOP_DEF_1(%s, uint32_t, uOpcode)' % (oNode.getFuncName(uDepth),),
     1510            '{',
     1511        ];
     1512        ## @todo check if the masks are restricted to a few bit differences at
     1513        ## this point and we can skip the iemDecodeA64_Invalid call.
     1514        for oInstr in oNode.aoInstructions:
     1515            asLines += [
     1516                '    if ((uOpcode & %#010x) == %#010x)' % (oInstr.fFixedMask, oInstr.fFixedValue,),
     1517                '        return iemDecodeA64_%s(pVCpu, uOpcode);' % (oInstr.getCName(),),
     1518            ];
     1519        asLines += [
     1520            '    return iemDecodeA64_Invalid(uOpcode);',
     1521            '}',
     1522        ];
     1523        return asLines;
     1524
     1525    def generateDecoderCode(self, oNode, uDepth):
     1526        """
     1527        Recursively generates the decoder code.
     1528        """
     1529        assert oNode.fChildMask != 0 and oNode.fChildMask < (1 << 24), \
     1530            'fChildMask=%s #dChildren=%s aoInstr=%s' % (oNode.fChildMask, len(oNode.dChildren), oNode.aoInstructions,);
     1531        asLines = [];
     1532
     1533        # First recurse.
     1534        for oChildNode in oNode.dChildren.values():
     1535            if oChildNode.fChildMask == DecoderNode.kChildMaskMultipleOpcodeValueIfs:
     1536                asLines += self.generateDecoderCodeMultiIfFunc(oChildNode, uDepth + 1);
     1537            elif oChildNode.fChildMask != DecoderNode.kChildMaskOpcodeValueIf:
     1538                assert oChildNode.dChildren;
     1539                asLines += self.generateDecoderCode(oChildNode, uDepth + 1);
     1540            else:
     1541                assert not oChildNode.dChildren;
     1542
     1543        # Generate the function.
     1544        ## @todo add some table stats here.
     1545        asLines += [
     1546            '',
     1547            '/* %08x/%08x level %u */' % (oNode.fCheckedMask, oNode.fCheckedValue, uDepth,),
     1548            'FNIEMOP_DEF_1(%s, uint32_t, uOpcode)' % (oNode.getFuncName(uDepth),),
     1549            '{',
     1550            '    static PFIEMOPU32 const s_apfn[] = ',
     1551            '    {',
     1552        ];
     1553
     1554        idxPrev = -1;
     1555        for idx, oChildNode in oNode.dChildren.items():
     1556            idxPrev += 1;
     1557            while idxPrev < idx:
     1558                asLines.append('        iemDecodeA64_Invalid,');
     1559                idxPrev += 1;
     1560            asLines.append('        %s,' % (oChildNode.getFuncName(uDepth + 1),));
     1561
     1562        asLines += [
     1563            '    };',
     1564            '    AssertCompile(RT_ELEMENTS(s_apfn) == %#x);' % (1 << oNode.fChildMask.bit_count()),
     1565            '',
     1566        ];
     1567
     1568        # Extract the index from uOpcode.
     1569        aaiAlgo = MaskZipper.compileAlgo(oNode.fChildMask);
     1570        assert aaiAlgo, 'fChildMask=%s #children=%s instrs=%s' % (oNode.fChildMask, len(oNode.dChildren), oNode.aoInstructions,);
     1571        asIdx = [
     1572            '    uintptr_t const idx = ((uOpcode >> %2u) & %#010x) /* bit %u L %u -> 0 */'
     1573            % (aaiAlgo[0][0], aaiAlgo[0][2], aaiAlgo[0][0], aaiAlgo[0][2].bit_count(), ),
     1574        ];
     1575        for iSrcBit, iDstBit, fMask in aaiAlgo[1:]:
     1576            asIdx.append('                        | ((uOpcode >> %2u) & %#010x) /* bit %u L %u -> %u */'
     1577                         % (iSrcBit - iDstBit, fMask << iDstBit, iSrcBit, fMask.bit_count(), iDstBit));
     1578        asIdx[-1] += ';';
     1579        asLines += asIdx;
     1580
     1581        # Make the call and complete the function.
     1582        asLines += [
     1583            '    return s_apfn[idx](pVCpu, uOpcode);',
     1584            '}'
     1585        ];
     1586        return asLines;
    14651587
    14661588    def generateDecoderCpp(self, iPartNo):
     
    14811603
    14821604        asLines += self.generateDecoderFunctions();
     1605
     1606        assert self.oDecoderRoot.dChildren;
     1607        asLines += self.generateDecoderCode(self.oDecoderRoot, 0);
     1608
    14831609
    14841610        return (True, asLines);
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