Changeset 47132 in vbox for trunk/src/VBox/VMM/testcase/Instructions/InstructionTestGen.py
- Timestamp:
- Jul 14, 2013 12:06:54 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/testcase/Instructions/InstructionTestGen.py
r47047 r47132 944 944 self.fIsIDiv = fIsIDiv; 945 945 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 946 992 def generateInputsNoXcpt(self, cbEffOp, fLong = False): 947 993 """ Generate inputs for cbEffOp. Returns a list of pairs, dividen + divisor. """ … … 952 998 953 999 # 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) 989 1001 990 1002 # random tests. … … 992 1004 for _ in range(6 if fLong else 2): 993 1005 while True: 994 uDivisor = randSxx(cbEffOp * 4);1006 uDivisor = randSxx(cbEffOp * 8); 995 1007 if uDivisor == 0 or uDivisor >= uStep or uDivisor < -uStep: 996 1008 continue; 997 uDividend = randSxx(cbEffOp * 8);1009 uDividend = randSxx(cbEffOp * 16); 998 1010 uResult = uDividend / uDivisor; 999 1011 if uResult >= uStep or uResult <= -uStep: # exclude difficulties … … 1004 1016 for _ in range(6 if fLong else 2): 1005 1017 while True: 1006 uDivisor = randUxx(cbEffOp * 4);1018 uDivisor = randUxx(cbEffOp * 8); 1007 1019 if uDivisor == 0 or uDivisor >= uStep: 1008 1020 continue; 1009 uDividend = randUxx(cbEffOp * 8);1021 uDividend = randUxx(cbEffOp * 16); 1010 1022 uResult = uDividend / uDivisor; 1011 1023 if uResult >= uStep: … … 1155 1167 return True; 1156 1168 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 1157 1297 def generateTest(self, oGen, sTestFnName): 1158 1298 oGen.write('VBINSTST_BEGINPROC %s\n' % (sTestFnName,)); … … 1160 1300 1161 1301 self.generateStandardTests(oGen); 1302 self.generateDivideErrorTests(oGen); 1162 1303 1163 1304 #oGen.write(' int3\n'); … … 1381 1522 return self._cSibIndexPerRun; 1382 1523 1524 def isTiny(self): 1525 """ Checks if we're in tiny mode.""" 1526 return self.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny; 1527 1383 1528 1384 1529 # … … 1446 1591 'VBINSTST_GLOBALNAME_EX g_uVBInsTstSubTestIndicator, data hidden\n' 1447 1592 ' dd 0\n' 1593 '%ifdef VBINSTST_CAN_DO_TRAPS\n' 1594 'VBINSTST_TRAP_RECS_BEGIN\n' 1595 '%endif\n' 1448 1596 'VBINSTST_BEGINCODE\n' 1449 1597 ); … … 1693 1841 """ 1694 1842 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 1695 1854 # Register checking functions. 1696 1855 for sName in self._dCheckFns: … … 1788 1947 ' MY_PUSH_ALL\n' 1789 1948 ' sub xSP, 40h\n' 1949 '%ifdef VBINSTST_CAN_DO_TRAPS\n' 1950 ' VBINSTST_TRAP_RECS_INSTALL\n' 1951 '%endif\n' 1790 1952 '\n'); 1791 1953 … … 1806 1968 1807 1969 self.write('\n' 1970 '%ifdef VBINSTST_CAN_DO_TRAPS\n' 1971 ' VBINSTST_TRAP_RECS_UNINSTALL\n' 1972 '%endif\n' 1808 1973 ' add xSP, 40h\n' 1809 1974 ' MY_POP_ALL\n'
Note:
See TracChangeset
for help on using the changeset viewer.