VirtualBox

Changeset 46771 in vbox


Ignore:
Timestamp:
Jun 25, 2013 8:26:31 AM (11 years ago)
Author:
vboxsync
Message:

SIB hacking in progress.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/testcase/Instructions/InstructionTestGen.py

    r46746 r46771  
    375375        self.acbOpVars    = [ 1, 2, 4, 8 ] if not acbOpVars else list(acbOpVars);
    376376
     377    ## @name Test Instruction Writers
     378    ## @{
     379
    377380    def writeInstrGregGreg(self, cbEffOp, iOp1, iOp2, oGen):
    378381        """ Writes the instruction with two general registers as operands. """
     
    440443        return True;
    441444
    442     def generateOneStdTestGregGreg(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult):
    443         """ Generate one standard test. """
    444         oGen.write('        call VBINSTST_NAME(Common_LoadKnownValues)\n');
    445         oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2], uInput,));
    446         oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[iOp2],));
    447         self.writeInstrGregGreg(cbEffOp, iOp1, iOp2, oGen);
    448         oGen.pushConst(uResult);
    449         oGen.write('        call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),));
    450         _ = cbMaxOp;
     445    def writeInstrGregSibLabel(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, oGen):
     446        """ Writes the instruction taking a register and a lable, SIB form. """
     447        ## @todo Dunno how to convince yasm to generate these. Considering patching it.
     448        oGen.write('        %s %s, [VBINSTST_NAME(g_u%sData) xWrtRIP]\n'
     449                   % (self.sInstr, gregName(iOp1, cbEffOp * 8),));
     450        return True;
     451
     452    def writeInstrGregSibScaledReg(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
     453        ## @todo Dunno how to convince yasm to generate SIB variants for iScale == 1 here. Considering patching it.
     454        oGen.write('        %s %s, [%s * %#x'
     455                   % (self.sInstr, gregName(iOp1, cbEffOp * 8), gregName(iIndexReg, cAddrBits), iScale,));
     456        if offDisp is not None:
     457            oGen.write(' + %#x' % (offDisp,));
     458        oGen.write('] ; iScale=%s\n' % (iScale,));
     459        _ = iBaseReg;
     460        return True;
     461
     462    def writeInstrGregSibBase(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
     463        ## @todo Dunno how to convince yasm to generate SIB variants for iScale == 1 here. Considering patching it.
     464        oGen.write('        %s %s, [%s'
     465                   % (self.sInstr, gregName(iOp1, cbEffOp * 8), gregName(iBaseReg, cAddrBits), iScale,));
     466        if offDisp is not None:
     467            oGen.write(' + %#x' % (offDisp,));
     468        oGen.write('] ; iScale=%s\n' % (iScale,));
     469        _ = iIndexReg;
     470        return True;
     471
     472    def writeInstrGregSibBaseAndScaledReg(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen):
     473        return True;
     474
     475    ## @}
     476
     477
     478    ## @name Memory setups
     479    ## @{
     480    def generateMemSetupReadByLabel(self, oGen, cAddrBits, uInput):
     481        """ Sets up memory for a memory read. """
     482        oGen.pushConst(uInput);
     483        oGen.write('        call    VBINSTST_NAME(Common_SetupMemReadU%u)\n' % (cbEffOp*8,));
     484        return True;
     485
     486    def generateMemSetupReadByReg(self, oGen, cAddrBits, cbEffOp, iReg1, uInput, offDisp = None):
     487        """ Sets up memory for a memory read indirectly addressed thru one register and optional displacement. """
     488        oGen.pushConst(uInput);
     489        oGen.write('        call    VBINSTST_NAME(%s)\n'
     490                   % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iReg1, offDisp),));
     491        oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[iReg1],));
     492        return True;
     493
     494    def generateMemSetupReadByScaledReg(self, oGen, cAddrBits, cbEffOp, iReg2, iScale, uInput, offDisp = None):
     495        """ Sets up memory for a memory read indirectly addressed thru one register and optional displacement. """
     496        oGen.pushConst(uInput);
     497        oGen.write('        call    VBINSTST_NAME(%s)\n'
     498                   % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iReg2, offDisp, iScale = iScale),));
     499        oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[iReg1],));
     500        return True;
     501
     502    def generateMemSetupReadByBaseAndScaledReg(self, oGen, cAddrBits, cbEffOp, iBaseReg, iIndexReg, iScale, uInput, offDisp):
     503        """ Sets up memory for a memory read indirectly addressed thru two registers with optional displacement. """
     504        oGen.pushConst(uInput);
     505        if iScale == 1:
     506        oGen.write('        call    VBINSTST_NAME(%s)\n'
     507                   % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iReg1, offDisp),));
     508        oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[iReg1],));
    451509        return True;
    452510
     
    463521        return True;
    464522
     523    ## @}
     524
     525    def generateOneStdTestGregGreg(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult):
     526        """ Generate one standard test. """
     527        oGen.write('        call VBINSTST_NAME(Common_LoadKnownValues)\n');
     528        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2], uInput,));
     529        oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[iOp2],));
     530        self.writeInstrGregGreg(cbEffOp, iOp1, iOp2, oGen);
     531        oGen.pushConst(uResult);
     532        oGen.write('        call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),));
     533        _ = cbMaxOp;
     534        return True;
    465535
    466536    def generateOneStdTestGregMemNoSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult):
     
    478548            if iOp2 != 5 and iOp2 != 13:
    479549                iMod = 1;
    480                 for offDisp in (127, -128):
     550                for offDisp in oGen.getDispForMod(iMod):
    481551                    oGen.write('        call    VBINSTST_NAME(Common_LoadKnownValues)\n');
    482552                    self.generateMemSetupPureRM(oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput, offDisp);
     
    486556
    487557                iMod = 2;
    488                 for offDisp in (2147483647, -2147483648):
     558                for offDisp in oGen.getDispForMod(iMod):
    489559                    oGen.write('        call    VBINSTST_NAME(Common_LoadKnownValues)\n');
    490560                    self.generateMemSetupPureRM(oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput, offDisp);
     
    492562                    oGen.pushConst(uResult);
    493563                    oGen.write('        call    VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),));
     564
     565        return True;
     566
     567    def generateOneStdTestGregMemNoSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iMod,
     568                                       iBaseReg, iIndexReg, iScale, uInput, uResult):
     569        """ Generate one SIB variations. """
     570        for offDisp in oGen.getDispForMod(iMod, cbEffOp):
     571            if ((iBaseReg == 5 or iBaseReg == 13) and iMod == 0):
     572                if iIndexReg == 4:
     573                    if cAddrBits == 64:
     574                        continue; # skipping.
     575                    oGen.write('        call    VBINSTST_NAME(Common_LoadKnownValues)\n');
     576                    self.generateMemSetupReadByLabel(oGen, cAddrBits, uInput);
     577                    self.writeInstrGregSibLabel(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, oGen);
     578                    sChecker = oGen.needGRegChecker(iOp1);
     579                else:
     580                    oGen.write('        call    VBINSTST_NAME(Common_LoadKnownValues)\n');
     581                    self.generateMemSetupReadByScaledReg(oGen, cAddrBits, cbEffOp, iIndexReg, iScale, uInput, offDisp);
     582                    self.writeInstrGregSibScaledReg(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
     583                    sChecker = oGen.needGRegChecker(iOp1, iIndexReg);
     584            else:
     585                oGen.write('        call    VBINSTST_NAME(Common_LoadKnownValues)\n');
     586                if iIndexReg == 4:
     587                    self.generateMemSetupReadByReg(oGen, cAddrBits, cbEffOp, iBaseReg, uInput, offDisp);
     588                    self.writeInstrGregSibBase(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
     589                    sChecker = oGen.needGRegChecker(iOp1, iBaseReg);
     590                else:
     591                    self.generateMemSetupReadByBaseAndScaledReg(oGen, cAddrBits, cbEffOp, iBaseReg,
     592                                                                iIndexReg, iScale, uInput, offDisp);
     593                    self.writeInstrGregSibBaseAndScaledReg(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen);
     594                    sChecker = oGen.needGRegChecker(iOp1, iBaseReg, iIndexReg);
     595            oGen.pushConst(uResult);
     596            oGen.write('        call    VBINSTST_NAME(%s)\n' % (sChecker,));
     597        return True;
     598
     599    def generateStdTestGregMemSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, auInputs):
     600        """ Generate all SIB variations for the given iOp1 (reg) value. """
     601        assert cAddrBits in [32, 64];
     602        for iBaseReg in range(len(oGen.oTarget.asGRegs)):
     603            for iIndexReg in range(len(oGen.oTarget.asGRegs)):
     604                if iBaseReg == 4 or iIndexReg == 4: # no RSP testing atm.
     605                    continue;
     606                for iMod in [0, 1, 2]:
     607                    if iBaseReg == iOp1 and ((iBaseReg != 5 and iBaseReg != 13) or iMod != 0) and cAddrBits != cbMaxOp:
     608                        continue; # Don't know the high bit of the address ending up the result - skip it for now.
     609                    for iScale in (1, 2, 4, 8):
     610                        for uInput in auInputs:
     611                            oGen.newSubTest();
     612                            uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[iOp1], oGen);
     613                            self.generateOneStdTestGregMemSib(oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iMod,
     614                                                              iBaseReg, iIndexReg, iScale, uInput, uResult);
    494615
    495616        return True;
     
    539660                    for cAddrBits in oGen.oTarget.getAddrModes():
    540661                        for iOp2 in range(len(oGen.oTarget.asGRegs)):
    541                             if iOp2 != 4:
    542 
     662                            if iOp2 != 4 or cAddrBits == 16:
    543663                                for uInput in (auLongInputs if iOp1 == iLongOp1 and False else auShortInputs):
    544664                                    oGen.newSubTest();
    545665                                    if iOp1 == iOp2 and iOp2 != 5 and iOp2 != 13 and cbEffOp != cbMaxOp:
    546                                         continue; # Don't know the high bit of the address ending up the result - skip it.
     666                                        continue; # Don't know the high bit of the address ending up the result - skip it for now.
    547667                                    uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[iOp1], oGen);
    548668                                    self.generateOneStdTestGregMemNoSib(oGen, cAddrBits, cbEffOp, cbMaxOp,
    549669                                                                        iOp1, iOp2, uInput, uResult);
    550670                            else:
    551                                 pass; # SIB
     671                                # SIB.
     672                                self.generateStdTestGregMemSib(oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, auInputs);
    552673
    553674        return True;
     
    703824        return True;
    704825
    705     def needGRegChecker(self, iReg1, iReg2):
     826    def needGRegChecker(self, iReg1, iReg2 = None, iReg3 = None):
    706827        """
    707828        Records the need for a given register checker function, returning its label.
     
    715836        return 'Common_Check_%s_%s' % (self.oTarget.asGRegs[iReg1], self.oTarget.asGRegs[iReg2]);
    716837
    717     def needGRegMemSetup(self, cAddrBits, cbEffOp, iReg1, offDisp = None):
     838    def needGRegMemSetup(self, cAddrBits, cbEffOp, iBaseReg, offDisp = None, iIndexReg = None, iScale = 1):
    718839        """
    719840        Records the need for a given register checker function, returning its label.
    720841        """
    721         sName = '%ubit_U%u_%s' % (cAddrBits, cbEffOp * 8, gregName(iReg1, cAddrBits),);
     842        sName = '%ubit_U%u' % (cAddrBits, cbEffOp * 8,);
     843        if iBaseReg is not None:
     844            sName += '_%s' % (gregName(iBaseReg, cAddrBits),);
     845        sName += '_x%u' % (iScale,);
     846        if iIndexReg is not None:
     847            sName += '_%s' % (gregName(iIndexReg, cAddrBits),);
    722848        if offDisp is not None:
    723849            sName += '_%#010x' % (offDisp & UINT32_MAX, );
     
    749875            self.write('        push    dword 0x%x\n' % (uResult,));
    750876        return True;
     877
     878    def getDispForMod(self, iMod, cbAlignment = 1):
     879        """
     880        Get a set of address dispositions for a given addressing mode.
     881        The alignment restriction is for SIB scaling.
     882        """
     883        assert cbAlignment in [1, 2, 4, 8];
     884        if iMod == 0:
     885            aoffDisp = [ None, ];
     886        elif iMod == 1:
     887            aoffDisp = [ 127 & ~cbAlignment, -128 ];
     888        elif iMod == 2:
     889            aoffDisp = [ 2147483647 & ~(cbAlignment - 1), -2147483648 ];
     890        else: assert False;
     891        return aoffDisp;
    751892
    752893
     
    8651006            cAddrBits  = int(asParams[0][:-3]);
    8661007            cEffOpBits = int(asParams[1][1:]);
    867             sBaseReg   = asParams[2];
    868 
    8691008            if cAddrBits == 64:   asAddrGRegs = g_asGRegs64;
    8701009            elif cAddrBits == 32: asAddrGRegs = g_asGRegs32;
    8711010            else:                 asAddrGRegs = g_asGRegs16;
    872             try:
    873                 iBaseReg = asAddrGRegs.index(sBaseReg);
    874             except ValueError:
    875                 assert False, 'sBaseReg=%s' % (sBaseReg,);
    876                 raise;
    877 
    878             i = 3;
     1011
     1012            i = 2;
     1013            if i < len(asParams[i]) and asParams[i]:
     1014                sBaseReg = asParams[i];
     1015                i += 1
     1016                try:
     1017                    iBaseReg = asAddrGRegs.index(sBaseReg);
     1018                except ValueError:
     1019                    assert False, 'sBaseReg=%s' % (sBaseReg,);
     1020                    raise;
     1021
    8791022            u32Disp = None;
    8801023            if i < len(asParams) and len(asParams[i]) == 10:
Note: See TracChangeset for help on using the changeset viewer.

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