VirtualBox

Changeset 46856 in vbox for trunk


Ignore:
Timestamp:
Jun 28, 2013 3:03:19 AM (12 years ago)
Author:
vboxsync
Message:

8-bit high register hell (reg/reg only so far).

Location:
trunk/src/VBox/VMM/testcase/Instructions
Files:
3 edited

Legend:

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

    r46853 r46856  
    7070## @}
    7171
    72 ## @name PRefixes
     72## @name Prefixes
    7373## @
    7474X86_OP_PRF_CS       = 0x2e;
     
    9090
    9191
     92## @name General registers
     93## @
     94X86_GREG_xAX        = 0
     95X86_GREG_xCX        = 1
     96X86_GREG_xDX        = 2
     97X86_GREG_xBX        = 3
     98X86_GREG_xSP        = 4
     99X86_GREG_xBP        = 5
     100X86_GREG_xSI        = 6
     101X86_GREG_xDI        = 7
     102X86_GREG_x8         = 8
     103X86_GREG_x9         = 9
     104X86_GREG_x10        = 10
     105X86_GREG_x11        = 11
     106X86_GREG_x12        = 12
     107X86_GREG_x13        = 13
     108X86_GREG_x14        = 14
     109X86_GREG_x15        = 15
     110## @}
     111
     112
    92113## @name Register names.
    93114## @{
     
    104125g_asGRegs8      = ('al',  'cl',  'dl',  'bl',  'ah',  'ch',  'dh',  'bh');
    105126g_asGRegs8Rex   = ('al',  'cl',  'dl',  'bl',  'spl', 'bpl', 'sil',  'dil',
    106                    'r8b', 'r9b', 'r10b', 'r11b', 'r12b', 'r13b', 'r14b', 'r15b');
     127                   'r8b', 'r9b', 'r10b', 'r11b', 'r12b', 'r13b', 'r14b', 'r15b',
     128                   'ah',  'ch',  'dh',  'bh');
    107129## @}
    108130
     
    128150
    129151def randUxxList(cBits, cElements):
    130     """ List of nsigned 8-, 16-, 32-, or 64-bit random numbers. """
     152    """ List of unsigned 8-, 16-, 32-, or 64-bit random numbers. """
    131153    return [randUxx(cBits) for _ in range(cElements)];
    132154## @}
     
    174196        return u32;
    175197    return u32 - UINT32_MAX - 1;
     198
     199def rotateLeftUxx(cBits, uVal, cShift):
     200    """ Rotate a xx-bit wide unsigned number to the left. """
     201    assert cShift < cBits;
     202
     203    if cBits == 16:
     204        uMask = UINT16_MAX;
     205    elif cBits == 32:
     206        uMask = UINT32_MAX;
     207    elif cBits == 64:
     208        uMask = UINT64_MAX;
     209    else:
     210        assert cBits == 8;
     211        uMask = UINT8_MAX;
     212
     213    uVal &= uMask;
     214    uRet = (uVal << cShift) & uMask;
     215    uRet |= (uVal >> (cBits - cShift));
     216    return uRet;
     217
     218def rotateRightUxx(cBits, uVal, cShift):
     219    """ Rotate a xx-bit wide unsigned number to the right. """
     220    assert cShift < cBits;
     221
     222    if cBits == 16:
     223        uMask = UINT16_MAX;
     224    elif cBits == 32:
     225        uMask = UINT32_MAX;
     226    elif cBits == 64:
     227        uMask = UINT64_MAX;
     228    else:
     229        assert cBits == 8;
     230        uMask = UINT8_MAX;
     231
     232    uVal &= uMask;
     233    uRet = (uVal >> cShift);
     234    uRet |= (uVal << (cBits - cShift)) & uMask;
     235    return uRet;
    176236
    177237def gregName(iReg, cBits, fRexByteRegs = True):
     
    264324        return self.getDefAddrBits() / 8;
    265325
    266     def getGRegCount(self):
     326    def getGRegCount(self, cbEffBytes = 4):
    267327        """ Get the number of general registers. """
    268328        if self.sInstrSet == self.ksInstrSet_64:
     329            if cbEffBytes == 1:
     330                return 16 + 4;
    269331            return 16;
    270332        return 8;
     
    282344            return [32, 16];
    283345        return [64, 32];
     346
     347    def is8BitHighGReg(self, cbEffOp, iGReg):
     348        """ Checks if the given register is a high 8-bit general register (AH, CH, DH or BH). """
     349        assert cbEffOp in [1, 2, 4, 8];
     350        if cbEffOp == 1:
     351            if iGReg >= 16:
     352                return True;
     353            if iGReg >= 4 and not self.is64Bit():
     354                return True;
     355        return False;
     356
    284357
    285358
     
    380453    def writeInstrGregGreg(self, cbEffOp, iOp1, iOp2, oGen):
    381454        """ Writes the instruction with two general registers as operands. """
    382         if cbEffOp == 8:
    383             oGen.write('        %s %s, %s\n' % (self.sInstr, g_asGRegs64[iOp1], g_asGRegs64[iOp2]));
    384         elif cbEffOp == 4:
    385             oGen.write('        %s %s, %s\n' % (self.sInstr, g_asGRegs32[iOp1], g_asGRegs32[iOp2]));
    386         elif cbEffOp == 2:
    387             oGen.write('        %s %s, %s\n' % (self.sInstr, g_asGRegs16[iOp1], g_asGRegs16[iOp2]));
    388         elif cbEffOp == 1:
    389             oGen.write('        %s %s, %s\n' % (self.sInstr, g_asGRegs8Rex[iOp1], g_asGRegs8Rex[iOp2]));
    390         else:
    391             assert False;
     455        fRexByteRegs = oGen.oTarget.is64Bit();
     456        oGen.write('        %s %s, %s\n'
     457                   % (self.sInstr, gregName(iOp1, cbEffOp * 8, fRexByteRegs),  gregName(iOp2, cbEffOp * 8, fRexByteRegs),));
    392458        return True;
    393459
     
    535601    ## @}
    536602
    537     def generateOneStdTestGregGreg(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult):
    538         """ Generate one standard test. """
     603    def generateOneStdTestGregGreg(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp1X, iOp2, iOp2X, uInput, uResult):
     604        """ Generate one standard instr greg,greg test. """
    539605        oGen.write('        call VBINSTST_NAME(Common_LoadKnownValues)\n');
    540         oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2], uInput,));
    541         oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[iOp2],));
     606        oGen.write('        mov     %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2X], uInput,));
     607        oGen.write('        push    %s\n' % (oGen.oTarget.asGRegs[iOp2X],));
    542608        self.writeInstrGregGreg(cbEffOp, iOp1, iOp2, oGen);
    543609        oGen.pushConst(uResult);
    544         oGen.write('        call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),));
     610        oGen.write('        call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1X, iOp2X),));
    545611        _ = cbMaxOp;
    546612        return True;
     613
     614    def generateOneStdTestGregGreg8BitHighPain(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput):
     615        """ High 8-bit registers are a real pain! """
     616        assert oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1) or oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2);
     617        # Figure out the register indexes of the max op sized regs involved.
     618        iOp1X = iOp1 & 3;
     619        iOp2X = iOp2 & 3;
     620        oGen.write('        ; iOp1=%u iOp1X=%u iOp2=%u iOp2X=%u\n' % (iOp1, iOp1X, iOp2, iOp2X,));
     621
     622        # Calculate unshifted result.
     623        if iOp1X != iOp2X:
     624            uCur = oGen.auRegValues[iOp1X];
     625            if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1):
     626                uCur = rotateRightUxx(cbMaxOp * 8, uCur, 8);
     627        else:
     628            uCur = uInput;
     629            if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1) != oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2):
     630                if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1):
     631                    uCur = rotateRightUxx(cbMaxOp * 8, uCur, 8);
     632                else:
     633                    uCur = rotateLeftUxx(cbMaxOp * 8, uCur, 8);
     634        uResult = self.fnCalcResult(cbEffOp, uInput, uCur, oGen);
     635
     636
     637        # Rotate the input and/or result to match their max-op-sized registers.
     638        if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2):
     639            uInput = rotateLeftUxx(cbMaxOp * 8, uInput, 8);
     640        if oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1):
     641            uResult = rotateLeftUxx(cbMaxOp * 8, uResult, 8);
     642
     643        # Hand it over to an overridable worker method.
     644        return self.generateOneStdTestGregGreg(oGen, cbEffOp, cbMaxOp, iOp1, iOp1X, iOp2, iOp2X, uInput, uResult);
     645
    547646
    548647    def generateOneStdTestGregMemNoSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult):
     
    640739        iLongOp1      = oGen.oTarget.randGRegNoSp();
    641740        iLongOp2      = oGen.oTarget.randGRegNoSp();
    642         oOp2Range     = range(oGen.oTarget.getGRegCount());
    643741        oOp1MemRange  = range(oGen.oTarget.getGRegCount());
     742        oOp2Range     = None;
    644743        if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
    645744            oOp2Range    = [iLongOp2,];
     
    651750                if cbEffOp > cbMaxOp:
    652751                    continue;
    653                 for iOp1 in range(oGen.oTarget.getGRegCount()):
    654                     if oGen.oTarget.asGRegsNoSp[iOp1] is None:
    655                         continue;
     752                oOp2Range = range(oGen.oTarget.getGRegCount(cbEffOp));
     753                if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny:
     754                    oOp2Range = [iLongOp2,];
     755                oGen.write('; cbEffOp=%u\n' % (cbEffOp,));
     756
     757                for iOp1 in range(oGen.oTarget.getGRegCount(cbEffOp)):
     758                    if iOp1 == X86_GREG_xSP:
     759                        continue; # Cannot test xSP atm.
    656760                    for iOp2 in oOp2Range:
    657                         if oGen.oTarget.asGRegsNoSp[iOp2] is None:
    658                             continue;
     761                        if   (iOp2 >= 16 and iOp1 in range(4, 16)) \
     762                          or (iOp1 >= 16 and iOp2 in range(4, 16)):
     763                            continue; # Any REX encoding turns AH,CH,DH,BH regs into SPL,BPL,SIL,DIL.
     764                        if iOp2 == X86_GREG_xSP:
     765                            continue; # Cannot test xSP atm.
     766
     767                        oGen.write('; iOp2=%u cbEffOp=%u\n' % (iOp2, cbEffOp));
    659768                        for uInput in (auLongInputs if iOp1 == iLongOp1 and iOp2 == iLongOp2 else auShortInputs):
    660                             uResult = self.fnCalcResult(cbEffOp, uInput,
    661                                                         oGen.auRegValues[iOp1] if iOp1 != iOp2 else uInput, oGen);
    662769                            oGen.newSubTest();
    663                             self.generateOneStdTestGregGreg(oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult);
     770                            if not oGen.oTarget.is8BitHighGReg(cbEffOp, iOp1) and not oGen.oTarget.is8BitHighGReg(cbEffOp, iOp2):
     771                                uCur = oGen.auRegValues[iOp1 & 15] if iOp1 != iOp2 else uInput;
     772                                uResult = self.fnCalcResult(cbEffOp, uInput, uCur, oGen);
     773                                self.generateOneStdTestGregGreg(oGen, cbEffOp, cbMaxOp, iOp1, iOp1 & 15, iOp2, iOp2 & 15,
     774                                                                uInput, uResult);
     775                            else:
     776                                self.generateOneStdTestGregGreg8BitHighPain(oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput);
    664777
    665778        # Memory test.
    666         if True:
     779        if False:
    667780            for cbEffOp in self.acbOpVars:
    668781                if cbEffOp > cbMaxOp:
    669782                    continue;
    670783                for iOp1 in oOp1MemRange:
    671                     if oGen.oTarget.asGRegsNoSp[iOp1] is None:
    672                         continue;
     784                    if iOp1 == X86_GREG_xSP:
     785                        continue; # Cannot test xSP atm.
    673786                    for cAddrBits in oGen.oTarget.getAddrModes():
    674787                        auInputs = auLongInputs if iOp1 == iLongOp1 and False else auShortInputs;
     
    11501263        # Register checking functions.
    11511264        for sName in self.dCheckFns:
    1152             # Decode the name.
    11531265            asRegs = sName.split('_');
    1154             sReg1 = asRegs[0];
    1155             iReg1 = self.oTarget.index(sReg1);
    1156             if len(asRegs) >= 2:
    1157                 sReg2 = None;
    1158                 iReg2 = None;
    1159 
    1160             iReg1 = iRegs & 0x1f;
    1161             sReg1 = self.oTarget.asGRegs[iReg1];
    1162             iReg2 = (iRegs >> 5) & 0x1f;
    1163             sReg2 = self.oTarget.asGRegs[iReg2];
    11641266            sPushSize = 'dword';
    11651267
    1166             # Write the test
     1268            # Prologue
    11671269            self.write('\n\n'
    1168                        '; Checks two register values, expected values pushed on the stack.\n'
    1169                         '; To save space, the callee cleans up the stack.'
     1270                       '; Checks 1 or more register values, expected values pushed on the stack.\n'
     1271                       '; To save space, the callee cleans up the stack.'
    11701272                       '; Ref count: %u\n'
    1171                        'VBINSTST_BEGINPROC Common_Check_%s_%s\n'
     1273                       'VBINSTST_BEGINPROC Common_Check_%s\n'
    11721274                       '        MY_PUSH_FLAGS\n'
    1173                        % ( self.dCheckFns[iRegs], sReg1, sReg2, ) );
    1174 
    1175             self.write('        cmp     %s, [xSP + MY_PUSH_FLAGS_SIZE + xCB]\n'
    1176                        '        je      .equal1\n'
    1177                        '        push    %s %u      ; register number\n'
    1178                        '        push    %s         ; actual\n'
    1179                        '        mov     %s, [xSP + sCB*2 + MY_PUSH_FLAGS_SIZE + xCB]\n'
    1180                        '        push    %s         ; expected\n'
    1181                        '        call    VBINSTST_NAME(Common_BadValue)\n'
    1182                        '        pop     %s\n'
    1183                        '        pop     %s\n'
    1184                        '        pop     %s\n'
    1185                        '.equal1:\n'
    1186                        % ( sReg1, sPushSize, iReg1, sReg1, sReg1, sReg1, sReg1, sReg1, sReg1, ) );
    1187             if iReg1 != iReg2: # If input and result regs are the same, only check the result.
    1188                 self.write('        cmp     %s, [xSP + sCB + MY_PUSH_FLAGS_SIZE + xCB]\n'
    1189                            '        je      .equal2\n'
    1190                            '        push    %s %u      ; register number\n'
    1191                            '        push    %s         ; actual\n'
    1192                            '        mov     %s, [xSP + sCB*3 + MY_PUSH_FLAGS_SIZE + xCB]\n'
    1193                            '        push    %s         ; expected\n'
    1194                            '        call    VBINSTST_NAME(Common_BadValue)\n'
    1195                            '        pop     %s\n'
    1196                            '        pop     %s\n'
    1197                            '        pop     %s\n'
    1198                            '.equal2:\n'
    1199                            % ( sReg2, sPushSize, iReg2, sReg2, sReg2, sReg2, sReg2, sReg2, sReg2, ) );
    1200 
    1201             if self.oTarget.is64Bit():
    1202                 self.write('        mov     %s, [g_u64KnownValue_%s wrt rip]\n' % (sReg1, sReg1,));
    1203                 if iReg1 != iReg2:
    1204                     self.write('        mov     %s, [g_u64KnownValue_%s wrt rip]\n' % (sReg2, sReg2,));
    1205             else:
    1206                 self.write('        mov     %s, 0x%x\n' % (sReg1, self.au32Regs[iReg1],));
    1207                 if iReg1 != iReg2:
    1208                     self.write('        mov     %s, 0x%x\n' % (sReg2, self.au32Regs[iReg2],));
     1275                       % ( self.dCheckFns[sName], sName, ) );
     1276
     1277            # Register checks.
     1278            iRegPrev = -1;
     1279            for i in range(len(asRegs)):
     1280                sReg = asRegs[i];
     1281                iReg = self.oTarget.asGRegs.index(sReg);
     1282                if i == asRegs.index(sReg): # Only check once, i.e. input = output reg.
     1283                    self.write('        cmp     %s, [xSP + MY_PUSH_FLAGS_SIZE + xCB + sCB * %u]\n'
     1284                               '        je      .equal%u\n'
     1285                               '        push    %s %u      ; register number\n'
     1286                               '        push    %s         ; actual\n'
     1287                               '        mov     %s, [xSP + sCB*2 + MY_PUSH_FLAGS_SIZE + xCB]\n'
     1288                               '        push    %s         ; expected\n'
     1289                               '        call    VBINSTST_NAME(Common_BadValue)\n'
     1290                               '        pop     %s\n'
     1291                               '        pop     %s\n'
     1292                               '        pop     %s\n'
     1293                               '.equal%u:\n'
     1294                           % ( sReg, i, i, sPushSize, iReg, sReg, sReg, sReg, sReg, sReg, sReg, i, ) );
     1295
     1296
     1297            # Restore known register values and check the other registers.
     1298            for sReg in asRegs:
     1299                if self.oTarget.is64Bit():
     1300                    self.write('        mov     %s, [g_u64KnownValue_%s wrt rip]\n' % (sReg, sReg,));
     1301                else:
     1302                    iReg = self.oTarget.asGRegs.index(sReg)
     1303                    self.write('        mov     %s, 0x%x\n' % (sReg, self.au32Regs[iReg],));
    12091304            self.write('        MY_POP_FLAGS\n'
    12101305                       '        call    VBINSTST_NAME(Common_CheckKnownValues)\n'
    1211                        '        ret     sCB*2\n'
    1212                        'VBINSTST_ENDPROC   Common_Check_%s_%s\n'
    1213                        % (sReg1, sReg2,));
     1306                       '        ret     sCB*%u\n'
     1307                       'VBINSTST_ENDPROC   Common_Check_%s\n'
     1308                       % (len(asRegs), sName,));
    12141309
    12151310        # memory setup functions
  • trunk/src/VBox/VMM/testcase/Instructions/env-common.mac

    r46731 r46856  
    100100;*******************************************************************************
    101101
     102VBINSTST_BEGINCODE
    102103
    103104;;
     
    113114VBINSTST_BEGINPROC Common_BadValue
    114115        MY_PUSH_ALL
     116        mov     xAX, xSP                ; 16-byte align the stack and reserve space for arguments and stuff.
     117        sub     xSP, 40h
     118        and     xSP, ~15
     119        mov     [xSP + 38h], xAX
    115120
    116121%ifdef ASM_CALL64_GCC
     
    123128
    124129%elifdef ASM_CALL64_MSC
    125         sub     rsp, 28h
    126130        mov     r10d, [VBINSTST_NAME(g_uVBInsTstSubTestIndicator) wrt rip]
    127131        mov     [rsp + 20h], r10
     
    131135        lea     rcx, [.szFmt wrt rip]
    132136        VBINSTST_CALL_FN_FAILURE_4
    133         add     rsp, 28h
    134137
    135138%else
     
    138141        mov     sAX, [xBP + 4 + xCB + 4] ; actual
    139142        mov     sDX, [xBP + 4 + xCB + 8] ; reg#
    140         push    sBX
    141         push    sCX
    142         push    sAX
    143         push    sDX
    144         push    .szFmt
     143        mov     [xSP + xCB + 3*sCB], sBX
     144        mov     [xSP + xCB + 2*sCB], sCX
     145        mov     [xSP + xCB + 1*sCB], sAX
     146        mov     [xSP + xCB], sDX
     147        mov     [xSP], RTCCPTR_PRE .szFmt
    145148        VBINSTST_CALL_FN_FAILURE_4
    146         add     esp, 4*sCB + xCB
    147 %endif
     149%endif
     150
     151        mov     xSP, [xSP + 38h]
    148152        MY_POP_ALL
    149153        ret
  • trunk/src/VBox/VMM/testcase/Instructions/env-iprt-r3.mac

    r46543 r46856  
    6464;; Call RTTestISub like function.
    6565%define VBINSTST_CALL_FN_SUB_TEST   call IMP2(RTTestISub)
    66 extern IMPNAME(RTTestISub)
     66EXTERN_IMP2 RTTestISub
    6767
    6868;; Call RTTestIFailure like function with simple message.
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