VirtualBox

Changeset 47017 in vbox for trunk/src/VBox/VMM/testcase


Ignore:
Timestamp:
Jul 5, 2013 5:49:53 PM (11 years ago)
Author:
vboxsync
Message:

div and idiv tests (greg only, no mem yet).

File:
1 edited

Legend:

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

    r46991 r47017  
    1717"""
    1818__version__ = "$Revision$";
     19
     20
     21# pylint: disable=C0103,R0913
    1922
    2023
     
    158161    return g_oMyRand.getrandbits(cBits);
    159162
     163def randSxx(cBits):
     164    """ Signed 8-, 16-, 32-, or 64-bit random number. """
     165    uVal = randUxx(cBits);
     166    iRet = uVal & ((1 << (cBits - 1)) - 1);
     167    if iRet != uVal:
     168        iRet = -iRet;
     169    return iRet;
     170
    160171def randUxxList(cBits, cElements):
    161172    """ List of unsigned 8-, 16-, 32-, or 64-bit random numbers. """
     
    351362        """ List of randGRegNoSp values. """
    352363        aiRegs = [];
    353         for i in range(cItems):
     364        for _ in range(cItems):
    354365            aiRegs.append(self.randGRegNoSp(cbEffBytes));
    355366        return aiRegs;
     
    832843                                for uInput in auInputs:
    833844                                    oGen.newSubTest();
    834                                     if oGen.iModReg == oGen.iModRm and oGen.iModRm != 5 and oGen.iModRm != 13 and cbEffOp != cbMaxOp:
     845                                    if oGen.iModReg == oGen.iModRm and oGen.iModRm != 5 \
     846                                       and oGen.iModRm != 13 and cbEffOp != cbMaxOp:
    835847                                        continue; # Don't know the high bit of the address ending up the result - skip it for now.
    836848                                    uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[oGen.iModReg & 15], oGen);
     
    926938    def __init__(self, fIsIDiv):
    927939        if not fIsIDiv:
    928             InstrTest_MemOrGreg_2_Greg.__init__(self, 'div Gv,Ev',  self.calc_div,  acbOpVars = [ 8, 4, 2, 1 ]);
    929         else
    930             InstrTest_MemOrGreg_2_Greg.__init__(self, 'idiv Gv,Ev', self.calc_idiv, acbOpVars = [ 8, 4, 2, 1 ]);
     940            InstrTestBase.__init__(self, 'div Gv,Ev', 'div');
     941        else:
     942            InstrTestBase.__init__(self, 'idiv Gv,Ev', 'idiv');
    931943        self.fIsIDiv = fIsIDiv;
     944
     945    def generateInputsNoXcpt(self, cbEffOp, fLong = False):
     946        """ Generate inputs for cbEffOp. Returns a list of pairs, dividen + divisor. """
     947        # Test params.
     948        uStep = 1 << (cbEffOp * 8);
     949        if self.fIsIDiv:
     950            uStep /= 2;
     951
     952        # edge tests
     953        auRet = [];
     954
     955        uDivisor  = 1 if fLong else 3;
     956        uDividend = uStep * uDivisor - 1;
     957        for i in range(5 if fLong else 3):
     958            auRet.append([uDividend, uDivisor]);
     959            if self.fIsIDiv:
     960                auRet.append([-uDividend, -uDivisor]);
     961                auRet.append([-(uDividend + uDivisor - 1), uDivisor]);
     962                auRet.append([ (uDividend + uDivisor - 1), -uDivisor]);
     963            if i <= 3 and fLong:
     964                auRet.append([uDividend - 1, uDivisor]);
     965                if self.fIsIDiv:
     966                    auRet.append([-(uDividend - 1), -uDivisor]);
     967            uDivisor += 1;
     968            uDividend += uStep;
     969
     970        uDivisor  = uStep - 1;
     971        uDividend = uStep * uDivisor - 1;
     972        for _ in range(3 if fLong else 1):
     973            auRet.append([uDividend, uDivisor]);
     974            if self.fIsIDiv:
     975                auRet.append([-uDividend, -uDivisor]);
     976            uDivisor  -= 1;
     977            uDividend -= uStep;
     978
     979        if self.fIsIDiv:
     980            uDivisor = -uStep;
     981            for _ in range(3 if fLong else 1):
     982                auRet.append([uDivisor * (uDivisor - 1) - 1, uDivisor]);
     983                uDivisor += 1
     984            uDivisor = uStep - 1;
     985            for _ in range(3 if fLong else 1):
     986                auRet.append([-(uDivisor * (uDivisor + 1) - 1), uDivisor]);
     987                uDivisor -= 1
     988
     989        # random tests.
     990        if self.fIsIDiv:
     991            for _ in range(6 if fLong else 2):
     992                while True:
     993                    uDivisor  = randSxx(cbEffOp * 4);
     994                    if uDivisor == 0 or uDivisor >= uStep or uDivisor < -uStep:
     995                        continue;
     996                    uDividend = randSxx(cbEffOp * 8);
     997                    uResult = uDividend / uDivisor;
     998                    if uResult >= uStep or uResult <= -uStep: # exclude difficulties
     999                        continue;
     1000                    break;
     1001                auRet.append([uDividend, uDivisor]);
     1002        else:
     1003            for _ in range(6 if fLong else 2):
     1004                while True:
     1005                    uDivisor  = randUxx(cbEffOp * 4);
     1006                    if uDivisor == 0 or uDivisor >= uStep:
     1007                        continue;
     1008                    uDividend = randUxx(cbEffOp * 8);
     1009                    uResult = uDividend / uDivisor;
     1010                    if uResult >= uStep:
     1011                        continue;
     1012                    break;
     1013                auRet.append([uDividend, uDivisor]);
     1014
     1015        return auRet;
     1016
     1017
     1018    def generateOneStdTestGreg(self, oGen, cbEffOp, iOp2, iDividend, iDivisor):
     1019        """ Generate code of one '[I]DIV rDX:rAX,<GREG>' test. """
     1020        cbMaxOp   = oGen.oTarget.getMaxOpBytes();
     1021        fEffOp    = ((1 << (cbEffOp *8) ) - 1);
     1022        fMaxOp    = UINT64_MAX if cbMaxOp == 8 else UINT32_MAX; assert cbMaxOp in [8, 4];
     1023        fTopOp    = fMaxOp - fEffOp;
     1024        fFullOp1  = ((1 << (cbEffOp*16)) - 1);
     1025
     1026        uAX       = iDividend & fFullOp1;       # full with unsigned
     1027        uDX       = uAX >> (cbEffOp*8);
     1028        uAX      &= fEffOp;
     1029        uOp2Val   = iDivisor & fEffOp;
     1030
     1031        iQuotient = iDividend / iDivisor;
     1032        iReminder = iDividend % iDivisor;
     1033        if iReminder != 0 and iQuotient < 0:    # python has different rounding rules for negative division.
     1034            iQuotient += 1;
     1035            iReminder -= iDivisor;
     1036        uAXResult = iQuotient & fEffOp;
     1037        uDXResult = iReminder & fEffOp;
     1038
     1039        if cbEffOp < cbMaxOp:
     1040            uAX     |= randUxx(cbMaxOp * 8) & fTopOp;
     1041            uDX     |= randUxx(cbMaxOp * 8) & fTopOp;
     1042            uOp2Val |= randUxx(cbMaxOp * 8) & fTopOp;
     1043            if cbEffOp < 4:
     1044                uAXResult |= uAX & fTopOp;
     1045                uDXResult |= uDX & fTopOp;
     1046        oGen.write('        ; iDividend=%#x (%d) iDivisor=%#x (%d)\n'
     1047                   '        ; iQuotient=%#x (%d) iReminder=%#x (%d)\n'
     1048                   % ( iDividend & fFullOp1, iDividend, iDivisor & fEffOp, iDivisor,
     1049                       iQuotient & fEffOp, iQuotient, iReminder & fEffOp, iReminder, ));
     1050
     1051        oGen.write('        call VBINSTST_NAME(Common_LoadKnownValues)\n');
     1052        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xDX], uDX,));
     1053        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX], uAX,));
     1054        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2],         uOp2Val,));
     1055
     1056        oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[iOp2],));
     1057        oGen.pushConst(uDXResult);
     1058        oGen.pushConst(uAXResult);
     1059
     1060        oGen.write('        %-4s    %s\n' % (self.sInstr, gregName(iOp2, cbEffOp * 8),));
     1061        oGen.write('        call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(X86_GREG_xAX, X86_GREG_xDX, iOp2),));
     1062        return True;
     1063
     1064    def generateOneStdTestGreg8Bit(self, oGen, cbEffOp, iOp2, iDividend, iDivisor):
     1065        """ Generate code of one '[I]DIV AX,<GREG>' test (8-bit). """
     1066        cbMaxOp   = oGen.oTarget.getMaxOpBytes();
     1067        fMaxOp    = UINT64_MAX if cbMaxOp == 8 else UINT32_MAX; assert cbMaxOp in [8, 4];
     1068        iOp2X     = (iOp2 & 3) if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2) else iOp2;
     1069        assert iOp2X != X86_GREG_xAX;
     1070
     1071        uAX       = iDividend & UINT16_MAX;     # full with unsigned
     1072        uOp2Val   = iDivisor  & UINT8_MAX;
     1073
     1074        iQuotient = iDividend / iDivisor;
     1075        iReminder = iDividend % iDivisor;
     1076        if iReminder != 0 and iQuotient < 0:    # python has different rounding rules for negative division.
     1077            iQuotient += 1;
     1078            iReminder -= iDivisor;
     1079        uAXResult = (iQuotient & UINT8_MAX) | ((iReminder & UINT8_MAX) << 8);
     1080
     1081        uAX       |= randUxx(cbMaxOp * 8) & (fMaxOp - UINT16_MAX);
     1082        uAXResult |= uAX & (fMaxOp - UINT16_MAX);
     1083        uOp2Val   |= randUxx(cbMaxOp * 8) & (fMaxOp - UINT8_MAX);
     1084        if iOp2X != iOp2:
     1085            uOp2Val = rotateLeftUxx(cbMaxOp * 8, uOp2Val, 8);
     1086        oGen.write('        ; iDividend=%#x (%d) iDivisor=%#x (%d)\n'
     1087                   '        ; iQuotient=%#x (%d) iReminder=%#x (%d)\n'
     1088                   % ( iDividend & UINT16_MAX, iDividend, iDivisor & UINT8_MAX, iDivisor,
     1089                       iQuotient & UINT8_MAX, iQuotient, iReminder & UINT8_MAX, iReminder, ));
     1090
     1091        oGen.write('        call VBINSTST_NAME(Common_LoadKnownValues)\n');
     1092        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX], uAX,));
     1093        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2X], uOp2Val,));
     1094        oGen.write('        push    %s\n'       % (oGen.oTarget.asGRegs[iOp2X],));
     1095        oGen.pushConst(uAXResult);
     1096
     1097        oGen.write('        %-4s    %s\n' % (self.sInstr, gregName(iOp2, cbEffOp * 8),));
     1098        oGen.write('        call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(X86_GREG_xAX, iOp2X),));
     1099        return;
     1100
    9321101
    9331102    def generateStandardTests(self, oGen):
     
    9351104
    9361105        # Parameters.
    937         cbDefOp       = oGen.oTarget.getDefOpBytes();
    938         cbMaxOp       = oGen.oTarget.getMaxOpBytes();
    939         #auShortInputs = self.generateInputs(cbDefOp, cbMaxOp, oGen);
    940         #auLongInputs  = self.generateInputs(cbDefOp, cbMaxOp, oGen, fLong = True);
    941         iLongOp2      = oGen.oTarget.randGRegNoSp();
     1106        iLongOp2       = oGen.oTarget.randGRegNoSp();
    9421107
    9431108        # Register tests
    9441109        if True:
    945             for cbEffOp in self.acbOpVars:
    946                 if cbEffOp > cbMaxOp:
     1110            for cbEffOp in  ( 8, 4, 2, 1 ):
     1111                if cbEffOp > oGen.oTarget.getMaxOpBytes():
    9471112                    continue;
    9481113                oGen.write('; cbEffOp=%u\n' % (cbEffOp,));
     
    9531118                    if iOp2 == X86_GREG_xSP:
    9541119                        continue; # Cannot test xSP atm.
    955                     #for uInput in (auLongInputs if iOp2 == iLongOp2 else auShortInputs):
    956                     #    oGen.newSubTest();
    957                     #    if not oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2):
    958                     #        uResult = self.fnCalcResult(cbEffOp, uInput, uCur, oGen);
    959                     #        self.generateOneStdTestGregGreg(oGen, cbEffOp, cbMaxOp, iOp2, iOp2 & 15,
    960                     #                                        uInput, uResult);
    961                     #    else:
    962                     #        self.generateOneStdTestGregGreg8BitHighPain(oGen, cbEffOp, cbMaxOp, iOp2, uInput);
     1120                    if iOp2 == X86_GREG_xAX or (cbEffOp > 1 and iOp2 == X86_GREG_xDX):
     1121                        continue; # Will overflow or be too complicated to get right.
     1122                    if cbEffOp == 1 and iOp2 == (16 if oGen.oTarget.is64Bit() else 4):
     1123                        continue; # Avoid dividing by AH, same reasons as above.
     1124
     1125                    for iDividend, iDivisor in self.generateInputsNoXcpt(cbEffOp, iOp2 == iLongOp2):
     1126                        oGen.newSubTest();
     1127                        if cbEffOp > 1:
     1128                            self.generateOneStdTestGreg(oGen, cbEffOp, iOp2, iDividend, iDivisor);
     1129                        else:
     1130                            self.generateOneStdTestGreg8Bit(oGen, cbEffOp, iOp2, iDividend, iDivisor);
    9631131
    9641132        ## Memory test.
     
    9901158        #oGen.write('        int3\n');
    9911159
    992         self.generateNoXcptTests(oGen);
     1160        self.generateStandardTests(oGen);
    9931161
    9941162        #oGen.write('        int3\n');
     
    9971165        return True;
    9981166
    999     @staticmethod
    1000     def calc_div(cbEffOp, uInput, uCur, oGen):
    1001         """ Returns a register pair. """
    1002         return 0;
    1003 
    1004     @staticmethod
    1005     def calc_idiv(cbEffOp, uInput, uCur, oGen):
    1006         """ Returns a register pair. """
    1007         return 0;
    1008 
    1009 
    1010 ## Instruction Tests.
     1167
     1168
     1169
     1170##
     1171# Instruction Tests.
     1172#
    10111173g_aoInstructionTests = [
    1012     #InstrTest_Mov_Gv_Ev(),
     1174    InstrTest_Mov_Gv_Ev(),
    10131175    #InstrTest_MovSxD_Gv_Ev(),
    1014     #InstrTest_DivIDiv(fIsIDiv = False),
     1176    InstrTest_DivIDiv(fIsIDiv = False),
    10151177    InstrTest_DivIDiv(fIsIDiv = True),
    10161178];
    10171179
    10181180
    1019 class InstructionTestGen(object):
     1181
     1182
     1183
     1184class InstructionTestGen(object): # pylint: disable=R0902
    10201185    """
    10211186    Instruction Test Generator.
     
    13371502        return True;
    13381503
    1339     def _generateMemSetupFunctions(self):
     1504    def _generateMemSetupFunctions(self): # pylint: disable=R0915
    13401505        """
    13411506        Generates the memory setup functions.
     
    15501715                               '        push    %s %u      ; register number\n'
    15511716                               '        push    %s         ; actual\n'
    1552                                '        mov     %s, [xSP + sCB*2 + MY_PUSH_FLAGS_SIZE + xCB]\n'
     1717                               '        mov     %s, [xSP + sCB*2 + MY_PUSH_FLAGS_SIZE + xCB + sCB * %u]\n'
    15531718                               '        push    %s         ; expected\n'
    15541719                               '        call    VBINSTST_NAME(Common_BadValue)\n'
    15551720                               '.equal%u:\n'
    1556                            % ( sReg, i, i, sPushSize, iReg, sReg, sReg, sReg, i, ) );
     1721                           % ( sReg, i, i, sPushSize, iReg, sReg, sReg, i, sReg, i, ) );
    15571722
    15581723
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