- Timestamp:
- Jun 28, 2013 3:03:19 AM (12 years ago)
- Location:
- trunk/src/VBox/VMM/testcase/Instructions
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/testcase/Instructions/InstructionTestGen.py
r46853 r46856 70 70 ## @} 71 71 72 ## @name P Refixes72 ## @name Prefixes 73 73 ## @ 74 74 X86_OP_PRF_CS = 0x2e; … … 90 90 91 91 92 ## @name General registers 93 ## @ 94 X86_GREG_xAX = 0 95 X86_GREG_xCX = 1 96 X86_GREG_xDX = 2 97 X86_GREG_xBX = 3 98 X86_GREG_xSP = 4 99 X86_GREG_xBP = 5 100 X86_GREG_xSI = 6 101 X86_GREG_xDI = 7 102 X86_GREG_x8 = 8 103 X86_GREG_x9 = 9 104 X86_GREG_x10 = 10 105 X86_GREG_x11 = 11 106 X86_GREG_x12 = 12 107 X86_GREG_x13 = 13 108 X86_GREG_x14 = 14 109 X86_GREG_x15 = 15 110 ## @} 111 112 92 113 ## @name Register names. 93 114 ## @{ … … 104 125 g_asGRegs8 = ('al', 'cl', 'dl', 'bl', 'ah', 'ch', 'dh', 'bh'); 105 126 g_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'); 107 129 ## @} 108 130 … … 128 150 129 151 def 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. """ 131 153 return [randUxx(cBits) for _ in range(cElements)]; 132 154 ## @} … … 174 196 return u32; 175 197 return u32 - UINT32_MAX - 1; 198 199 def 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 218 def 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; 176 236 177 237 def gregName(iReg, cBits, fRexByteRegs = True): … … 264 324 return self.getDefAddrBits() / 8; 265 325 266 def getGRegCount(self ):326 def getGRegCount(self, cbEffBytes = 4): 267 327 """ Get the number of general registers. """ 268 328 if self.sInstrSet == self.ksInstrSet_64: 329 if cbEffBytes == 1: 330 return 16 + 4; 269 331 return 16; 270 332 return 8; … … 282 344 return [32, 16]; 283 345 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 284 357 285 358 … … 380 453 def writeInstrGregGreg(self, cbEffOp, iOp1, iOp2, oGen): 381 454 """ 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),)); 392 458 return True; 393 459 … … 535 601 ## @} 536 602 537 def generateOneStdTestGregGreg(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp 2, 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. """ 539 605 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],)); 542 608 self.writeInstrGregGreg(cbEffOp, iOp1, iOp2, oGen); 543 609 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),)); 545 611 _ = cbMaxOp; 546 612 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 547 646 548 647 def generateOneStdTestGregMemNoSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult): … … 640 739 iLongOp1 = oGen.oTarget.randGRegNoSp(); 641 740 iLongOp2 = oGen.oTarget.randGRegNoSp(); 642 oOp2Range = range(oGen.oTarget.getGRegCount());643 741 oOp1MemRange = range(oGen.oTarget.getGRegCount()); 742 oOp2Range = None; 644 743 if oGen.oOptions.sTestSize == InstructionTestGen.ksTestSize_Tiny: 645 744 oOp2Range = [iLongOp2,]; … … 651 750 if cbEffOp > cbMaxOp: 652 751 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. 656 760 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)); 659 768 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);662 769 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); 664 777 665 778 # Memory test. 666 if True:779 if False: 667 780 for cbEffOp in self.acbOpVars: 668 781 if cbEffOp > cbMaxOp: 669 782 continue; 670 783 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. 673 786 for cAddrBits in oGen.oTarget.getAddrModes(): 674 787 auInputs = auLongInputs if iOp1 == iLongOp1 and False else auShortInputs; … … 1150 1263 # Register checking functions. 1151 1264 for sName in self.dCheckFns: 1152 # Decode the name.1153 1265 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];1164 1266 sPushSize = 'dword'; 1165 1267 1166 # Write the test1268 # Prologue 1167 1269 self.write('\n\n' 1168 '; Checks tworegister values, expected values pushed on the stack.\n'1169 1270 '; Checks 1 or more register values, expected values pushed on the stack.\n' 1271 '; To save space, the callee cleans up the stack.' 1170 1272 '; Ref count: %u\n' 1171 'VBINSTST_BEGINPROC Common_Check_%s _%s\n'1273 'VBINSTST_BEGINPROC Common_Check_%s\n' 1172 1274 ' 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],)); 1209 1304 self.write(' MY_POP_FLAGS\n' 1210 1305 ' 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,)); 1214 1309 1215 1310 # memory setup functions -
trunk/src/VBox/VMM/testcase/Instructions/env-common.mac
r46731 r46856 100 100 ;******************************************************************************* 101 101 102 VBINSTST_BEGINCODE 102 103 103 104 ;; … … 113 114 VBINSTST_BEGINPROC Common_BadValue 114 115 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 115 120 116 121 %ifdef ASM_CALL64_GCC … … 123 128 124 129 %elifdef ASM_CALL64_MSC 125 sub rsp, 28h126 130 mov r10d, [VBINSTST_NAME(g_uVBInsTstSubTestIndicator) wrt rip] 127 131 mov [rsp + 20h], r10 … … 131 135 lea rcx, [.szFmt wrt rip] 132 136 VBINSTST_CALL_FN_FAILURE_4 133 add rsp, 28h134 137 135 138 %else … … 138 141 mov sAX, [xBP + 4 + xCB + 4] ; actual 139 142 mov sDX, [xBP + 4 + xCB + 8] ; reg# 140 pushsBX141 pushsCX142 pushsAX143 pushsDX144 push.szFmt143 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 145 148 VBINSTST_CALL_FN_FAILURE_4 146 add esp, 4*sCB + xCB 147 %endif 149 %endif 150 151 mov xSP, [xSP + 38h] 148 152 MY_POP_ALL 149 153 ret -
trunk/src/VBox/VMM/testcase/Instructions/env-iprt-r3.mac
r46543 r46856 64 64 ;; Call RTTestISub like function. 65 65 %define VBINSTST_CALL_FN_SUB_TEST call IMP2(RTTestISub) 66 extern IMPNAME(RTTestISub) 66 EXTERN_IMP2 RTTestISub 67 67 68 68 ;; Call RTTestIFailure like function with simple message.
Note:
See TracChangeset
for help on using the changeset viewer.