Changeset 46771 in vbox
- Timestamp:
- Jun 25, 2013 8:26:31 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/testcase/Instructions/InstructionTestGen.py
r46746 r46771 375 375 self.acbOpVars = [ 1, 2, 4, 8 ] if not acbOpVars else list(acbOpVars); 376 376 377 ## @name Test Instruction Writers 378 ## @{ 379 377 380 def writeInstrGregGreg(self, cbEffOp, iOp1, iOp2, oGen): 378 381 """ Writes the instruction with two general registers as operands. """ … … 440 443 return True; 441 444 442 def generateOneStdTestGregGreg(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult): 443 """ Generate one standard test. """ 444 oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n'); 445 oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2], uInput,)); 446 oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2],)); 447 self.writeInstrGregGreg(cbEffOp, iOp1, iOp2, oGen); 448 oGen.pushConst(uResult); 449 oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),)); 450 _ = cbMaxOp; 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),)); 450 return True; 451 452 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,)); 456 if offDisp is not None: 457 oGen.write(' + %#x' % (offDisp,)); 458 oGen.write('] ; iScale=%s\n' % (iScale,)); 459 _ = iBaseReg; 460 return True; 461 462 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,)); 466 if offDisp is not None: 467 oGen.write(' + %#x' % (offDisp,)); 468 oGen.write('] ; iScale=%s\n' % (iScale,)); 469 _ = iIndexReg; 470 return True; 471 472 def writeInstrGregSibBaseAndScaledReg(self, cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen): 473 return True; 474 475 ## @} 476 477 478 ## @name Memory setups 479 ## @{ 480 def generateMemSetupReadByLabel(self, oGen, cAddrBits, uInput): 481 """ Sets up memory for a memory read. """ 482 oGen.pushConst(uInput); 483 oGen.write(' call VBINSTST_NAME(Common_SetupMemReadU%u)\n' % (cbEffOp*8,)); 484 return True; 485 486 def generateMemSetupReadByReg(self, oGen, cAddrBits, cbEffOp, iReg1, uInput, offDisp = None): 487 """ Sets up memory for a memory read indirectly addressed thru one register and optional displacement. """ 488 oGen.pushConst(uInput); 489 oGen.write(' call VBINSTST_NAME(%s)\n' 490 % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iReg1, offDisp),)); 491 oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iReg1],)); 492 return True; 493 494 def generateMemSetupReadByScaledReg(self, oGen, cAddrBits, cbEffOp, iReg2, iScale, uInput, offDisp = None): 495 """ Sets up memory for a memory read indirectly addressed thru one register and optional displacement. """ 496 oGen.pushConst(uInput); 497 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[iReg1],)); 500 return True; 501 502 def generateMemSetupReadByBaseAndScaledReg(self, oGen, cAddrBits, cbEffOp, iBaseReg, iIndexReg, iScale, uInput, offDisp): 503 """ Sets up memory for a memory read indirectly addressed thru two registers with optional displacement. """ 504 oGen.pushConst(uInput); 505 if iScale == 1: 506 oGen.write(' call VBINSTST_NAME(%s)\n' 507 % (oGen.needGRegMemSetup(cAddrBits, cbEffOp, iReg1, offDisp),)); 508 oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iReg1],)); 451 509 return True; 452 510 … … 463 521 return True; 464 522 523 ## @} 524 525 def generateOneStdTestGregGreg(self, oGen, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult): 526 """ Generate one standard test. """ 527 oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n'); 528 oGen.write(' mov %s, 0x%x\n' % (oGen.oTarget.asGRegs[iOp2], uInput,)); 529 oGen.write(' push %s\n' % (oGen.oTarget.asGRegs[iOp2],)); 530 self.writeInstrGregGreg(cbEffOp, iOp1, iOp2, oGen); 531 oGen.pushConst(uResult); 532 oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),)); 533 _ = cbMaxOp; 534 return True; 465 535 466 536 def generateOneStdTestGregMemNoSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iOp2, uInput, uResult): … … 478 548 if iOp2 != 5 and iOp2 != 13: 479 549 iMod = 1; 480 for offDisp in (127, -128):550 for offDisp in oGen.getDispForMod(iMod): 481 551 oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n'); 482 552 self.generateMemSetupPureRM(oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput, offDisp); … … 486 556 487 557 iMod = 2; 488 for offDisp in (2147483647, -2147483648):558 for offDisp in oGen.getDispForMod(iMod): 489 559 oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n'); 490 560 self.generateMemSetupPureRM(oGen, cAddrBits, cbEffOp, iOp2, iMod, uInput, offDisp); … … 492 562 oGen.pushConst(uResult); 493 563 oGen.write(' call VBINSTST_NAME(%s)\n' % (oGen.needGRegChecker(iOp1, iOp2),)); 564 565 return True; 566 567 def generateOneStdTestGregMemNoSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iMod, 568 iBaseReg, iIndexReg, iScale, uInput, uResult): 569 """ Generate one SIB variations. """ 570 for offDisp in oGen.getDispForMod(iMod, cbEffOp): 571 if ((iBaseReg == 5 or iBaseReg == 13) and iMod == 0): 572 if iIndexReg == 4: 573 if cAddrBits == 64: 574 continue; # skipping. 575 oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n'); 576 self.generateMemSetupReadByLabel(oGen, cAddrBits, uInput); 577 self.writeInstrGregSibLabel(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, oGen); 578 sChecker = oGen.needGRegChecker(iOp1); 579 else: 580 oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n'); 581 self.generateMemSetupReadByScaledReg(oGen, cAddrBits, cbEffOp, iIndexReg, iScale, uInput, offDisp); 582 self.writeInstrGregSibScaledReg(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen); 583 sChecker = oGen.needGRegChecker(iOp1, iIndexReg); 584 else: 585 oGen.write(' call VBINSTST_NAME(Common_LoadKnownValues)\n'); 586 if iIndexReg == 4: 587 self.generateMemSetupReadByReg(oGen, cAddrBits, cbEffOp, iBaseReg, uInput, offDisp); 588 self.writeInstrGregSibBase(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen); 589 sChecker = oGen.needGRegChecker(iOp1, iBaseReg); 590 else: 591 self.generateMemSetupReadByBaseAndScaledReg(oGen, cAddrBits, cbEffOp, iBaseReg, 592 iIndexReg, iScale, uInput, offDisp); 593 self.writeInstrGregSibBaseAndScaledReg(cbEffOp, iOp1, cAddrBits, iBaseReg, iIndexReg, iScale, offDisp, oGen); 594 sChecker = oGen.needGRegChecker(iOp1, iBaseReg, iIndexReg); 595 oGen.pushConst(uResult); 596 oGen.write(' call VBINSTST_NAME(%s)\n' % (sChecker,)); 597 return True; 598 599 def generateStdTestGregMemSib(self, oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, auInputs): 600 """ Generate all SIB variations for the given iOp1 (reg) value. """ 601 assert cAddrBits in [32, 64]; 602 for iBaseReg in range(len(oGen.oTarget.asGRegs)): 603 for iIndexReg in range(len(oGen.oTarget.asGRegs)): 604 if iBaseReg == 4 or iIndexReg == 4: # no RSP testing atm. 605 continue; 606 for iMod in [0, 1, 2]: 607 if iBaseReg == iOp1 and ((iBaseReg != 5 and iBaseReg != 13) or iMod != 0) and cAddrBits != cbMaxOp: 608 continue; # Don't know the high bit of the address ending up the result - skip it for now. 609 for iScale in (1, 2, 4, 8): 610 for uInput in auInputs: 611 oGen.newSubTest(); 612 uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[iOp1], oGen); 613 self.generateOneStdTestGregMemSib(oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, iMod, 614 iBaseReg, iIndexReg, iScale, uInput, uResult); 494 615 495 616 return True; … … 539 660 for cAddrBits in oGen.oTarget.getAddrModes(): 540 661 for iOp2 in range(len(oGen.oTarget.asGRegs)): 541 if iOp2 != 4: 542 662 if iOp2 != 4 or cAddrBits == 16: 543 663 for uInput in (auLongInputs if iOp1 == iLongOp1 and False else auShortInputs): 544 664 oGen.newSubTest(); 545 665 if iOp1 == iOp2 and iOp2 != 5 and iOp2 != 13 and cbEffOp != cbMaxOp: 546 continue; # Don't know the high bit of the address ending up the result - skip it .666 continue; # Don't know the high bit of the address ending up the result - skip it for now. 547 667 uResult = self.fnCalcResult(cbEffOp, uInput, oGen.auRegValues[iOp1], oGen); 548 668 self.generateOneStdTestGregMemNoSib(oGen, cAddrBits, cbEffOp, cbMaxOp, 549 669 iOp1, iOp2, uInput, uResult); 550 670 else: 551 pass; # SIB 671 # SIB. 672 self.generateStdTestGregMemSib(oGen, cAddrBits, cbEffOp, cbMaxOp, iOp1, auInputs); 552 673 553 674 return True; … … 703 824 return True; 704 825 705 def needGRegChecker(self, iReg1, iReg2 ):826 def needGRegChecker(self, iReg1, iReg2 = None, iReg3 = None): 706 827 """ 707 828 Records the need for a given register checker function, returning its label. … … 715 836 return 'Common_Check_%s_%s' % (self.oTarget.asGRegs[iReg1], self.oTarget.asGRegs[iReg2]); 716 837 717 def needGRegMemSetup(self, cAddrBits, cbEffOp, i Reg1, offDisp = None):838 def needGRegMemSetup(self, cAddrBits, cbEffOp, iBaseReg, offDisp = None, iIndexReg = None, iScale = 1): 718 839 """ 719 840 Records the need for a given register checker function, returning its label. 720 841 """ 721 sName = '%ubit_U%u_%s' % (cAddrBits, cbEffOp * 8, gregName(iReg1, cAddrBits),); 842 sName = '%ubit_U%u' % (cAddrBits, cbEffOp * 8,); 843 if iBaseReg is not None: 844 sName += '_%s' % (gregName(iBaseReg, cAddrBits),); 845 sName += '_x%u' % (iScale,); 846 if iIndexReg is not None: 847 sName += '_%s' % (gregName(iIndexReg, cAddrBits),); 722 848 if offDisp is not None: 723 849 sName += '_%#010x' % (offDisp & UINT32_MAX, ); … … 749 875 self.write(' push dword 0x%x\n' % (uResult,)); 750 876 return True; 877 878 def getDispForMod(self, iMod, cbAlignment = 1): 879 """ 880 Get a set of address dispositions for a given addressing mode. 881 The alignment restriction is for SIB scaling. 882 """ 883 assert cbAlignment in [1, 2, 4, 8]; 884 if iMod == 0: 885 aoffDisp = [ None, ]; 886 elif iMod == 1: 887 aoffDisp = [ 127 & ~cbAlignment, -128 ]; 888 elif iMod == 2: 889 aoffDisp = [ 2147483647 & ~(cbAlignment - 1), -2147483648 ]; 890 else: assert False; 891 return aoffDisp; 751 892 752 893 … … 865 1006 cAddrBits = int(asParams[0][:-3]); 866 1007 cEffOpBits = int(asParams[1][1:]); 867 sBaseReg = asParams[2];868 869 1008 if cAddrBits == 64: asAddrGRegs = g_asGRegs64; 870 1009 elif cAddrBits == 32: asAddrGRegs = g_asGRegs32; 871 1010 else: asAddrGRegs = g_asGRegs16; 872 try: 873 iBaseReg = asAddrGRegs.index(sBaseReg); 874 except ValueError: 875 assert False, 'sBaseReg=%s' % (sBaseReg,); 876 raise; 877 878 i = 3; 1011 1012 i = 2; 1013 if i < len(asParams[i]) and asParams[i]: 1014 sBaseReg = asParams[i]; 1015 i += 1 1016 try: 1017 iBaseReg = asAddrGRegs.index(sBaseReg); 1018 except ValueError: 1019 assert False, 'sBaseReg=%s' % (sBaseReg,); 1020 raise; 1021 879 1022 u32Disp = None; 880 1023 if i < len(asParams) and len(asParams[i]) == 10:
Note:
See TracChangeset
for help on using the changeset viewer.