Changeset 49671 in vbox for trunk/src/VBox/VMM/testcase/Instructions/InstructionTestGen.py
- Timestamp:
- Nov 26, 2013 6:09:07 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/testcase/Instructions/InstructionTestGen.py
r48346 r49671 137 137 ## @} 138 138 139 ## @name EFLAGS/RFLAGS/EFLAGS 140 ## @{ 141 X86_EFL_CF = RT_BIT_32(0); 142 X86_EFL_CF_BIT = 0; 143 X86_EFL_1 = RT_BIT_32(1); 144 X86_EFL_PF = RT_BIT_32(2); 145 X86_EFL_AF = RT_BIT_32(4); 146 X86_EFL_AF_BIT = 4; 147 X86_EFL_ZF = RT_BIT_32(6); 148 X86_EFL_ZF_BIT = 6; 149 X86_EFL_SF = RT_BIT_32(7); 150 X86_EFL_SF_BIT = 7; 151 X86_EFL_TF = RT_BIT_32(8); 152 X86_EFL_IF = RT_BIT_32(9); 153 X86_EFL_DF = RT_BIT_32(10); 154 X86_EFL_OF = RT_BIT_32(11); 155 X86_EFL_OF_BIT = 11; 156 X86_EFL_IOPL = (RT_BIT_32(12) | RT_BIT_32(13)); 157 X86_EFL_NT = RT_BIT_32(14); 158 X86_EFL_RF = RT_BIT_32(16); 159 X86_EFL_VM = RT_BIT_32(17); 160 X86_EFL_AC = RT_BIT_32(18); 161 X86_EFL_VIF = RT_BIT_32(19); 162 X86_EFL_VIP = RT_BIT_32(20); 163 X86_EFL_ID = RT_BIT_32(21); 164 X86_EFL_LIVE_MASK = 0x003f7fd5; 165 X86_EFL_RA1_MASK = RT_BIT_32(1); 166 X86_EFL_IOPL_SHIFT = 12; 167 X86_EFL_STATUS_BITS = ( X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF ); 168 ## @} 139 169 140 170 ## @name Random … … 1307 1337 1308 1338 1339 class InstrTest_DaaDas(InstrTestBase): 1340 """ Tests the DAA and DAS instructions. """ 1341 1342 def __init__(self, fIsDas): 1343 InstrTestBase.__init__(self, 'das' if fIsDas else 'daa'); 1344 self.fIsDas = fIsDas; 1345 1346 def isApplicable(self, oGen): 1347 return not oGen.oTarget.is64Bit(); 1348 1349 def generateTest(self, oGen, sTestFnName): 1350 if self.fIsDas: from itgTableDas import g_aItgDasResults as aItgResults; 1351 else: from itgTableDaa import g_aItgDaaResults as aItgResults; 1352 cMax = len(aItgResults); 1353 if oGen.isTiny(): 1354 cMax = 64; 1355 1356 oGen.write('VBINSTST_BEGINPROC %s\n' % (sTestFnName,)); 1357 oGen.write(' xor ebx, ebx\n'); 1358 oGen.write('.das_loop:\n'); 1359 # Save the loop variable so we can load known values. 1360 oGen.write(' push ebx\n'); 1361 oGen.newSubTestEx('ebx'); 1362 1363 # Push the results. 1364 oGen.write(' movzx eax, byte [.abAlResults + ebx]\n'); 1365 oGen.write(' or eax, %#x\n' % (oGen.au32Regs[X86_GREG_xAX] & ~0xff,)); 1366 oGen.write(' push eax\n'); 1367 oGen.write(' movzx eax, byte [.aFlagsResults + ebx]\n'); 1368 oGen.write(' push eax\n'); 1369 # Calc and push the inputs. 1370 oGen.write(' mov eax, ebx\n'); 1371 oGen.write(' shr eax, 2\n'); 1372 oGen.write(' and eax, 0ffh\n'); 1373 oGen.write(' or eax, %#x\n' % (oGen.au32Regs[X86_GREG_xAX] & ~0xff,)); 1374 oGen.write(' push eax\n'); 1375 1376 oGen.write(' pushfd\n') 1377 oGen.write(' and dword [xSP], ~(X86_EFL_CF | X86_EFL_AF)\n'); 1378 oGen.write(' mov al, bl\n'); 1379 oGen.write(' and al, 2\n'); 1380 oGen.write(' shl al, X86_EFL_AF_BIT - 1\n'); 1381 oGen.write(' or [xSP], al\n'); 1382 oGen.write(' mov al, bl\n'); 1383 oGen.write(' and al, X86_EFL_CF\n'); 1384 oGen.write(' or [xSP], al\n'); 1385 1386 # Load register values and do the test. 1387 oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n'); 1388 oGen.write(' popfd\n'); 1389 oGen.write(' pop eax\n'); 1390 if self.fIsDas: 1391 oGen.write(' das\n'); 1392 else: 1393 oGen.write(' daa\n'); 1394 1395 # Verify the results. 1396 fFlagsToCheck = X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_ZF; 1397 oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needFlagsGRegChecker(fFlagsToCheck, X86_GREG_xAX),)); 1398 1399 # Restore the loop variable and advance. 1400 oGen.write(' pop ebx\n'); 1401 oGen.write(' inc ebx\n'); 1402 oGen.write(' cmp ebx, %#x\n' % (cMax,)); 1403 oGen.write(' jb .das_loop\n'); 1404 1405 oGen.write(' ret\n'); 1406 1407 oGen.write('.abAlResults:\n'); 1408 for i in range(cMax): 1409 oGen.write(' db %#x\n' % (aItgResults[i][0],)); 1410 1411 oGen.write('.aFlagsResults:\n'); 1412 for i in range(cMax): 1413 oGen.write(' db %#x\n' % (aItgResults[i][1],)); 1414 1415 oGen.write('VBINSTST_ENDPROC %s\n' % (sTestFnName,)); 1416 return True; 1417 1309 1418 1310 1419 ## … … 1316 1425 InstrTest_DivIDiv(fIsIDiv = False), 1317 1426 InstrTest_DivIDiv(fIsIDiv = True), 1427 InstrTest_DaaDas(fIsDas = False), 1428 InstrTest_DaaDas(fIsDas = True), 1318 1429 ]; 1319 1430 … … 1335 1446 kasTestSizes = ( ksTestSize_Large, ksTestSize_Medium, ksTestSize_Tiny ); 1336 1447 1448 ## The prefix for the checker functions. 1449 ksCheckerPrefix = 'Common_Check_' 1337 1450 1338 1451 … … 1421 1534 return True; 1422 1535 1536 def newSubTestEx(self, sIndicator): 1537 """ 1538 Indicates that a new subtest has started. 1539 """ 1540 self.write(' mov dword [VBINSTST_NAME(g_uVBInsTstSubTestIndicator) xWrtRIP], %s\n' % (sIndicator, )); 1541 return True; 1542 1423 1543 def needGRegChecker(self, iReg1, iReg2 = None, iReg3 = None): 1424 1544 """ … … 1439 1559 self._dCheckFns[sName] = 1; 1440 1560 1441 return 'Common_Check_' + sName; 1561 return self.ksCheckerPrefix + sName; 1562 1563 def needFlagsGRegChecker(self, fFlagsToCheck, iReg1, iReg2 = None, iReg3 = None): 1564 """ 1565 Records the need for a given rFLAGS + register checker function, returning its label. 1566 """ 1567 sWorkerName = self.needGRegChecker(iReg1, iReg2, iReg3); 1568 1569 sName = 'eflags_%#x_%s' % (fFlagsToCheck, sWorkerName[len(self.ksCheckerPrefix):]); 1570 if sName in self._dCheckFns: 1571 self._dCheckFns[sName] += 1; 1572 else: 1573 self._dCheckFns[sName] = 1; 1574 1575 return self.ksCheckerPrefix + sName; 1442 1576 1443 1577 def needGRegMemSetup(self, cAddrBits, cbEffOp, iBaseReg = None, offDisp = None, iIndexReg = None, iScale = 1): … … 1523 1657 """ Checks if we're in tiny mode.""" 1524 1658 return self.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny; 1659 1660 def isMedium(self): 1661 """ Checks if we're in medium mode.""" 1662 return self.oOptions.sTestSize == InstructionTestGen.ksTestSize_Medium; 1525 1663 1526 1664 … … 1874 2012 sPushSize = 'dword'; 1875 2013 1876 # Prologue 1877 self.write('\n\n' 1878 '; Checks 1 or more register values, expected values pushed on the stack.\n' 1879 '; To save space, the callee cleans up the stack.' 1880 '; Ref count: %u\n' 1881 'VBINSTST_BEGINPROC Common_Check_%s\n' 1882 ' MY_PUSH_FLAGS\n' 1883 % ( self._dCheckFns[sName], sName, ) ); 1884 1885 # Register checks. 1886 for i in range(len(asRegs)): 1887 sReg = asRegs[i]; 1888 iReg = self.oTarget.asGRegs.index(sReg); 1889 if i == asRegs.index(sReg): # Only check once, i.e. input = output reg. 1890 self.write(' cmp %s, [xSP + MY_PUSH_FLAGS_SIZE + xCB + sCB * %u]\n' 1891 ' je .equal%u\n' 1892 ' push %s %u ; register number\n' 1893 ' push %s ; actual\n' 1894 ' mov %s, [xSP + sCB*2 + MY_PUSH_FLAGS_SIZE + xCB + sCB * %u]\n' 1895 ' push %s ; expected\n' 1896 ' call VBINSTST_NAME(Common_BadValue)\n' 1897 '.equal%u:\n' 1898 % ( sReg, i, i, sPushSize, iReg, sReg, sReg, i, sReg, i, ) ); 1899 1900 1901 # Restore known register values and check the other registers. 1902 for sReg in asRegs: 1903 if self.oTarget.is64Bit(): 1904 self.write(' mov %s, [g_u64KnownValue_%s wrt rip]\n' % (sReg, sReg,)); 1905 else: 1906 iReg = self.oTarget.asGRegs.index(sReg) 1907 self.write(' mov %s, 0x%x\n' % (sReg, self.au32Regs[iReg],)); 1908 self.write(' MY_POP_FLAGS\n' 1909 ' call VBINSTST_NAME(Common_CheckKnownValues)\n' 1910 ' ret sCB*%u\n' 1911 'VBINSTST_ENDPROC Common_Check_%s\n' 1912 % (len(asRegs), sName,)); 2014 # Do we check eflags first. 2015 if asRegs[0] == 'eflags': 2016 asRegs.pop(0); 2017 sFlagsToCheck = asRegs.pop(0); 2018 self.write('\n\n' 2019 '; Check flags and then defers to the register-only checker\n' 2020 '; To save space, the callee cleans up the stack.' 2021 '; Ref count: %u\n' 2022 'VBINSTST_BEGINPROC %s%s\n' 2023 ' MY_PUSH_FLAGS\n' 2024 ' push sAX\n' 2025 ' mov sAX, [xSP + sCB]\n' 2026 ' and sAX, %s\n' 2027 ' cmp sAX, [xSP + xCB + sCB*2]\n' 2028 ' je .equal\n' 2029 % ( self._dCheckFns[sName], self.ksCheckerPrefix, sName, 2030 sFlagsToCheck,)); 2031 self.write(' push dword 0xef ; register number\n' 2032 ' push sAX ; actual\n' 2033 ' mov sAX, [xSP + xCB + sCB*4]\n' 2034 ' push sAX ; expected\n' 2035 ' call VBINSTST_NAME(Common_BadValue)\n'); 2036 self.write('.equal:\n' 2037 ' mov xAX, [xSP + sCB*2]\n' # Remove the expected eflags value from the stack frame. 2038 ' mov [xSP + sCB*2 + xCB + sCB - xCB], xAX\n' 2039 ' pop sAX\n' 2040 ' MY_POP_FLAGS\n' 2041 ' lea xSP, [xSP + sCB]\n' 2042 ' jmp VBINSTST_NAME(Common_Check_%s)\n' 2043 'VBINSTST_ENDPROC %s%s\n' 2044 % ( '_'.join(asRegs), 2045 self.ksCheckerPrefix, sName,) ); 2046 else: 2047 # Prologue 2048 self.write('\n\n' 2049 '; Checks 1 or more register values, expected values pushed on the stack.\n' 2050 '; To save space, the callee cleans up the stack.' 2051 '; Ref count: %u\n' 2052 'VBINSTST_BEGINPROC %s%s\n' 2053 ' MY_PUSH_FLAGS\n' 2054 % ( self._dCheckFns[sName], self.ksCheckerPrefix, sName, ) ); 2055 2056 # Register checks. 2057 for i in range(len(asRegs)): 2058 sReg = asRegs[i]; 2059 iReg = self.oTarget.asGRegs.index(sReg); 2060 if i == asRegs.index(sReg): # Only check once, i.e. input = output reg. 2061 self.write(' cmp %s, [xSP + MY_PUSH_FLAGS_SIZE + xCB + sCB * %u]\n' 2062 ' je .equal%u\n' 2063 ' push %s %u ; register number\n' 2064 ' push %s ; actual\n' 2065 ' mov %s, [xSP + sCB*2 + MY_PUSH_FLAGS_SIZE + xCB + sCB * %u]\n' 2066 ' push %s ; expected\n' 2067 ' call VBINSTST_NAME(Common_BadValue)\n' 2068 '.equal%u:\n' 2069 % ( sReg, i, i, sPushSize, iReg, sReg, sReg, i, sReg, i, ) ); 2070 2071 2072 # Restore known register values and check the other registers. 2073 for sReg in asRegs: 2074 if self.oTarget.is64Bit(): 2075 self.write(' mov %s, [g_u64KnownValue_%s wrt rip]\n' % (sReg, sReg,)); 2076 else: 2077 iReg = self.oTarget.asGRegs.index(sReg) 2078 self.write(' mov %s, 0x%x\n' % (sReg, self.au32Regs[iReg],)); 2079 self.write(' MY_POP_FLAGS\n' 2080 ' call VBINSTST_NAME(Common_CheckKnownValues)\n' 2081 ' ret sCB*%u\n' 2082 'VBINSTST_ENDPROC %s%s\n' 2083 % (len(asRegs), self.ksCheckerPrefix, sName,)); 1913 2084 1914 2085 # memory setup functions … … 1950 2121 for iInstrTest in range(iInstrTestStart, iInstrTestEnd): 1951 2122 oInstrTest = g_aoInstructionTests[iInstrTest]; 1952 self.write('\n' 1953 '\n' 1954 ';\n' 1955 '; %s\n' 1956 ';\n' 1957 % (oInstrTest.sName,)); 1958 self._randInitIndexes(); 1959 oInstrTest.generateTest(self, self._calcTestFunctionName(oInstrTest, iInstrTest)); 2123 if oInstrTest.isApplicable(self): 2124 self.write('\n' 2125 '\n' 2126 ';\n' 2127 '; %s\n' 2128 ';\n' 2129 % (oInstrTest.sName,)); 2130 self._randInitIndexes(); 2131 oInstrTest.generateTest(self, self._calcTestFunctionName(oInstrTest, iInstrTest)); 1960 2132 1961 2133 # Generate the main function.
Note:
See TracChangeset
for help on using the changeset viewer.