VirtualBox

Ignore:
Timestamp:
Nov 26, 2013 6:09:07 PM (11 years ago)
Author:
vboxsync
Message:

IEM: Fixed several instances of iEffSeg being accessed before the decoding was over, causing iPXE to guru on us. Implemented DAS and DAA to verify the previous fix.

File:
1 edited

Legend:

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

    r48346 r49671  
    137137## @}
    138138
     139## @name EFLAGS/RFLAGS/EFLAGS
     140## @{
     141X86_EFL_CF              = RT_BIT_32(0);
     142X86_EFL_CF_BIT          = 0;
     143X86_EFL_1               = RT_BIT_32(1);
     144X86_EFL_PF              = RT_BIT_32(2);
     145X86_EFL_AF              = RT_BIT_32(4);
     146X86_EFL_AF_BIT          = 4;
     147X86_EFL_ZF              = RT_BIT_32(6);
     148X86_EFL_ZF_BIT          = 6;
     149X86_EFL_SF              = RT_BIT_32(7);
     150X86_EFL_SF_BIT          = 7;
     151X86_EFL_TF              = RT_BIT_32(8);
     152X86_EFL_IF              = RT_BIT_32(9);
     153X86_EFL_DF              = RT_BIT_32(10);
     154X86_EFL_OF              = RT_BIT_32(11);
     155X86_EFL_OF_BIT          = 11;
     156X86_EFL_IOPL            = (RT_BIT_32(12) | RT_BIT_32(13));
     157X86_EFL_NT              = RT_BIT_32(14);
     158X86_EFL_RF              = RT_BIT_32(16);
     159X86_EFL_VM              = RT_BIT_32(17);
     160X86_EFL_AC              = RT_BIT_32(18);
     161X86_EFL_VIF             = RT_BIT_32(19);
     162X86_EFL_VIP             = RT_BIT_32(20);
     163X86_EFL_ID              = RT_BIT_32(21);
     164X86_EFL_LIVE_MASK       = 0x003f7fd5;
     165X86_EFL_RA1_MASK        = RT_BIT_32(1);
     166X86_EFL_IOPL_SHIFT      = 12;
     167X86_EFL_STATUS_BITS     = ( X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF );
     168## @}
    139169
    140170## @name Random
     
    13071337
    13081338
     1339class 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
    13091418
    13101419##
     
    13161425    InstrTest_DivIDiv(fIsIDiv = False),
    13171426    InstrTest_DivIDiv(fIsIDiv = True),
     1427    InstrTest_DaaDas(fIsDas = False),
     1428    InstrTest_DaaDas(fIsDas = True),
    13181429];
    13191430
     
    13351446    kasTestSizes = ( ksTestSize_Large, ksTestSize_Medium, ksTestSize_Tiny );
    13361447
     1448    ## The prefix for the checker functions.
     1449    ksCheckerPrefix   = 'Common_Check_'
    13371450
    13381451
     
    14211534        return True;
    14221535
     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
    14231543    def needGRegChecker(self, iReg1, iReg2 = None, iReg3 = None):
    14241544        """
     
    14391559            self._dCheckFns[sName]  = 1;
    14401560
    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;
    14421576
    14431577    def needGRegMemSetup(self, cAddrBits, cbEffOp, iBaseReg = None, offDisp = None, iIndexReg = None, iScale = 1):
     
    15231657        """ Checks if we're in tiny mode."""
    15241658        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;
    15251663
    15261664
     
    18742012            sPushSize = 'dword';
    18752013
    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,));
    19132084
    19142085        # memory setup functions
     
    19502121            for iInstrTest in range(iInstrTestStart, iInstrTestEnd):
    19512122                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));
    19602132
    19612133            # Generate the main function.
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