Changeset 46853 in vbox
- Timestamp:
- Jun 27, 2013 5:53:01 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 86806
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/testcase/Instructions/InstructionTestGen.py
r46771 r46853 392 392 return True; 393 393 394 395 394 def writeInstrGregPureRM(self, cbEffOp, iOp1, cAddrBits, iOp2, iMod, offDisp, oGen): 396 395 """ Writes the instruction with two general registers as operands. """ 397 if iOp2 == 13 and iMod == 0 and cAddrBits == 64: # Alt rip encoding, yasm isn't helping, do what we can. 398 if cbEffOp == 2: 399 oGen.write(' db %#04x\n' % (X86_OP_PRF_SIZE_OP,)); 400 bRex = X86_OP_REX_B; 401 if iOp1 >= 8: 402 bRex |= X86_OP_REX_R; 403 if cbEffOp == 8: 404 bRex |= X86_OP_REX_W; 405 oGen.write(' db %#04x\n' % (bRex,)); 406 if cbEffOp == 1: 407 oGen.write(' %s %s, [' % (self.sInstr, g_asGRegs8[iOp1 & 0x7],)); 408 else: 409 oGen.write(' %s %s, [' % (self.sInstr, g_asGRegs32[iOp1 & 0x7],)); 410 elif cbEffOp == 8: 411 oGen.write(' %s %s, [' % (self.sInstr, g_asGRegs64[iOp1],)); 396 oGen.write(' '); 397 if iOp2 == 13 and iMod == 0 and cAddrBits == 64: 398 oGen.write('altrexb '); # Alternative encoding for rip relative addressing. 399 if cbEffOp == 8: 400 oGen.write('%s %s, [' % (self.sInstr, g_asGRegs64[iOp1],)); 412 401 elif cbEffOp == 4: 413 oGen.write(' 402 oGen.write('%s %s, [' % (self.sInstr, g_asGRegs32[iOp1],)); 414 403 elif cbEffOp == 2: 415 oGen.write(' 404 oGen.write('%s %s, [' % (self.sInstr, g_asGRegs16[iOp1],)); 416 405 elif cbEffOp == 1: 417 oGen.write(' 406 oGen.write('%s %s, [' % (self.sInstr, g_asGRegs8Rex[iOp1],)); 418 407 else: 419 408 assert False; … … 443 432 return True; 444 433 445 def writeInstrGregSibLabel(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, oGen): 446 """ Writes the instruction taking a register and a lable, SIB form. """ 447 ## @todo Dunno how to convince yasm to generate these. Considering patching it. 448 oGen.write(' %s %s, [VBINSTST_NAME(g_u%sData) xWrtRIP]\n' 449 % (self.sInstr, gregName(iOp1, cbEffOp * 8),)); 434 def writeInstrGregSibLabel(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen): 435 """ Writes the instruction taking a register and a label (base only w/o reg), SIB form. """ 436 assert offDisp is None; assert iBaseReg in [5, 13]; assert iIndexReg == 4; assert cAddrBits != 16; 437 if cAddrBits == 64: 438 # Note! Cannot test this in 64-bit mode in any sensible way because the disp is 32-bit 439 # and we cannot (yet) make assumtions about where we're loaded. 440 ## @todo Enable testing this in environments where we can make assumptions (boot sector). 441 oGen.write(' %s %s, [VBINSTST_NAME(g_u%sData) xWrtRIP]\n' 442 % ( self.sInstr, gregName(iOp1, cbEffOp * 8), cbEffOp * 8,)); 443 else: 444 oGen.write(' altsibx%u %s %s, [VBINSTST_NAME(g_u%sData) xWrtRIP]\n' 445 % ( iScale, self.sInstr, gregName(iOp1, cbEffOp * 8), cbEffOp * 8,)); 450 446 return True; 451 447 452 448 def writeInstrGregSibScaledReg(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen): 453 ## @todo Dunno how to convince yasm to generate SIB variants for iScale == 1 here. Considering patching it. 454 oGen.write(' %s %s, [%s * %#x' 455 % (self.sInstr, gregName(iOp1, cbEffOp * 8), gregName(iIndexReg, cAddrBits), iScale,)); 449 """ Writes the instruction taking a register and disp+scaled register (no base reg), SIB form. """ 450 assert iBaseReg in [5, 13]; assert iIndexReg != 4; assert cAddrBits != 16; 451 # Note! Using altsibxN to force scaled encoding. This is only really a 452 # necessity for iScale=1, but doesn't hurt for the rest. 453 oGen.write(' altsibx%u %s %s, [%s * %#x' 454 % (iScale, self.sInstr, gregName(iOp1, cbEffOp * 8), gregName(iIndexReg, cAddrBits), iScale,)); 456 455 if offDisp is not None: 457 456 oGen.write(' + %#x' % (offDisp,)); 458 oGen.write('] ; iScale=%s\n' % (iScale,));457 oGen.write(']\n'); 459 458 _ = iBaseReg; 460 459 return True; 461 460 462 461 def writeInstrGregSibBase(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen): 463 ## @todo Dunno how to convince yasm to generate SIB variants for iScale == 1 here. Considering patching it.464 oGen.write(' %s %s, [%s'465 % ( self.sInstr, gregName(iOp1, cbEffOp * 8), gregName(iBaseReg, cAddrBits), iScale,));462 """ Writes the instruction taking a register and base only (with reg), SIB form. """ 463 oGen.write(' altsibx%u %s %s, [%s' 464 % (iScale, self.sInstr, gregName(iOp1, cbEffOp * 8), gregName(iBaseReg, cAddrBits),)); 466 465 if offDisp is not None: 467 466 oGen.write(' + %#x' % (offDisp,)); 468 oGen.write('] ; iScale=%s\n' % (iScale,));467 oGen.write(']\n'); 469 468 _ = iIndexReg; 470 469 return True; 471 470 472 471 def writeInstrGregSibBaseAndScaledReg(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen): 472 """ Writes tinstruction taking a register and full featured SIB form address. """ 473 # Note! From the looks of things, yasm will encode the following instructions the same way: 474 # mov eax, [rsi*1 + rbx] 475 # mov eax, [rbx + rsi*1] 476 # So, when there are two registers involved, the '*1' selects 477 # which is index and which is base. 478 oGen.write(' %s %s, [%s + %s * %u' 479 % ( self.sInstr, gregName(iOp1, cbEffOp * 8), 480 gregName(iBaseReg, cAddrBits), gregName(iIndexReg, cAddrBits), iScale,)); 481 if offDisp is not None: 482 oGen.write(' + %#x' % (offDisp,)); 483 oGen.write(']\n'); 473 484 return True; 474 485 … … 478 489 ## @name Memory setups 479 490 ## @{ 480 def generateMemSetupReadByLabel(self, oGen, c AddrBits, uInput):491 def generateMemSetupReadByLabel(self, oGen, cbEffOp, uInput): 481 492 """ Sets up memory for a memory read. """ 482 493 oGen.pushConst(uInput); … … 488 499 oGen.pushConst(uInput); 489 500 oGen.write(' call VBINSTST_NAME(%s)\n' 490 % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, i Reg1,offDisp),));501 % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iBaseReg = iReg1, offDisp = offDisp),)); 491 502 oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iReg1],)); 492 503 return True; 493 504 494 def generateMemSetupReadByScaledReg(self, oGen, cAddrBits, cbEffOp, i Reg2, iScale, uInput, offDisp = None):505 def generateMemSetupReadByScaledReg(self, oGen, cAddrBits, cbEffOp, iIndexReg, iScale, uInput, offDisp = None): 495 506 """ Sets up memory for a memory read indirectly addressed thru one register and optional displacement. """ 496 507 oGen.pushConst(uInput); 497 508 oGen.write(' call VBINSTST_NAME(%s)\n' 498 % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iReg2, offDisp, iScale = iScale),));499 oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[i Reg1],));509 % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, offDisp = offDisp, iIndexReg = iIndexReg, iScale = iScale),)); 510 oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iIndexReg],)); 500 511 return True; 501 512 … … 503 514 """ Sets up memory for a memory read indirectly addressed thru two registers with optional displacement. """ 504 515 oGen.pushConst(uInput); 505 if iScale == 1:506 516 oGen.write(' call VBINSTST_NAME(%s)\n' 507 % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iReg1, offDisp),)); 508 oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iReg1],)); 517 % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iBaseReg = iBaseReg, offDisp = offDisp, 518 iIndexReg = iIndexReg, iScale = iScale),)); 519 oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iBaseReg],)); 520 oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iIndexReg],)); 509 521 return True; 510 522 … … 565 577 return True; 566 578 567 def generateOneStdTestGregMem NoSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iMod,568 579 def generateOneStdTestGregMemSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iMod, # pylint: disable=R0913 580 iBaseReg, iIndexReg, iScale, uInput, uResult): 569 581 """ Generate one SIB variations. """ 570 582 for offDisp in oGen.getDispForMod(iMod, cbEffOp): … … 574 586 continue; # skipping. 575 587 oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n'); 576 self.generateMemSetupReadByLabel(oGen, c AddrBits, uInput);577 self.writeInstrGregSibLabel(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, o Gen);588 self.generateMemSetupReadByLabel(oGen, cbEffOp, uInput); 589 self.writeInstrGregSibLabel(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen); 578 590 sChecker = oGen.needGRegChecker(iOp1); 579 591 else: … … 595 607 oGen.pushConst(uResult); 596 608 oGen.write(' call VBINSTST_NAME(%s)\n' % (sChecker,)); 609 _ = cbMaxOp; 597 610 return True; 598 611 … … 659 672 continue; 660 673 for cAddrBits in oGen.oTarget.getAddrModes(): 674 auInputs = auLongInputs if iOp1 == iLongOp1 and False else auShortInputs; 661 675 for iOp2 in range(len(oGen.oTarget.asGRegs)): 662 676 if iOp2 != 4 or cAddrBits == 16: 663 for uInput in (auLongInputs if iOp1 == iLongOp1 and False else auShortInputs):677 for uInput in auInputs: 664 678 oGen.newSubTest(); 665 679 if iOp1 == iOp2 and iOp2 != 5 and iOp2 != 13 and cbEffOp != cbMaxOp: … … 828 842 Records the need for a given register checker function, returning its label. 829 843 """ 830 assert iReg1 < 32; assert iReg2 < 32; 831 iRegs = iReg1 + iReg2 * 32; 832 if iRegs in self.dCheckFns: 833 self.dCheckFns[iRegs] += 1; 844 if iReg2 is not None: 845 if iReg3 is not None: 846 sName = '%s_%s_%s' % (self.oTarget.asGRegs[iReg1], self.oTarget.asGRegs[iReg2], self.oTarget.asGRegs[iReg3],); 847 else: 848 sName = '%s_%s' % (self.oTarget.asGRegs[iReg1], self.oTarget.asGRegs[iReg2],); 834 849 else: 835 self.dCheckFns[iRegs] = 1; 836 return 'Common_Check_%s_%s' % (self.oTarget.asGRegs[iReg1], self.oTarget.asGRegs[iReg2]); 837 838 def needGRegMemSetup(self, cAddrBits, cbEffOp, iBaseReg, offDisp = None, iIndexReg = None, iScale = 1): 850 sName = '%s' % (self.oTarget.asGRegs[iReg1],); 851 assert iReg3 is None; 852 853 if sName in self.dCheckFns: 854 self.dCheckFns[sName] += 1; 855 else: 856 self.dCheckFns[sName] = 1; 857 858 return 'Common_Check_' + sName; 859 860 def needGRegMemSetup(self, cAddrBits, cbEffOp, iBaseReg = None, offDisp = None, iIndexReg = None, iScale = 1): 839 861 """ 840 862 Records the need for a given register checker function, returning its label. … … 848 870 if offDisp is not None: 849 871 sName += '_%#010x' % (offDisp & UINT32_MAX, ); 850 if sName in self.d CheckFns:872 if sName in self.dMemSetupFns: 851 873 self.dMemSetupFns[sName] += 1; 852 874 else: … … 1127 1149 1128 1150 # Register checking functions. 1129 for iRegs in self.dCheckFns: 1151 for sName in self.dCheckFns: 1152 # Decode the name. 1153 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 1130 1160 iReg1 = iRegs & 0x1f; 1131 1161 sReg1 = self.oTarget.asGRegs[iReg1]; … … 1134 1164 sPushSize = 'dword'; 1135 1165 1166 # Write the test 1136 1167 self.write('\n\n' 1137 1168 '; Checks two register values, expected values pushed on the stack.\n'
Note:
See TracChangeset
for help on using the changeset viewer.