VirtualBox

Ignore:
Timestamp:
Jul 14, 2013 12:06:54 AM (11 years ago)
Author:
vboxsync
Message:

test divide errors (BS2+big.mac).

File:
1 edited

Legend:

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

    r47047 r47132  
    944944        self.fIsIDiv = fIsIDiv;
    945945
     946    def generateInputEdgeCases(self, cbEffOp, fLong, fXcpt):
     947        """ Generate edge case inputs for cbEffOp. Returns a list of pairs, dividen + divisor. """
     948        # Test params.
     949        uStep = 1 << (cbEffOp * 8);
     950        if self.fIsIDiv:
     951            uStep /= 2;
     952
     953        # edge tests
     954        auRet = [];
     955
     956        uDivisor  = 1 if fLong else 3;
     957        uDividend = uStep * uDivisor - 1;
     958        for i in range(5 if fLong else 3):
     959            auRet.append([uDividend + fXcpt, uDivisor]);
     960            if self.fIsIDiv:
     961                auRet.append([-uDividend - fXcpt, -uDivisor]);
     962                auRet.append([-(uDividend + uDivisor + fXcpt), uDivisor]);
     963                auRet.append([ (uDividend + uDivisor + fXcpt), -uDivisor]);
     964            if i <= 3 and fLong:
     965                auRet.append([uDividend - 1 + fXcpt*3, uDivisor]);
     966                if self.fIsIDiv:
     967                    auRet.append([-(uDividend - 1 + fXcpt*3), -uDivisor]);
     968            uDivisor += 1;
     969            uDividend += uStep;
     970
     971        uDivisor  = uStep - 1;
     972        uDividend = uStep * uDivisor - 1;
     973        for _ in range(3 if fLong else 1):
     974            auRet.append([uDividend + fXcpt, uDivisor]);
     975            if self.fIsIDiv:
     976                auRet.append([-uDividend - fXcpt, -uDivisor]);
     977            uDivisor  -= 1;
     978            uDividend -= uStep;
     979
     980        if self.fIsIDiv:
     981            uDivisor = -uStep;
     982            for _ in range(3 if fLong else 1):
     983                auRet.append([uDivisor * (-uStep - 1) - (not fXcpt), uDivisor]);
     984                uDivisor += 1
     985            uDivisor = uStep - 1;
     986            for _ in range(3 if fLong else 1):
     987                auRet.append([-(uDivisor * (uStep + 1) - (not fXcpt)), uDivisor]);
     988                uDivisor -= 1
     989
     990        return auRet;
     991
    946992    def generateInputsNoXcpt(self, cbEffOp, fLong = False):
    947993        """ Generate inputs for cbEffOp. Returns a list of pairs, dividen + divisor. """
     
    952998
    953999        # edge tests
    954         auRet = [];
    955 
    956         uDivisor  = 1 if fLong else 3;
    957         uDividend = uStep * uDivisor - 1;
    958         for i in range(5 if fLong else 3):
    959             auRet.append([uDividend, uDivisor]);
    960             if self.fIsIDiv:
    961                 auRet.append([-uDividend, -uDivisor]);
    962                 auRet.append([-(uDividend + uDivisor - 1), uDivisor]);
    963                 auRet.append([ (uDividend + uDivisor - 1), -uDivisor]);
    964             if i <= 3 and fLong:
    965                 auRet.append([uDividend - 1, uDivisor]);
    966                 if self.fIsIDiv:
    967                     auRet.append([-(uDividend - 1), -uDivisor]);
    968             uDivisor += 1;
    969             uDividend += uStep;
    970 
    971         uDivisor  = uStep - 1;
    972         uDividend = uStep * uDivisor - 1;
    973         for _ in range(3 if fLong else 1):
    974             auRet.append([uDividend, uDivisor]);
    975             if self.fIsIDiv:
    976                 auRet.append([-uDividend, -uDivisor]);
    977             uDivisor  -= 1;
    978             uDividend -= uStep;
    979 
    980         if self.fIsIDiv:
    981             uDivisor = -uStep;
    982             for _ in range(3 if fLong else 1):
    983                 auRet.append([uDivisor * (uDivisor - 1) - 1, uDivisor]);
    984                 uDivisor += 1
    985             uDivisor = uStep - 1;
    986             for _ in range(3 if fLong else 1):
    987                 auRet.append([-(uDivisor * (uDivisor + 1) - 1), uDivisor]);
    988                 uDivisor -= 1
     1000        auRet = self.generateInputEdgeCases(cbEffOp, fLong, False)
    9891001
    9901002        # random tests.
     
    9921004            for _ in range(6 if fLong else 2):
    9931005                while True:
    994                     uDivisor  = randSxx(cbEffOp * 4);
     1006                    uDivisor  = randSxx(cbEffOp * 8);
    9951007                    if uDivisor == 0 or uDivisor >= uStep or uDivisor < -uStep:
    9961008                        continue;
    997                     uDividend = randSxx(cbEffOp * 8);
     1009                    uDividend = randSxx(cbEffOp * 16);
    9981010                    uResult = uDividend / uDivisor;
    9991011                    if uResult >= uStep or uResult <= -uStep: # exclude difficulties
     
    10041016            for _ in range(6 if fLong else 2):
    10051017                while True:
    1006                     uDivisor  = randUxx(cbEffOp * 4);
     1018                    uDivisor  = randUxx(cbEffOp * 8);
    10071019                    if uDivisor == 0 or uDivisor >= uStep:
    10081020                        continue;
    1009                     uDividend = randUxx(cbEffOp * 8);
     1021                    uDividend = randUxx(cbEffOp * 16);
    10101022                    uResult = uDividend / uDivisor;
    10111023                    if uResult >= uStep:
     
    11551167        return True;
    11561168
     1169    def generateInputsXcpt(self, cbEffOp, fLong = False):
     1170        """
     1171        Generate inputs for cbEffOp that will overflow or underflow.
     1172        Returns a list of pairs, dividen + divisor.
     1173        """
     1174        # Test params.
     1175        uStep = 1 << (cbEffOp * 8);
     1176        if self.fIsIDiv:
     1177            uStep /= 2;
     1178
     1179        # edge tests
     1180        auRet = self.generateInputEdgeCases(cbEffOp, fLong, True);
     1181        auRet.extend([[0, 0], [1, 0], [ uStep * uStep / 2 - 1, 0]]);
     1182
     1183        # random tests.
     1184        if self.fIsIDiv:
     1185            for _ in range(6 if fLong else 2):
     1186                while True:
     1187                    uDivisor  = randSxx(cbEffOp * 8);
     1188                    uDividend = randSxx(cbEffOp * 16);
     1189                    if uDivisor >= uStep or uDivisor < -uStep:
     1190                        continue;
     1191                    if uDivisor != 0:
     1192                        uResult = uDividend / uDivisor;
     1193                        if (uResult <= uStep and uResult >= 0) or (uResult >= -uStep and uResult < 0):
     1194                            continue;  # exclude difficulties
     1195                    break;
     1196                auRet.append([uDividend, uDivisor]);
     1197        else:
     1198            for _ in range(6 if fLong else 2):
     1199                while True:
     1200                    uDivisor  = randUxx(cbEffOp * 8);
     1201                    uDividend = randUxx(cbEffOp * 16);
     1202                    if uDivisor >= uStep:
     1203                        continue;
     1204                    if uDivisor != 0:
     1205                        uResult = uDividend / uDivisor;
     1206                        if uResult < uStep:
     1207                            continue;
     1208                    break;
     1209                auRet.append([uDividend, uDivisor]);
     1210
     1211        return auRet;
     1212
     1213    def generateOneDivideErrorTestGreg(self, oGen, cbEffOp, iOp2, iDividend, iDivisor):
     1214        """ Generate code of one '[I]DIV rDX:rAX,<GREG>' test that causes #DE. """
     1215        cbMaxOp   = oGen.oTarget.getMaxOpBytes();
     1216        fEffOp    = ((1 << (cbEffOp *8) ) - 1);
     1217        fMaxOp    = UINT64_MAX if cbMaxOp == 8 else UINT32_MAX; assert cbMaxOp in [8, 4];
     1218        fTopOp    = fMaxOp - fEffOp;
     1219        fFullOp1  = ((1 << (cbEffOp*16)) - 1);
     1220
     1221        uAX       = iDividend & fFullOp1;       # full with unsigned
     1222        uDX       = uAX >> (cbEffOp*8);
     1223        uAX      &= fEffOp;
     1224        uOp2Val   = iDivisor & fEffOp;
     1225
     1226        if cbEffOp < cbMaxOp:
     1227            uAX     |= randUxx(cbMaxOp * 8) & fTopOp;
     1228            uDX     |= randUxx(cbMaxOp * 8) & fTopOp;
     1229            uOp2Val |= randUxx(cbMaxOp * 8) & fTopOp;
     1230        oGen.write('        ; iDividend=%#x (%d) iDivisor=%#x (%d)\n'
     1231                   % ( iDividend & fFullOp1, iDividend, iDivisor & fEffOp, iDivisor,));
     1232        oGen.write('        call VBINSTST_NAME(Common_LoadKnownValues)\n');
     1233        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xDX], uDX,));
     1234        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX], uAX,));
     1235        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2],         uOp2Val,));
     1236        oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[iOp2],));
     1237        oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[X86_GREG_xDX],));
     1238        oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX],));
     1239        oGen.write('        VBINSTST_TRAP_INSTR X86_XCPT_DE, 0, %-4s    %s\n'
     1240                   % (self.sInstr, gregName(iOp2, cbEffOp * 8),));
     1241        oGen.write('        call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(X86_GREG_xAX, X86_GREG_xDX, iOp2),));
     1242        return True;
     1243
     1244    def generateOneDivideErrorTestGreg8Bit(self, oGen, cbEffOp, iOp2, iDividend, iDivisor):
     1245        """ Generate code of one '[I]DIV AX,<GREG>' test that causes #DE (8-bit). """
     1246        cbMaxOp   = oGen.oTarget.getMaxOpBytes();
     1247        fMaxOp    = UINT64_MAX if cbMaxOp == 8 else UINT32_MAX; assert cbMaxOp in [8, 4];
     1248        iOp2X     = (iOp2 & 3) if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2) else iOp2;
     1249        assert iOp2X != X86_GREG_xAX;
     1250
     1251        uAX       = iDividend & UINT16_MAX;     # full with unsigned
     1252        uOp2Val   = iDivisor  & UINT8_MAX;
     1253
     1254        uAX       |= randUxx(cbMaxOp * 8) & (fMaxOp - UINT16_MAX);
     1255        uOp2Val   |= randUxx(cbMaxOp * 8) & (fMaxOp - UINT8_MAX);
     1256        if iOp2X != iOp2:
     1257            uOp2Val = rotateLeftUxx(cbMaxOp * 8, uOp2Val, 8);
     1258        oGen.write('        ; iDividend=%#x (%d) iDivisor=%#x (%d)\n'
     1259                   % ( iDividend & UINT16_MAX, iDividend, iDivisor & UINT8_MAX, iDivisor,));
     1260        oGen.write('        call VBINSTST_NAME(Common_LoadKnownValues)\n');
     1261        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[X86_GREG_xAX], uAX,));
     1262        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2X], uOp2Val,));
     1263        oGen.write('        push    %s\n'       % (oGen.oTarget.asGRegs[iOp2X],));
     1264        oGen.write('        push    sAX\n');
     1265        oGen.write('        VBINSTST_TRAP_INSTR X86_XCPT_DE, 0, %-4s    %s\n'
     1266                   % (self.sInstr, gregName(iOp2, cbEffOp * 8),));
     1267        oGen.write('        call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(X86_GREG_xAX, iOp2X),));
     1268        return;
     1269
     1270    def generateDivideErrorTests(self, oGen):
     1271        """ Generate divide error tests (raises X86_XCPT_DE). """
     1272        oGen.write('%ifdef VBINSTST_CAN_DO_TRAPS\n');
     1273
     1274        # We do one register variation here, assuming the standard test has got them covered.
     1275        # Register tests
     1276        if True:
     1277            iOp2 = oGen.oTarget.randGRegNoSp();
     1278            while iOp2 == X86_GREG_xAX or iOp2 == X86_GREG_xDX:
     1279                iOp2 = oGen.oTarget.randGRegNoSp();
     1280
     1281            for cbEffOp in ( 8, 4, 2, 1 ):
     1282                if cbEffOp > oGen.oTarget.getMaxOpBytes():
     1283                    continue;
     1284                oGen.write('; cbEffOp=%u iOp2=%u\n' % (cbEffOp, iOp2,));
     1285
     1286                for iDividend, iDivisor in self.generateInputsXcpt(cbEffOp, fLong = not oGen.isTiny()):
     1287                    oGen.newSubTest();
     1288                    if cbEffOp > 1:
     1289                        self.generateOneDivideErrorTestGreg(oGen, cbEffOp, iOp2, iDividend, iDivisor);
     1290                    else:
     1291                        self.generateOneDivideErrorTestGreg8Bit(oGen, cbEffOp, iOp2, iDividend, iDivisor);
     1292
     1293        oGen.write('%endif ; VBINSTST_CAN_DO_TRAPS\n');
     1294        return True;
     1295
     1296
    11571297    def generateTest(self, oGen, sTestFnName):
    11581298        oGen.write('VBINSTST_BEGINPROC %s\n' % (sTestFnName,));
     
    11601300
    11611301        self.generateStandardTests(oGen);
     1302        self.generateDivideErrorTests(oGen);
    11621303
    11631304        #oGen.write('        int3\n');
     
    13811522        return self._cSibIndexPerRun;
    13821523
     1524    def isTiny(self):
     1525        """ Checks if we're in tiny mode."""
     1526        return self.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny;
     1527
    13831528
    13841529    #
     
    14461591                   'VBINSTST_GLOBALNAME_EX g_uVBInsTstSubTestIndicator, data hidden\n'
    14471592                   '        dd      0\n'
     1593                   '%ifdef VBINSTST_CAN_DO_TRAPS\n'
     1594                   'VBINSTST_TRAP_RECS_BEGIN\n'
     1595                   '%endif\n'
    14481596                   'VBINSTST_BEGINCODE\n'
    14491597                   );
     
    16931841        """
    16941842
     1843        # Terminate the trap records.
     1844        self.write('\n\n'
     1845                   ';\n'
     1846                   '; Terminate the trap records\n'
     1847                   ';\n'
     1848                   'VBINSTST_BEGINDATA\n'
     1849                   '%ifdef VBINSTST_CAN_DO_TRAPS\n'
     1850                   'VBINSTST_TRAP_RECS_END\n'
     1851                   '%endif\n'
     1852                   'VBINSTST_BEGINCODE\n');
     1853
    16951854        # Register checking functions.
    16961855        for sName in self._dCheckFns:
     
    17881947                       '        MY_PUSH_ALL\n'
    17891948                       '        sub xSP, 40h\n'
     1949                       '%ifdef VBINSTST_CAN_DO_TRAPS\n'
     1950                       '        VBINSTST_TRAP_RECS_INSTALL\n'
     1951                       '%endif\n'
    17901952                       '\n');
    17911953
     
    18061968
    18071969            self.write('\n'
     1970                       '%ifdef VBINSTST_CAN_DO_TRAPS\n'
     1971                       '        VBINSTST_TRAP_RECS_UNINSTALL\n'
     1972                       '%endif\n'
    18081973                       '        add  xSP, 40h\n'
    18091974                       '        MY_POP_ALL\n'
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