You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
|
Feb
|
Mar
(16) |
Apr
(83) |
May
(27) |
Jun
(14) |
Jul
(11) |
Aug
(22) |
Sep
|
Oct
|
Nov
|
Dec
|
From: <cap...@us...> - 2007-04-19 23:18:31
|
Revision: 74 http://svn.sourceforge.net/pearcolator/?rev=74&view=rev Author: captain5050 Date: 2007-04-19 16:18:32 -0700 (Thu, 19 Apr 2007) Log Message: ----------- Support for Intel move string operations, flag clearing and shifts by 1 Modified Paths: -------------- src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java Modified: src/org/binarytranslator/arch/x86/decoder/X862IR.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-19 17:02:13 UTC (rev 73) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-19 23:18:32 UTC (rev 74) @@ -405,6 +405,14 @@ } /** + * Wrap the direction flag up in a register operand and return + */ + OPT_RegisterOperand getDirectionFlag() { + flag_DF_InUse = true; + return new OPT_RegisterOperand(flag_DF, VM_TypeReference.Boolean); + } + + /** * Wrap the overflow flag up in a register operand and return */ OPT_RegisterOperand getOverflowFlag() { @@ -576,6 +584,23 @@ .peekResolvedField().getOffset()), new OPT_LocationOperand( flagFref), new OPT_TrueGuardOperand())); } + { + OPT_RegisterOperand flag_DF_Op; + if (flag_DF == null) { + flag_DF_Op = makeTemp(VM_TypeReference.Boolean); + flag_DF = flag_DF_Op.register; + } else { + flag_DF_Op = new OPT_RegisterOperand(flag_DF, VM_TypeReference.Boolean); + } + VM_FieldReference flagFref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("flag_DF"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + VM_TypeReference flagTref = flagFref.getFieldContentsType(); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag_DF_Op, + ps_registersOp.copyRO(), new OPT_AddressConstantOperand(flagFref + .peekResolvedField().getOffset()), new OPT_LocationOperand( + flagFref), new OPT_TrueGuardOperand())); + } } /** @@ -649,6 +674,18 @@ .peekResolvedField().getOffset()), new OPT_LocationOperand( flagFref), new OPT_TrueGuardOperand())); } + { + OPT_RegisterOperand flag_DF_Op = new OPT_RegisterOperand(flag_DF, + VM_TypeReference.Boolean); + VM_FieldReference flagFref = VM_MemberReference.findOrCreate( + registersTref, VM_Atom.findOrCreateAsciiAtom("flag_DF"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + VM_TypeReference flagTref = flagFref.getFieldContentsType(); + appendInstructionToCurrentBlock(GetField.create(PUTFIELD, flag_DF_Op, + ps_registersOp, new OPT_AddressConstantOperand(flagFref + .peekResolvedField().getOffset()), new OPT_LocationOperand( + flagFref), new OPT_TrueGuardOperand())); + } } // -oO Laziness Oo- Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-19 17:02:13 UTC (rev 73) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-19 23:18:32 UTC (rev 74) @@ -17,6 +17,7 @@ import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.*; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*; /** * Decoder for X86 instructions @@ -77,55 +78,44 @@ public static final int PARITY_ODD = 15; /** + * Encoding of flags for decoders + */ + protected enum FLAG { + CARRY, DIRECTION, INTERRUPT + } + + /** * Look up table to find instruction translator, performed using the first * byte of the instruction */ private static final X86_InstructionDecoder[] primaryOpcodes = { /* OPCD Decoder */ - /* 0x00 */new X86_Add_OpcodeDecoder(8, true, 0, true), // 8bit, has - // ModRM, no imm, - // rm is dest - /* 0x01 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest - /* 0x02 */new X86_Add_OpcodeDecoder(8, true, 0, false),// 8bit, has - // ModRM, no imm, - // rm is src + /* 0x00 */new X86_Add_OpcodeDecoder(8, true, 0, true), + // 8bit, has ModRM, no imm, rm is dest + /* 0x01 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), + // 16/32bit, has ModRM, no imm, rm is dest + /* 0x02 */new X86_Add_OpcodeDecoder(8, true, 0, false), + // 8bit, has ModRM, no imm, rm is src /* 0x03 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false), // 16/32bit, has ModRM, no imm, rm is src - /* 0x04 */new X86_Add_OpcodeDecoder(8, false, 8, false),// 8bit, no ModRM, - // 8bit imm - /* 0x05 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 - : 32, false),// 16/32bit, no ModRM, 16/32bit imm + /* 0x04 */new X86_Add_OpcodeDecoder(8, false, 8, false), + // 8bit, no ModRM, 8bit imm + /* 0x05 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT?16:32, false), + // 16/32bit, no ModRM, 16/32bit imm /* 0x06 */null, /* 0x07 */null, - /* 0x08 */new X86_Or_OpcodeDecoder(8, true, 0, true), // 8bit, has ModRM, - // no imm, rm is - // dest - /* 0x09 */new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest - /* 0x0A */new X86_Or_OpcodeDecoder(8, true, 0, false),// 8bit, has ModRM, - // no imm, rm is src - /* 0x0B */new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src - /* 0x0C */new X86_Or_OpcodeDecoder(8, false, 8, false),// 8bit, no ModRM, - // 8bit imm + /* 0x08 */new X86_Or_OpcodeDecoder(8, true, 0, true), + // 8bit, has ModRM, no imm, rm is dest + /* 0x09 */new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), + // 16/32bit,has ModRM, no imm, rm is dest + /* 0x0A */new X86_Or_OpcodeDecoder(8, true, 0, false), + // 8bit, has ModRM, no imm, rm is src + /* 0x0B */new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false), + // 16/32bit, has ModRM, no imm, rm is src + /* 0x0C */new X86_Or_OpcodeDecoder(8, false, 8, false), + // 8bit, no ModRM, 8bit imm /* 0x0D */new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 - : 32, false),// 16/32bit, no ModRM, 16/32bit imm + : 32, false),// 16/32bit, no ModRM, 16/32bit im /* 0x0E */null, /* 0x0F */new X86_Escape_OpcodeDecoder(), @@ -354,38 +344,20 @@ new X86_Xor_OpcodeDecoder(8, true, 8, true),// 6 new X86_Cmp_OpcodeDecoder(8, true, 8, true) // 7 }), - /* 0x81 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 16/32bit, - // ModRM, - // 16/32bit - // imm, - // rm - // is - // dest - new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 - : 32, true),// 0 - new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, - _16BIT ? 16 : 32, true),// 1 - new X86_Adc_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 - : 32, true),// 2 - new X86_Sbb_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 - : 32, true),// 3 - new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 - : 32, true),// 4 - new X86_Sub_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 - : 32, true),// 5 - new X86_Xor_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 - : 32, true),// 6 - new X86_Cmp_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 - : 32, true) // 7 + /* 0x81 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { + // 16/32bit, ModRM, 16/32bit imm, rm is dest + new X86_Add_OpcodeDecoder(_16BIT?16:32, true, _16BIT?16:32, true),// 0 + new X86_Or_OpcodeDecoder(_16BIT?16:32, true, _16BIT?16:32, true),// 1 + new X86_Adc_OpcodeDecoder(_16BIT?16:32, true, _16BIT?16:32, true),// 2 + new X86_Sbb_OpcodeDecoder(_16BIT?16:32, true, _16BIT?16:32, true),// 3 + new X86_And_OpcodeDecoder(_16BIT?16:32, true, _16BIT?16:32, true),// 4 + new X86_Sub_OpcodeDecoder(_16BIT?16:32, true, _16BIT?16:32, true),// 5 + new X86_Xor_OpcodeDecoder(_16BIT?16:32, true, _16BIT?16:32, true),// 6 + new X86_Cmp_OpcodeDecoder(_16BIT?16:32, true, _16BIT?16:32, true) // 7 }), /* 0x82 */null, - /* 0x83 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 16/32bit, - // ModRM, - // 8bit - // imm, - // rm - // is - // dest + /* 0x83 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { + // 16/32bit, ModRM, 8bit imm, rm is dest new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 0 new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 1 new X86_Adc_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 2 @@ -462,8 +434,8 @@ /* 0xA3 */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, true), // mov // [disp(16|32)], // eax - /* 0xA4 */null, - /* 0xA5 */null, + /* 0xA4 */new X86_Movs_OpcodeDecoder(8), + /* 0xA5 */new X86_Movs_OpcodeDecoder(_16BIT ? 16 : 32), /* 0xA6 */null, /* 0xA7 */null, /* 0xA8 */null, @@ -550,8 +522,28 @@ /* 0xCE */null, /* 0xCF */null, - /* 0xD0 */null, - /* 0xD1 */null, + /* 0xD0 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { + // 8bit shift/rotates by 1 + new X86_Rol_OpcodeDecoder(8),// 0 + new X86_Ror_OpcodeDecoder(8),// 1 + new X86_Rcl_OpcodeDecoder(8),// 2 + new X86_Rcr_OpcodeDecoder(8),// 3 + new X86_Shl_OpcodeDecoder(8),// 4 + new X86_Ushr_OpcodeDecoder(8),// 5 + null, // 6 + new X86_Shr_OpcodeDecoder(8) // 7 + }), + /* 0xD1 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { + // 16/32bit shift/rotates by 1 + new X86_Rol_OpcodeDecoder(_16BIT?16:32),// 0 + new X86_Ror_OpcodeDecoder(_16BIT?16:32),// 1 + new X86_Rcl_OpcodeDecoder(_16BIT?16:32),// 2 + new X86_Rcr_OpcodeDecoder(_16BIT?16:32),// 3 + new X86_Shl_OpcodeDecoder(_16BIT?16:32),// 4 + new X86_Ushr_OpcodeDecoder(_16BIT?16:32),// 5 + null, // 6 + new X86_Shr_OpcodeDecoder(_16BIT?16:32) // 7 + }), /* 0xD2 */null, /* 0xD3 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { null, // 0 @@ -630,7 +622,7 @@ /* 0xF2 */new X86_RepNE_PrefixDecoder(), /* 0xF3 */new X86_Rep_PrefixDecoder(), /* 0xF4 */null, - /* 0xF5 */null, + /* 0xF5 */null,//complement carry /* 0xF6 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 8bit, // ModRM, 8bit imm, rm is dest new X86_Test_OpcodeDecoder(8, true, 8), // 0 @@ -659,12 +651,12 @@ new X86_Div_OpcodeDecoder(_16BIT ? 16 : 32), // 6 - 16/32bit null // 7 }), - /* 0xF8 */null, - /* 0xF9 */null, - /* 0xFA */null, - /* 0xFB */null, - /* 0xFC */null, - /* 0xFD */null, + /* 0xF8 */new X86_MoveToFlag_OpcodeDecoder(FLAG.CARRY,false), // clc + /* 0xF9 */new X86_MoveToFlag_OpcodeDecoder(FLAG.CARRY,true), // stc + /* 0xFA */new X86_MoveToFlag_OpcodeDecoder(FLAG.INTERRUPT,false), // cli + /* 0xFB */new X86_MoveToFlag_OpcodeDecoder(FLAG.INTERRUPT,true), // sti + /* 0xFC */new X86_MoveToFlag_OpcodeDecoder(FLAG.DIRECTION,false), // cld + /* 0xFD */new X86_MoveToFlag_OpcodeDecoder(FLAG.DIRECTION,true), // std /* 0xFE */null, /* 0xFF */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { new X86_Inc_OpcodeDecoder(-1), // 0 - Inc of memory operand @@ -910,14 +902,14 @@ public int translate(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc) { if (prefix1 != null) - prefix1.applyPrefix(); + prefix1.startPrefix(translationHelper, lazy); int nextPC = opcode.translate(translationHelper, ps, lazy, pc, modrm, sib, displacement, immediateSize, immediate, length, prefix2, prefix3, prefix4, prefix5); if (prefix1 != null) - prefix1.removePrefix(); + prefix1.endPrefix(translationHelper, lazy); return nextPC; } @@ -953,18 +945,14 @@ */ abstract class X86_Group1PrefixDecoder extends X86_PrefixDecoder { /** - * Apply an instruction prefix + * Start an instruction prefix */ - void applyPrefix() { - DBT_OptimizingCompilerException.TODO(); - } + abstract void startPrefix(X862IR translationHelper, X86_Laziness lazy); /** - * Remove an instruction prefix + * End an instruction prefix */ - void removePrefix() { - DBT_OptimizingCompilerException.TODO(); - } + abstract void endPrefix(X862IR translationHelper, X86_Laziness lazy); /** * Get the decoder with upto four or five(X86_64) prefix decoders but @@ -1078,18 +1066,105 @@ * Decoder for X86 lock prefix */ class X86_Lock_PrefixDecoder extends X86_Group1PrefixDecoder { + /** + * Start an instruction prefix + */ + void startPrefix(X862IR translationHelper, X86_Laziness lazy) { + TODO(); + } + + /** + * End an instruction prefix + */ + void endPrefix(X862IR translationHelper, X86_Laziness lazy) { + TODO(); + } + + /** + * Disassemble a single prefix + * @param ps the process space of the translation + * @param pc the address of the instruction to translate + * @return the string for this prefic + */ + public String disassemble(ProcessSpace ps, int pc) { + return "lock "; + } } /** * Decoder for X86 repne/repnz prefix */ class X86_RepNE_PrefixDecoder extends X86_Group1PrefixDecoder { + /** + * Start an instruction prefix + */ + void startPrefix(X862IR translationHelper, X86_Laziness lazy) { + TODO(); + } + + /** + * End an instruction prefix + */ + void endPrefix(X862IR translationHelper, X86_Laziness lazy) { + TODO(); + } + /** + * Disassemble a single prefix + * @param ps the process space of the translation + * @param pc the address of the instruction to translate + * @return the string for this prefic + */ + public String disassemble(ProcessSpace ps, int pc) { + return "repne "; + } } /** * Decoder for X86 rep or repe/repz prefix */ class X86_Rep_PrefixDecoder extends X86_Group1PrefixDecoder { + /** + * Block containing instruction to repeat + */ + private OPT_BasicBlock instructionBlock; + /** + * Start an instruction prefix + */ + void startPrefix(X862IR translationHelper, X86_Laziness lazy) { + instructionBlock = translationHelper.createBlockAfterCurrent(); + translationHelper.setCurrentBlock(instructionBlock); + } + + /** + * End an instruction prefix + */ + void endPrefix(X862IR translationHelper, X86_Laziness lazy) { + // TODO: handle 16bit addresses + OPT_RegisterOperand ecx = translationHelper.getGPRegister(lazy, + X86_Registers.ECX, 32); + + translationHelper.appendInstructionToCurrentBlock( + Binary.create(INT_ADD, ecx.copyRO(), ecx.copyRO(), new OPT_IntConstantOperand(-1))); + + OPT_RegisterOperand guardResult = translationHelper.getTempValidation(0); + translationHelper.appendInstructionToCurrentBlock( + IfCmp.create(INT_IFCMP, guardResult, ecx.copyRO(), new OPT_IntConstantOperand(0), + OPT_ConditionOperand.EQUAL(), instructionBlock.makeJumpTarget(), + OPT_BranchProfileOperand.likely())); + + instructionBlock.insertOut(instructionBlock); + OPT_BasicBlock nextBlock = translationHelper.createBlockAfterCurrent(); + translationHelper.setCurrentBlock(nextBlock); + } + /** + * Disassemble a single prefix + * @param ps the process space of the translation + * @param pc the address of the instruction to translate + * @return the string for this prefic + */ + public String disassemble(ProcessSpace ps, int pc) { + return "rep "; + } } // -oO Group 2 prefixs Oo- @@ -1523,6 +1598,9 @@ immediate = ps.memory.loadSigned8(pc + offset); offset++; break; + case 1: // Special case for shift/rotates by 1 + immediate = 1; + break; default: // no immediate break; } @@ -1590,6 +1668,9 @@ immediate = ps.memory.loadSigned8(pc + offset); offset++; break; + case 1: // Special case for shift/rotates by 1 + immediate = 1; + break; default: // no immediate break; } @@ -2402,6 +2483,150 @@ } /** + * The decoder for the Movs opcode + */ +class X86_Movs_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_Movs_OpcodeDecoder(int size) { + super(size, false, 0, false); + } + /** + * Perform the actual translation + * @param translationHelper + * @param ps + * @param lazy + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected int translate(X862IR translationHelper, ProcessSpace ps, + X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, + int displacement, int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int operandSize; + if (prefix3 == null) { + operandSize = this.operandSize; + } else if (this.operandSize == 32) { + operandSize = 16; + } else { + operandSize = 32; + } + int addressSize; + if (prefix4 == null) { + addressSize = _16BIT ? 16 : 32; + } else { + addressSize = _16BIT ? 32 : 16; + } + // Create memory references + X86_DecodedOperand source = X86_DecodedOperand.getMemory( + (prefix2 != null) ? prefix2.getSegment() : X86_Registers.DS, + X86_Registers.ESI, 0, -1, 0, addressSize, operandSize); + + X86_DecodedOperand destination = X86_DecodedOperand.getMemory( + X86_Registers.ES, X86_Registers.EDI, 0, -1, 0, addressSize, operandSize); + + // Perform copy + OPT_RegisterOperand temp = translationHelper.getTempInt(0); + source.readToRegister(translationHelper, lazy, temp); + destination.writeValue(translationHelper, lazy, temp); + + // Do update + OPT_RegisterOperand esi = translationHelper.getGPRegister(lazy, + X86_Registers.ESI, addressSize); + OPT_RegisterOperand edi = translationHelper.getGPRegister(lazy, + X86_Registers.EDI, addressSize); + + OPT_IntConstantOperand upIncrement = null, downIncrement = null; + switch(operandSize) { + case 32: + upIncrement = new OPT_IntConstantOperand(4); + downIncrement = new OPT_IntConstantOperand(-4); + break; + case 16: + upIncrement = new OPT_IntConstantOperand(2); + downIncrement = new OPT_IntConstantOperand(-2); + break; + case 8: + upIncrement = new OPT_IntConstantOperand(1); + downIncrement = new OPT_IntConstantOperand(-1); + break; + default: + DBT_OptimizingCompilerException.UNREACHABLE(); + } + translationHelper.appendInstructionToCurrentBlock(CondMove.create(INT_COND_MOVE, + temp.copyRO(), translationHelper.getDirectionFlag(), new OPT_IntConstantOperand(0), + OPT_ConditionOperand.EQUAL(), upIncrement, downIncrement)); + + translationHelper.appendInstructionToCurrentBlock(Binary.create(INT_ADD, + esi.copyRO(), esi.copyRO(), temp.copyRO())); + + translationHelper.appendInstructionToCurrentBlock(Binary.create(INT_ADD, + edi.copyRO(), edi.copyRO(), temp.copyRO())); + + return pc + length; + } + + /** + * Disassemble the opcode + * @param ps + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immedate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected String disassemble(ProcessSpace ps, int pc, + X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, int displacement, + int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int operandSize; + if (prefix3 == null) { + operandSize = this.operandSize; + } else if (this.operandSize == 32) { + operandSize = 16; + } else { + operandSize = 32; + } + char addressPrefix; + if (prefix4 == null) { + addressPrefix = _16BIT ? ' ' : 'e'; + } else { + addressPrefix = _16BIT ? 'e' : ' '; + } + // TODO: apply segment override + switch (operandSize) { + case 8: + return "movsb ds:" + addressPrefix + "si, " + addressPrefix + "di"; + case 16: + return "movsw ds:" + addressPrefix + "si, " + addressPrefix + "di"; + case 32: + return "movsd ds:" + addressPrefix + "si, " + addressPrefix + "di"; + default: + DBT_OptimizingCompilerException.UNREACHABLE(); + return "error"; + } + } +} + +/** * The decoder for the Or opcode */ class X86_Or_OpcodeDecoder extends X86_OpcodeDecoder { @@ -2427,25 +2652,137 @@ return "or"; } } +/** + * The decoder for the Rcl opcode + */ +class X86_Rcl_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Rotate rm right by 1 through carry + */ + X86_Rcl_OpcodeDecoder(int size) { + super(size, true, 1, true); + } + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_Rcl_OpcodeDecoder(int size, boolean hasModRM, int immediateSize, + boolean isMemoryOperandDestination) { + super(size, hasModRM, immediateSize, isMemoryOperandDestination, + X86_Registers.ECX); + } + /** + * Return the RCL operator + */ + OPT_Operator getOperator() { + TODO(); + return null; + } +} +/** + * The decoder for the Rcr opcode + */ +class X86_Rcr_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Rotate rm right by 1 through carry + */ + X86_Rcr_OpcodeDecoder(int size) { + super(size, true, 1, true); + } + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_Rcr_OpcodeDecoder(int size, boolean hasModRM, int immediateSize, + boolean isMemoryOperandDestination) { + super(size, hasModRM, immediateSize, isMemoryOperandDestination, + X86_Registers.ECX); + } + /** + * Return the RCL operator + */ + OPT_Operator getOperator() { + TODO(); + return null; + } +} +/** + * The decoder for the Rol opcode + */ +class X86_Rol_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Rotate rm left by 1 + */ + X86_Rol_OpcodeDecoder(int size) { + super(size, true, 1, true); + } + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_Rol_OpcodeDecoder(int size, boolean hasModRM, int immediateSize, + boolean isMemoryOperandDestination) { + super(size, hasModRM, immediateSize, isMemoryOperandDestination, + X86_Registers.ECX); + } + /** + * Return the ROL operator + */ + OPT_Operator getOperator() { + TODO(); + return null; + } +} +/** + * The decoder for the Ror opcode + */ +class X86_Ror_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Rotate rm right by 1 + */ + X86_Ror_OpcodeDecoder(int size) { + super(size, true, 1, true); + } + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_Ror_OpcodeDecoder(int size, boolean hasModRM, int immediateSize, + boolean isMemoryOperandDestination) { + super(size, hasModRM, immediateSize, isMemoryOperandDestination, + X86_Registers.ECX); + } + /** + * Return the ROL operator + */ + OPT_Operator getOperator() { + TODO(); + return null; + } +} + /** - * The decoder for the Shr opcode + * The decoder for the Shl opcode */ -class X86_Shr_OpcodeDecoder extends X86_OpcodeDecoder { +class X86_Shl_OpcodeDecoder extends X86_OpcodeDecoder { /** + * Shift rm left by 1 + */ + X86_Shl_OpcodeDecoder(int size) { + super(size, true, 1, true); + } + + /** * Constructor, {@see X86_OpcodeDecoder} */ - X86_Shr_OpcodeDecoder(int size, boolean hasModRM, int immediateSize, + X86_Shl_OpcodeDecoder(int size, boolean hasModRM, int immediateSize, boolean isMemoryOperandDestination) { super(size, hasModRM, immediateSize, isMemoryOperandDestination, X86_Registers.ECX); } /** - * Return the SHR operator + * Return the SHL operator */ OPT_Operator getOperator() { - return INT_SHR; + return INT_SHL; } /** @@ -2456,7 +2793,7 @@ OPT_RegisterOperand source2) { OPT_RegisterOperand carry = translationHelper.getCarryFlag(); OPT_RegisterOperand temp = translationHelper.getTempInt(9); - translationHelper.appendInstructionToCurrentBlock(Binary.create(INT_SUB, + translationHelper.appendInstructionToCurrentBlock(Binary.create(INT_ADD, temp, source2, new OPT_IntConstantOperand(1))); translationHelper.appendInstructionToCurrentBlock(BooleanCmp.create( BOOLEAN_CMP_INT, carry, source1, temp.copyRO(), OPT_ConditionOperand @@ -2464,31 +2801,38 @@ } /** - * Return "shr" + * Return "shl" */ String getOperatorString() { - return "shr"; + return "shl"; } } /** - * The decoder for the Shl opcode + * The decoder for the Shr opcode */ -class X86_Shl_OpcodeDecoder extends X86_OpcodeDecoder { +class X86_Shr_OpcodeDecoder extends X86_OpcodeDecoder { /** + * Shift rm right by 1 + */ + X86_Shr_OpcodeDecoder(int size) { + super(size, true, 1, true); + } + + /** * Constructor, {@see X86_OpcodeDecoder} */ - X86_Shl_OpcodeDecoder(int size, boolean hasModRM, int immediateSize, + X86_Shr_OpcodeDecoder(int size, boolean hasModRM, int immediateSize, boolean isMemoryOperandDestination) { super(size, hasModRM, immediateSize, isMemoryOperandDestination, X86_Registers.ECX); } /** - * Return the SHL operator + * Return the SHR operator */ OPT_Operator getOperator() { - return INT_SHL; + return INT_SHR; } /** @@ -2507,10 +2851,10 @@ } /** - * Return "shl" + * Return "shr" */ String getOperatorString() { - return "shl"; + return "shr"; } } @@ -2650,6 +2994,12 @@ */ class X86_Ushr_OpcodeDecoder extends X86_OpcodeDecoder { /** + * Unsigned shift rm right by 1 + */ + X86_Ushr_OpcodeDecoder(int size) { + super(size, true, 1, true); + } + /** * Constructor, {@see X86_OpcodeDecoder} */ X86_Ushr_OpcodeDecoder(int size, boolean hasModRM, int immediateSize, @@ -4525,6 +4875,110 @@ } /** + * The decoder to set or clear flags + */ +class X86_MoveToFlag_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * The value to set the flag to + */ + private final boolean value; + /** + * The flag to set + */ + private final FLAG flag; + + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_MoveToFlag_OpcodeDecoder(FLAG flag, boolean value) { + super(0, false, 0, false); + this.flag = flag; + this.value = value; + } + + /** + * Perform the actual translation + * @param translationHelper + * @param ps + * @param lazy + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected int translate(X862IR translationHelper, ProcessSpace ps, + X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, + int displacement, int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + OPT_RegisterOperand flagOp; + switch (flag) { + case CARRY: + flagOp = translationHelper.getCarryFlag(); + break; + case DIRECTION: + flagOp = translationHelper.getDirectionFlag(); + break; + default: + TODO(); + flagOp = null; + break; + } + translationHelper.appendInstructionToCurrentBlock( + Move.create(INT_MOVE, flagOp, + value ? new OPT_IntConstantOperand(1) : + new OPT_IntConstantOperand(0))); + return pc + length; + } + + /** + * Return the operator for this opcode + */ + OPT_Operator getOperator() { + throw new Error("This opcode requires more complex operator decoding"); + } + + /** + * Disassemble the opcode + * @param ps + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected String disassemble(ProcessSpace ps, int pc, + X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, int displacement, + int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + String prefix = value ? "st" : "cl"; + switch (flag) { + case CARRY: + return prefix + "c"; + case DIRECTION: + return prefix + "d"; + case INTERRUPT: + return prefix + "i"; + default: + return "Unrecognized flag"; + } + } +} +/** * The decoder for the Nop opcode */ class X86_Nop_OpcodeDecoder extends X86_OpcodeDecoder { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-19 17:02:13
|
Revision: 73 http://svn.sourceforge.net/pearcolator/?rev=73&view=rev Author: michael_baer Date: 2007-04-19 10:02:13 -0700 (Thu, 19 Apr 2007) Log Message: ----------- Built a new ARM instruction decoder after an optimised decision tree, which was created by the Weka data mining tool. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-19 15:35:38 UTC (rev 72) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-19 17:02:13 UTC (rev 73) @@ -1,233 +1,250 @@ package org.binarytranslator.arch.arm.decoder; -import org.binarytranslator.DBT; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; /** * This class decodes an ARM instruction and uses a user-supplied ARM_InstructionFactory to create a class * that represents the given instruction. * - * I'm not happy with the structure of this module, but looking at the opcode map of the ARM, it's hard to - * provide a structured way of decoding primary and secondary opcodes efficiently. This class first looks at - * bits 25-27 and tries to decode as much from these as possible, using the decode_xxx functions. However, - * sometimes bits have to be checked in quite a non-systematic fashion to really catch all the cases that - * have been squeezed into newer ARM architectures. + * The decoder first performs a pseudo-switch on bits 27-25 of the instruction. + * For performance reasons, the switch is implemented as an array lookup (using the {@link #prefixDecoders} array), + * with single {@link Decoder} classes implementing the cases. * + * ARM has a very cluttered opcode map, which is why the decoding process does not look very tidy. + * However, the presented decoded scheme has been derived by producing all possible instructions and then + * letting a data mining tool (specifically: Weka) create a decision tree to decode the single + * instruction classes. This has two implications: + * <ol> + * <li>The decoder is correct (at least, when I didn't introduce any typos), as Weka verified an error rate of 0% for this decision tree.</li> + * <li>The decoder is reasonably fast, considering Weka tries to build a shallow decision tree.</li> + * </ol> + * * @author Michael Baer * */ public class ARM_InstructionDecoder { - /** This static field caches the default {@link ARM_InstructionFactory} implementation, which is used by {@link #decode(int)}. + /** + * This table is used to perform a lookup on bits 25-27 of an instruction. + * According to the result of this lookup, the {@link Decoder} instances within this + * array perform the subsequent instruction decoding. */ + private static Decoder[] prefixDecoders = { + new decoder_000(), new decoder_001(), + new decoder_010(), new decoder_011(), + new decoder_100(), new decoder_101(), + new decoder_110(), new decoder_111() + }; + + /** + * This static field caches the default {@link ARM_InstructionFactory} implementation, which is used by {@link #decode(int)}. * It is being lazily initialized once it is used for the first time. */ private static DefaultFactory _defaultFactory; - /** - * Decodes a given ARM instruction and returns an object representation of it. - * @param instruction - * A binary ARM instruction, that is to be decoded. - * @return - * A version of the instruction, which has been decoded into an instance of {@link Instruction}. - * Use the {@link Instruction#visit(ARM_InstructionVisitor)} method to further interact with the - * returned instance. - */ - public static Instruction decode(int instruction) { - if (_defaultFactory == null) - _defaultFactory = new DefaultFactory(); - - return decode(instruction, _defaultFactory); + /** + * This class performs additional instruction decoding, after bits 25-27 of an instruction have been + * determined. The class is basically just a way of substituting a switch by an array lookup+virtual method call. + * */ + private static abstract class Decoder { + abstract <T> T decode(int instr, ARM_InstructionFactory<T> factory); } + + /** Decoder which assumes that bits 27-25 == 000. */ + private static class decoder_000 extends Decoder { - /** - * Decodes a binary ARM instruction. This method will use the supplied {@link ARM_InstructionFactory} - * to create an object representation of the decoded instruction. - * @param <T> - * The return type depends on whatever the {@link ARM_InstructionFactory} actually creates. - * @param instruction - * A binary representation of the instruction that is to be decoded. - * @param factory - * A factory, that will create object instances of the instruction. - * @return - * An object representation of the decoded instruction. - */ - static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { - if (Utils.getBit(instruction, 27)) { - return decode_1xx(instruction, factory); + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + + //Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } + + byte bits_7_4 = (byte)Utils.getBits(instr, 4, 7); + + if (bits_7_4 == 0 && ((instr & 0x01900000) == 0x01100000)) { + //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 20) == true + if (Utils.getBit(instr, 21)) + return factory.createMoveToStatusRegister(instr); + else + return factory.createMoveFromStatusRegister(instr); + } + + if (bits_7_4 == 1 && ((instr & 0x01F00000) == 0x01200000)) { + //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 22) == false && Utils.getBit(instr, 21) == true && Utils.getBit(instr, 20) == false + return factory.createBranchExchange(instr); + } + + if ((bits_7_4 & 9) == 9) { + //bits7-4 = 1xx1 + if (bits_7_4 == 9) { + if (Utils.getBit(instr, 23)) { + return factory.createLongMultiply(instr); + } + else { + if (Utils.getBit(instr, 24)) + return factory.createSwap(instr); + else + return factory.createIntMultiply(instr); + } + } + else + return factory.createSingleDataTransfer(instr); + } + + return factory.createDataProcessing(instr); } - else { - return decode_0xx(instruction, factory); - } } - private static <T> T decode_0xx(int instr, ARM_InstructionFactory<T> factory) { - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + /** Decoder which assumes that bits 27-25 == 001. */ + private static class decoder_001 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + + //Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } + + if (((instr & 0x01900000) == 0x01000000)) { + //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 20) == false + if (Utils.getBit(instr, 21)) + return factory.createMoveToStatusRegister(instr); + else + return factory.createUndefinedInstruction(instr); + } + + return factory.createDataProcessing(instr); } - - if (Utils.getBit(instr, 26)) { - //opcode: 01 - if (Utils.getBit(instr, 25) && Utils.getBit(instr, 4)) + } + + /** Decoder which assumes that bits 27-25 == 010. */ + private static class decoder_010 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + //Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { return factory.createUndefinedInstruction(instr); - else + } + else { return factory.createSingleDataTransfer(instr); + } } - else { - //opcode: 00 - return decode_00x(instr, factory); - } } - private static <T> T decode_1xx(int instr, ARM_InstructionFactory<T> factory) { - if (Utils.getBit(instr, 26)) { - //opcode: 11 - return decode_11x( instr, factory); + /** Decoder which assumes that bits 27-25 == 011. */ + private static class decoder_011 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + //Check condition==never? or bit4==true + if ((instr & 0xF0000000) == 0xF0000000 || Utils.getBit(instr, 4)) { + return factory.createUndefinedInstruction(instr); + } + else { + return factory.createSingleDataTransfer(instr); + } } - else { - //opcode: 10 - return decode_10x(instr, factory); - } } - private static <T> T decode_00x(int instr, ARM_InstructionFactory<T> factory) { - if (Utils.getBit(instr, 25)) - return decode_001(instr, factory); - else - return decode_000(instr, factory); - } - - private static <T> T decode_10x(int instr, ARM_InstructionFactory<T> factory) { - if (Utils.getBit(instr, 25)) { - //opcode: 101 - if ((instr & 0xF0000000) == 0xF0000000) - return factory.createBranchExchange(instr); - else - return factory.createBranch(instr); - } - else { - //opcode: 100 - if ((instr & 0xF0000000) == 0xF0000000) + /** Decoder which assumes that bits 27-25 == 100. */ + private static class decoder_100 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + //Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { return factory.createUndefinedInstruction(instr); - else - return factory.createBlockDataTransfer(instr); + } + + return factory.createBlockDataTransfer(instr); } } - private static <T> T decode_000(int instr, ARM_InstructionFactory<T> factory) { - //opcode: 000 - if (Utils.getBit(instr, 24) && !Utils.getBit(instr, 23) && !Utils.getBit(instr, 20)) { - //opcode: 00010xx0 - those are the new instructions, which the ARM ref. manual calls "misc. instructions" - return decode_00010xx0(instr, factory); - } - else { - if (Utils.getBit(instr, 4) == false || Utils.getBit(instr, 7) == false) - return factory.createDataProcessing(instr); + /** Decoder which assumes that bits 27-25 == 101. */ + private static class decoder_101 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + //Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createBranchExchange(instr); + } - return decode_multiplies_extra_load_stores(instr, factory); + return factory.createBranch(instr); } } - private static <T> T decode_001(int instr, ARM_InstructionFactory<T> factory) { - //opcode: 001 - if (!Utils.getBit(instr, 24) || Utils.getBit(instr, 23) || Utils.getBit(instr, 20)) { - return factory.createDataProcessing(instr); - } - - if (Utils.getBit(instr, 21)) - return factory.createMoveToStatusRegister(instr); - else - return factory.createUndefinedInstruction(instr); - } - - private static <T> T decode_11x(int instr, ARM_InstructionFactory<T> factory) { - - if (Utils.getBit(instr, 25) == false) { - //opcode: 110 + /** Decoder which assumes that bits 27-25 == 110. */ + private static class decoder_110 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { return factory.createCoprocessorDataTransfer(instr); } - - //opcode: 111 - if (Utils.getBit(instr, 24)) { - //opcode: 1111 - if ((instr & 0xF0000000) == 0xF0000000) - return factory.createUndefinedInstruction(instr); - else - return factory.createSoftwareInterrupt(instr); - } - else { - //opcode: 1110 - if (Utils.getBit(instr, 4)) { - return factory.createCoprocessorDataTransfer(instr); - } - else { - return factory.createCoprocessorRegisterTransfer(instr); - } - } } - /** Decodes instructions with the opcode 00010xx0 - those are the new instructions, which - * the ARM ref. manual calls "misc. instructions". - * - * @see Page A3-4 in the ARM Reference Manual (ARM DDI 0100 E) / 2000 - */ - private static <T> T decode_00010xx0(int instr, ARM_InstructionFactory<T> factory) { - // - if (Utils.getBit(instr, 6) || Utils.getBit(instr, 7)) { - //enhanced DSP multiplications, DSP add/subtracts and software breakpoints - //we might want to support these in the future, so when in debug mode, catch if any program actually uses them - if (DBT.VerifyAssertions) DBT._assert(false); - return factory.createUndefinedInstruction(instr); - } - else { - //bit 6 and 7 are clear - if (Utils.getBit(instr, 4)) { - if (Utils.getBit(instr, 22)) - return factory.createDataProcessing(instr); //should be a CLZ instruction - else - return factory.createBranchExchange(instr); - } - else { - if (Utils.getBit(instr, 21)) - return factory.createMoveToStatusRegister(instr); - else - return factory.createMoveFromStatusRegister(instr); - } - } - } - /** This might appear even more weird, but I didn't design the ARM ISA. This function decodes - * all the operations defined on p. A3-3 in the ARM reference manual from 2000 (ARM DDI 0100 E). - * - * @see ARM Reference Manual (ARM DDI 0100 E) / 2000 - */ - private static <T> T decode_multiplies_extra_load_stores(int instr, ARM_InstructionFactory<T> factory) { - //Here, we already know that bits 4 and 7 are set, while bit 25-27 are clear - if (Utils.getBit(instr, 6)) { - //load/store signed half-word or two words - if (Utils.getBit(instr, 20)) - return factory.createSingleDataTransfer(instr); - else - return factory.createUndefinedInstruction(instr); //two words immediate offset - } - else { - if (Utils.getBit(instr, 5)) { - //load/store half-word - return factory.createSingleDataTransfer(instr); + /** Decoder which assumes that bits 27-25 == 111. */ + private static class decoder_111 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 24)) { + //Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } + else { + return factory.createSoftwareInterrupt(instr); + } } else { - //Multiply, multiply long or Swap - if (Utils.getBit(instr, 24)) { - return factory.createSwap(instr); + if (Utils.getBit(instr, 4)) { + return factory.createCoprocessorRegisterTransfer(instr); } else { - if (Utils.getBit(instr, 23)) - return factory.createLongMultiply(instr); - else - return factory.createIntMultiply(instr); + return factory.createCoprocessorDataProcessing(instr); } } } } /** + * Decodes a given ARM instruction and returns an object representation of it. + * @param instruction + * A binary ARM instruction, that is to be decoded. + * @return + * A version of the instruction, which has been decoded into an instance of {@link Instruction}. + * Use the {@link Instruction#visit(ARM_InstructionVisitor)} method to further interact with the + * returned instance. + */ + public static Instruction decode(int instruction) { + if (_defaultFactory == null) + _defaultFactory = new DefaultFactory(); + + return decode(instruction, _defaultFactory); + } + + /** + * Decodes a binary ARM instruction. This method will use the supplied {@link ARM_InstructionFactory} + * to create an object representation of the decoded instruction. + * @param <T> + * The return type depends on whatever the {@link ARM_InstructionFactory} actually creates. + * @param instruction + * A binary representation of the instruction that is to be decoded. + * @param factory + * A factory, that will create object instances of the instruction. + * @return + * An object representation of the decoded instruction. + */ + static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { + + int bits_27_25 = Utils.getBits(instruction, 25, 27); + return prefixDecoders[bits_27_25].decode(instruction, factory); + } + + /** * An interface to a factory class, which will create the actual object representations of the * instruction classes decoded by {@link ARM_InstructionDecoder}. * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-19 15:35:54
|
Revision: 72 http://svn.sourceforge.net/pearcolator/?rev=72&view=rev Author: captain5050 Date: 2007-04-19 08:35:38 -0700 (Thu, 19 Apr 2007) Log Message: ----------- Support to disassemble instructions as they are ran (rather than just at translate time). Fixes for x86 sysinfo (vdso) page support - disabling vdso for now. Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DynamicCodeRunner.java Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -5,6 +5,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Interpreter; import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.arch.x86.decoder.X86_InstructionDecoder; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.memory.DebugMemory; import org.binarytranslator.generic.os.loader.Loader; @@ -90,6 +91,14 @@ } /** + * Return a string disassembly of the instuction at the given address + */ + @Uninterruptible + public String disassembleInstruction(int pc) { + return "TODO"; + } + + /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -22,6 +22,7 @@ import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; +import org.jikesrvm.ppc.PPC_Disassembler; import org.vmmagic.pragma.Uninterruptible; /** @@ -176,6 +177,15 @@ } /** + * Return a string disassembly of the instuction at the given address + */ + @Uninterruptible + public String disassembleInstruction(int pc) { + int instr = memory.load32(pc); + return PPC_Disassembler.disasm(instr, pc); + } + + /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -16,6 +16,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.loader.elf.ELF_Loader; import org.binarytranslator.generic.os.process.ProcessSpace; /** @@ -99,12 +100,13 @@ 0x64, LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, - 0xBADADD8E, // todo + ((ELF_Loader)loader).getProgramHeaderAddress(), + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, + ((ELF_Loader)loader).elfHeader.getNumberOfProgramSegmentHeaders(), LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, - 0xBAD1BAD1, // todo - LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, - 0xBAD2BAD2, // todo - LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, + ((ELF_Loader)loader).elfHeader.getProgramSegmentHeaderSize(), + + //LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, pc, LinuxStackInitializer.AuxiliaryVectorType.AT_UID, DBT_Options.UID, Modified: src/org/binarytranslator/arch/x86/decoder/X862IR.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-19 15:35:38 UTC (rev 72) @@ -54,12 +54,8 @@ * @return the next instruction address or -1 */ protected int translateInstruction(Laziness lazy, int pc) { - if (pc != 0xffffe400) { - return X86_InstructionDecoder.translateInstruction((X862IR) this, - (X86_ProcessSpace) ps, (X86_Laziness) lazy, pc); - } else { - return plantSystemCallGateEntry((X86_Laziness) lazy, pc); - } + return X86_InstructionDecoder.translateInstruction((X862IR) this, + (X86_ProcessSpace) ps, (X86_Laziness) lazy, pc); } /** Modified: src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/x86/decoder/X86_DecodedOperand.java 2007-04-19 15:35:38 UTC (rev 72) @@ -220,7 +220,11 @@ this.base = base; this.scale = scale; this.index = index; - this.displacement = displacement; + if (segment == X86_Registers.GS){ + this.displacement = displacement + 0xffffe000; + } else { + this.displacement = displacement; + } this.addressSize = addressSize; this.operandSize = operandSize; } Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-19 15:35:38 UTC (rev 72) @@ -21,7 +21,7 @@ /** * Decoder for X86 instructions */ -class X86_InstructionDecoder extends InstructionDecoder { +public class X86_InstructionDecoder extends InstructionDecoder { /* * Process defaults @@ -714,7 +714,7 @@ /** * Get the decoder */ - static X86_InstructionDecoder getDecoder(ProcessSpace ps, int pc) { + public static X86_InstructionDecoder getDecoder(ProcessSpace ps, int pc) { int opcode = ps.memory.loadInstruction8(pc); return primaryOpcodeLookup(opcode).getDecoder(ps, pc, 1, null, null, null, null, null); Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -20,6 +20,7 @@ import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; +import org.binarytranslator.arch.x86.decoder.X86_InstructionDecoder; import org.binarytranslator.generic.os.loader.Loader; import org.vmmagic.pragma.Uninterruptible; @@ -183,7 +184,16 @@ public void setCurrentInstructionAddress(int pc) { registers.eip = pc; } + /** + * Return a string disassembly of the instuction at the given address + */ + @Uninterruptible + public String disassembleInstruction(int pc) { + return X86_InstructionDecoder.getDecoder(this,pc).disassemble(this, pc); + } + + /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -16,7 +16,9 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.loader.elf.ELF_Loader; import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.generic.memory.MemoryMapException; /** * Linux specific parts of the process @@ -61,19 +63,27 @@ registers.eip = pc; this.brk = brk; registers.writeGP32(X86_Registers.ESP, initialiseStack(loader, pc)); + try { + memory.map(0xffffe000, 8192, true, true, true); + } catch (MemoryMapException e) { + throw new Error ("Error creating VDSO page"); + } + memory.store8(0xffffe400, 0xCD); // INT + memory.store8(0xffffe400, 0x80); // 80h + memory.store8(0xffffe400, 0xC3); // RET } /** * Initialise the stack */ private int initialiseStack(Loader loader, int pc) { - int[] auxVector = {LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, - LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, 0xffffe000, + int[] auxVector = {//LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, + //LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, 0xffffe000, LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x78bfbff, LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x64, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, 0xBADADD8E, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0xBAD2BAD2, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, ((ELF_Loader)loader).getProgramHeaderAddress(), + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, ((ELF_Loader)loader).elfHeader.getNumberOfProgramSegmentHeaders(), LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, pc, Modified: src/org/binarytranslator/generic/decoder/DecoderUtils.java =================================================================== --- src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-19 15:35:38 UTC (rev 72) @@ -1046,13 +1046,17 @@ * @return true => try to stop the trace */ protected boolean suitableToStop() { - switch (gc.options.getOptLevel()) { - case 0: - return numberOfInstructions > DBT_Options.instrOpt0; - case 1: - return numberOfInstructions > DBT_Options.instrOpt1; - default: - return numberOfInstructions > DBT_Options.instrOpt2; + if (DBT_Options.singleInstrTranslation && (numberOfInstructions >= 1)) { + return true; + } else { + switch (gc.options.getOptLevel()) { + case 0: + return numberOfInstructions > DBT_Options.instrOpt0; + case 1: + return numberOfInstructions > DBT_Options.instrOpt1; + default: + return numberOfInstructions > DBT_Options.instrOpt2; + } } } Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-19 15:35:38 UTC (rev 72) @@ -29,7 +29,7 @@ /** * Header of ELF file */ - private ELF_Header elfHeader; + public ELF_Header elfHeader; /** * Program segment headers @@ -259,6 +259,13 @@ return elfHeader.isARM_ABI(); } + /** + * Where did the program header get loaded in memory? + */ + public int getProgramHeaderAddress() { + return elfHeader.e_phoff - segmentHeaders[0].p_offset + segmentHeaders[0].p_vaddr; + } + /* * Local classes holding structures from the ELF file */ @@ -267,7 +274,7 @@ * Class to read and hold ELF header information */ @SuppressWarnings("unused") - class ELF_Header { + public class ELF_Header { /** * Class to read and hold ELF header indentity information */ @@ -744,7 +751,7 @@ int getEntryPoint() { return e_entry; } - + /** * Program header table file offset */ @@ -760,56 +767,56 @@ /** * Section header table file offset */ - private int e_shoff; + private final int e_shoff; /** * Processor-specific flags */ - private int e_flags; + private final int e_flags; /** * ELF header size in bytes */ - private short e_ehsize; + private final short e_ehsize; /** * Program header table entry size */ - private short e_phentsize; + private final short e_phentsize; /** * What's the size of a program segment header? */ - int getProgramSegmentHeaderSize() { + public int getProgramSegmentHeaderSize() { return e_phentsize; } /** * Program header table entry count */ - private short e_phnum; + private final short e_phnum; /** * How many program segments are in this ELF binary? */ - int getNumberOfProgramSegmentHeaders() { + public int getNumberOfProgramSegmentHeaders() { return e_phnum; } /** * Section header table entry size */ - private short e_shentsize; + private final short e_shentsize; /** * Section header table entry count */ - private short e_shnum; + private final short e_shnum; /** * Section header table index */ - private short e_shstrndx; + private final short e_shstrndx; /** * Construct/read ELF header Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-04-19 15:35:38 UTC (rev 72) @@ -138,6 +138,12 @@ public abstract void setCurrentInstructionAddress(int pc); /** + * Return a string disassembly of the instuction at the given address + */ + @Uninterruptible + public abstract String disassembleInstruction(int pc); + + /** * Return as an integer the current instruction's address */ public abstract int getCurrentStackAddress(); Modified: src/org/binarytranslator/vmInterface/DynamicCodeRunner.java =================================================================== --- src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-04-18 22:26:30 UTC (rev 71) +++ src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-04-19 15:35:38 UTC (rev 72) @@ -40,11 +40,12 @@ throws BadInstructionException { // Useful when debugging in GDB: if (DBT_Options.debugRuntime) { + VM.sysWriteln(ps.toString()); + ps.dumpStack(20); VM.sysWrite("Running PC="); VM.sysWriteHex(ps.getCurrentInstructionAddress()); - VM.sysWriteln(); - VM.sysWriteln(ps.toString()); - ps.dumpStack(20); + VM.sysWrite(" "); + VM.sysWriteln(ps.disassembleInstruction(ps.getCurrentInstructionAddress())); VM.sysWrite("About to bridge to "); VM.sysWriteHex(VM_Magic.objectAsAddress(code).toInt()); VM.sysWriteln(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-18 22:26:28
|
Revision: 71 http://svn.sourceforge.net/pearcolator/?rev=71&view=rev Author: captain5050 Date: 2007-04-18 15:26:30 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Fix at least one silly mistake in Linux stack initialization and enable stack debug. argv[0] is always the executable file name. Modified Paths: -------------- src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java src/org/binarytranslator/vmInterface/DynamicCodeRunner.java Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java 2007-04-18 18:44:18 UTC (rev 70) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java 2007-04-18 22:26:30 UTC (rev 71) @@ -299,8 +299,12 @@ // grab the vector of command line options that are to be delivered to the // linux program - String[] argv = DBT_Options.executableArguments; - + String[] argv = new String[DBT_Options.executableArguments.length+1]; + argv[0] = DBT_Options.executableFile; + for (int i=0; i < DBT_Options.executableArguments.length; i++) { + argv[i+1] = DBT_Options.executableArguments[i]; + } + // --- // First create the information block by concatenating all strings // together, then compute pointers to values in the information Modified: src/org/binarytranslator/vmInterface/DynamicCodeRunner.java =================================================================== --- src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-04-18 18:44:18 UTC (rev 70) +++ src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-04-18 22:26:30 UTC (rev 71) @@ -44,7 +44,7 @@ VM.sysWriteHex(ps.getCurrentInstructionAddress()); VM.sysWriteln(); VM.sysWriteln(ps.toString()); - // ps.dumpStack(20); + ps.dumpStack(20); VM.sysWrite("About to bridge to "); VM.sysWriteHex(VM_Magic.objectAsAddress(code).toInt()); VM.sysWriteln(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-18 18:44:23
|
Revision: 70 http://svn.sourceforge.net/pearcolator/?rev=70&view=rev Author: michael_baer Date: 2007-04-18 11:44:18 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Added more source comments to the interpreter, Fixed a few minor interpreter and disassembler bugs Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-18 17:40:18 UTC (rev 69) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-18 18:44:18 UTC (rev 70) @@ -191,19 +191,20 @@ if (instr.updateConditionCodes()) mnemonic += 'S'; - String optionalParam; + String parameters; // Filter instructions that only take one parameter - if (instr.getOpcode() != DataProcessing.Opcode.MOV - && instr.getOpcode() != DataProcessing.Opcode.MVN - && instr.getOpcode() != DataProcessing.Opcode.CLZ) { + if (instr.getOpcode() == DataProcessing.Opcode.MOV + || instr.getOpcode() == DataProcessing.Opcode.MVN + || instr.getOpcode() == DataProcessing.Opcode.CLZ) { - optionalParam = ", " + operand(instr.getOperand2()); - } else - optionalParam = ""; + parameters = String.format("%s", operand(instr.getOperand2())); + } + else { + parameters = String.format("r%d, %s", instr.getRn(), operand(instr.getOperand2())); + } - setResult(String.format("%s r%d, r%d%s", mnemonic, instr.getRd(), instr - .getOperandRegister(), optionalParam)); + setResult(String.format("%s r%d, %s", mnemonic, instr.getRd(), parameters)); } public void visit(SingleDataTransfer instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-18 17:40:18 UTC (rev 69) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-18 18:44:18 UTC (rev 70) @@ -441,7 +441,7 @@ } /** Represents a Data Processing instruction. */ - public static class DataProcessing extends Instruction { + public static class DataProcessing extends TwoRegistersTemplate { /** A list of possible DataProcessing operations. The list is orded in ascendingly, with the * first opcode corresponding to opcode 0 (zero) in the opcode field of an ARM data processing @@ -458,9 +458,6 @@ /** @see #getOperand2() */ protected final OperandWrapper operand2; - - /** @see #getOperandRegister() */ - protected final byte operandRegister; /** @see #getRd() */ protected final byte Rd; @@ -474,27 +471,15 @@ if (Utils.getBits(instr, 20, 27) == 0x16 && Utils.getBits(instr, 4, 7) == 1) { //this is a CLZ instruction, which we're catching and merging into the data processing instructions - operandRegister = (byte) (instr & 0xF); opcode = Opcode.CLZ; - operand2 = OperandWrapper.createImmediate(0); + operand2 = OperandWrapper.createRegister((byte)(instr & 0xF)); } else { - operandRegister = (byte) Utils.getBits(instr, 16, 19); opcode = Opcode.values()[(byte) Utils.getBits(instr, 21, 24)]; operand2 = OperandWrapper.decodeDataProcessingOperand(instr); } } - /** Returns the number of the operation's destination register, starting from 0.*/ - public final byte getRd() { - return Rd; - } - - /** Returns the number of the operation's first operand register, starting from 0.*/ - public final byte getOperandRegister() { - return operandRegister; - } - /** Returns the opcode, that specifies the data processing operation, which is to be performed. */ public final Opcode getOpcode() { return opcode; @@ -1111,6 +1096,8 @@ Rd = (byte) Utils.getBits(instr, 12, 15); transferSavedPSR = Utils.getBit(instr, 22); + + if (DBT.VerifyAssertions) DBT._assert(Rd != 15); } /** Returns the number of the destination register. */ Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-18 17:40:18 UTC (rev 69) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-18 18:44:18 UTC (rev 70) @@ -1,5 +1,6 @@ package org.binarytranslator.arch.arm.decoder; +import org.binarytranslator.DBT; import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; @@ -8,10 +9,24 @@ import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.generic.decoder.Interpreter; +import com.sun.org.apache.bcel.internal.generic.InstructionFactory; + +/** + * This class implements the {@link Interpreter} interface to interpret ARM instructions from + * a process space. It uses the {@link ARM_InstructionDecoder} class with a custom {@link InstructionFactory} + * implementations to create representations of the decoded instructions that implement the {@link Instruction} interface. + * + * @author Michael Baer + */ public class ARM_Interpreter implements Interpreter { + /** The process space that we're interpreting.*/ protected final ARM_ProcessSpace ps; + + /** A "quick" pointer to the ARM registers within the process space*/ protected final ARM_Registers regs; + + /** The interpreter factory is creating the final instructions, which implement the Interpreter.Instruction interface. */ protected final InterpreterFactory instructionFactory; public ARM_Interpreter(ARM_ProcessSpace ps) { @@ -20,6 +35,7 @@ instructionFactory = new InterpreterFactory(); } + /** Decodes the instruction at the given address.*/ public Instruction decode(int pc) { int binaryInstruction = ps.memory.loadInstruction32(pc); @@ -32,14 +48,21 @@ return instruction; } + /** All ARM interpreter instructions implement this interface. */ private interface ARM_Instruction extends Interpreter.Instruction { + /** Returns the condition, under which the given instruction will be executed. */ Condition getCondition(); } + /** All ARM instructions that are supposed to be executed conditionally + * are decorated with this decorator. + * The decorator takes care of checking the individual condition and depending on it, executing the + * instruction (or not). The instruction classes itself do not check any conditions. */ private final class ConditionalDecorator implements Interpreter.Instruction { protected final ARM_Instruction conditionalInstruction; + /** Decorates an ARM interpreter instruction, by making it execute conditionally. */ protected ConditionalDecorator(ARM_Instruction i) { conditionalInstruction = i; } @@ -50,13 +73,18 @@ } public int getSuccessor(int pc) { - return -1; + //if this instruction is not a jump, then we can tell what the next instruction will be. + if (conditionalInstruction.getSuccessor(pc) == pc + 4) + return pc + 4; + else + return -1; } + /** Return true if the condition required by the conditional instruction is fulfilled, false otherwise.*/ private boolean isConditionTrue() { switch (conditionalInstruction.getCondition()) { case AL: - return true; + throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator."); case CC: return !regs.isCarrySet(); @@ -109,18 +137,31 @@ } } + /** A base class for all data processing interpreter instructions, including CLZ.*/ private abstract class DataProcessing extends ARM_Instructions.DataProcessing implements ARM_Instruction { + /** Most data processing instructions may set the carry flag according to the barrel shifter's carry + * out value. The (supposed) value of the barrel shifter is stored within this variable. */ protected boolean shifterCarryOut; protected DataProcessing(int instr) { super(instr); } - protected final int resolveShift(OperandWrapper operand) { + /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift + * and set the result of the barrel shifter accordingly. */ + private final int resolveShift(OperandWrapper operand) { + if (DBT.VerifyAssertions) + DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || + operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); int value = regs.get(operand.getRegister()); + + //consider the "usual" ARM program counter offset + if (operand.getRegister() == ARM_Registers.PC) + value += 8; + byte shiftAmount; if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) @@ -209,15 +250,19 @@ } } + /** Returns the value of operand 1 of the data processing instruction. This is always a register value. + * However, deriving classes may alter this behavior, for example to return a negative register + * value for a RSB instruction. */ protected int resolveOperand1() { - if (operandRegister == ARM_Registers.PC) { - return regs.get(operandRegister) + 8; + if (Rn == ARM_Registers.PC) { + return regs.get(Rn) + 8; } - return regs.get(operandRegister); + return regs.get(Rn); } + /** Returns the value of the rhs-operand of the data processing instruction. */ protected int resolveOperand2() { int value; @@ -249,7 +294,8 @@ public abstract void execute(); - protected final void setFlagsForResult(int result) { + /** Sets the condition field for logical operations. */ + protected final void setFlagsForLogicalOperator(int result) { if (updateConditionCodes) { if (Rd != 15) { @@ -260,6 +306,7 @@ } } + /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ protected final void setFlagsForAdd(int lhs, int rhs) { if (updateConditionCodes) { @@ -283,6 +330,7 @@ } } + /** Binary and. <code>Rd = op1 & op2 </code>.*/ private final class DataProcessing_And extends DataProcessing { protected DataProcessing_And(int instr) { @@ -293,10 +341,11 @@ public void execute() { int result = resolveOperand1() & resolveOperand2(); regs.set(Rd, result); - setFlagsForResult(result); + setFlagsForLogicalOperator(result); } } + /** Exclusive or. <code>Rd = op1 ^ op2 </code>.*/ private final class DataProcessing_Eor extends DataProcessing { protected DataProcessing_Eor(int instr) { @@ -307,10 +356,11 @@ public void execute() { int result = resolveOperand1() ^ resolveOperand2(); regs.set(Rd, result); - setFlagsForResult(result); + setFlagsForLogicalOperator(result); } } + /** Add. <code>Rd = op1 + op2 </code>.*/ private class DataProcessing_Add extends DataProcessing { public DataProcessing_Add(int instr) { @@ -327,6 +377,7 @@ } } + /** Subtract. <code>Rd = op1 - op2 </code>.*/ private final class DataProcessing_Sub extends DataProcessing_Add { public DataProcessing_Sub(int instr) { @@ -339,6 +390,7 @@ } } + /** Reverse subtract. <code>Rd = - op1 + op2</code>.*/ private final class DataProcessing_Rsb extends DataProcessing_Add { protected DataProcessing_Rsb(int instr) { @@ -351,10 +403,19 @@ } } + /** Add with carry. <code>Rd = op1 + op2 + CARRY</code>. + * If the carry flag is set, the instruction will add 1 to one of the operands (whichever operands would + * not cause an overflow). Then, the normal add-routine is being invoked. + * The class is also used as a base class for the subtract with carry (SBC) and reverse subtract with + * carry (RSC) instructions. Therefore, it provides added functionality to optionally negate one or both + * of the operands.*/ private class DataProcessing_Adc extends DataProcessing_Add { + /** A cached version of the first operand. A carry might be added to this operand. */ protected int cachedOperand1; + /** A cached version of the second operand. A carry might be added to this operand, if no carry could + * be added to the first operand.. */ protected int cachedOperand2; protected DataProcessing_Adc(int instr) { @@ -362,19 +423,37 @@ } @Override - protected int resolveOperand1() { + protected final int resolveOperand1() { return cachedOperand1; } @Override - protected int resolveOperand2() { + protected final int resolveOperand2() { return cachedOperand2; } + + /** Shall be overwritten by deriving classes, if they wish the first operand to be negated before + * the addition. */ + protected boolean negateOperand1() { + return false; + } + + /** Shall be overwritten by deriving classes, if they wish the second operand to be negated before + * the addition. */ + protected boolean negateOperand2() { + return false; + } @Override public void execute() { cachedOperand1 = super.resolveOperand1(); cachedOperand2 = super.resolveOperand2(); + + if (negateOperand1()) + cachedOperand1 = -cachedOperand1; + + if (negateOperand2()) + cachedOperand2 = -cachedOperand2; if (regs.isCarrySet()) { if (cachedOperand1 != Integer.MAX_VALUE) { @@ -391,6 +470,7 @@ } } + /** Subtract with carry. <code>Rd = op1 - op2 + CARRY</code>.*/ private class DataProcessing_Sbc extends DataProcessing_Adc { protected DataProcessing_Sbc(int instr) { @@ -398,11 +478,12 @@ } @Override - protected int resolveOperand2() { - return -cachedOperand2; + protected boolean negateOperand2() { + return true; } } + /** Reserve subtract with carry. <code>Rd = -op1 + op2 + CARRY</code>.*/ private class DataProcessing_Rsc extends DataProcessing_Adc { protected DataProcessing_Rsc(int instr) { @@ -410,11 +491,13 @@ } @Override - protected int resolveOperand1() { - return -cachedOperand1; + protected boolean negateOperand1() { + return true; } } + /** Set the flags according to the logical-and of two values. + * <code>Flags = op1 & op2</code>*/ private class DataProcessing_Tst extends DataProcessing { protected DataProcessing_Tst(int instr) { @@ -423,10 +506,12 @@ @Override public void execute() { - setFlagsForResult(resolveOperand1() & resolveOperand2()); + setFlagsForLogicalOperator(resolveOperand1() & resolveOperand2()); } } + /** Sets the flags according to the exclusive-or of two values. + * <code>Flags = op1 ^ op2</code> */ private class DataProcessing_Teq extends DataProcessing { protected DataProcessing_Teq(int instr) { @@ -435,10 +520,12 @@ @Override public void execute() { - setFlagsForResult(resolveOperand1() ^ resolveOperand2()); + setFlagsForLogicalOperator(resolveOperand1() ^ resolveOperand2()); } } + /** Set the flags according to the comparison of two values. + * <code>Flags = op1 - op2</code> */ private class DataProcessing_Cmp extends DataProcessing { protected DataProcessing_Cmp(int instr) { @@ -451,6 +538,8 @@ } } + /** Set the flags according to the comparison of two values, negating the 2nd value on the way. + * <code>Flags = op1 + op2</code>. */ private class DataProcessing_Cmn extends DataProcessing { protected DataProcessing_Cmn(int instr) { @@ -463,6 +552,7 @@ } } + /** Binary or. <code>Rd = op1 | op2</code>. */ private class DataProcessing_Orr extends DataProcessing { protected DataProcessing_Orr(int instr) { @@ -473,7 +563,7 @@ public void execute() { int result = resolveOperand1() | resolveOperand2(); regs.set(Rd, result); - setFlagsForResult(result); + setFlagsForLogicalOperator(result); } } @@ -484,13 +574,16 @@ } @Override + /** Moves a value into a register .*/ public void execute() { int result = resolveOperand2(); regs.set(Rd, result); - setFlagsForResult(result); + setFlagsForLogicalOperator(result); } } + /** Bit clear. Clear bits in a register by a mask given by a second operand. + * <code>Rd = op1 & (~op2)</code>.*/ private class DataProcessing_Bic extends DataProcessing { protected DataProcessing_Bic(int instr) { @@ -498,13 +591,16 @@ } @Override + /** Clear bits in a register by a mask given by a second operand. */ public void execute() { int result = resolveOperand1() & (~resolveOperand2()); regs.set(Rd, result); - setFlagsForResult(result); + setFlagsForLogicalOperator(result); } } + /** Move and negate. Moves an integer between two registers, negating it on the way. + * <code>Rd = -op2</code>.*/ private class DataProcessing_Mvn extends DataProcessing { protected DataProcessing_Mvn(int instr) { @@ -515,10 +611,12 @@ public void execute() { int result = ~resolveOperand2(); regs.set(Rd, result); - setFlagsForResult(result); + setFlagsForLogicalOperator(result); } } + /** Count the number of leading zeros in an integer. + * <code>Rd = Number_Of_Leading_Zeroes(op2) </code> */ private class DataProcessing_Clz extends DataProcessing { protected DataProcessing_Clz(int instr) { @@ -527,11 +625,14 @@ @Override public void execute() { - int result = Integer.numberOfLeadingZeros(resolveOperand1()); + int result = Integer.numberOfLeadingZeros(resolveOperand2()); regs.set(Rd, result); } } + /** Swap a register and a memory value. + * TODO: At the moment, Pearcolator does not support any way of locking the memory. However, once it does + * any other memory accesses should be pending until the swap instruction succeeds.*/ private class Swap extends ARM_Instructions.Swap implements ARM_Instruction { @@ -556,6 +657,7 @@ } } + /** Transfer multiple registers at once between the register bank and the memory. */ private class BlockDataTransfer extends ARM_Instructions.BlockDataTransfer implements ARM_Instruction { @@ -662,6 +764,7 @@ } } + /** Branch to another instruction address. */ private class Branch extends ARM_Instructions.Branch implements ARM_Instruction { @@ -670,11 +773,9 @@ } public void execute() { + //remember the previous address, taking ARM's register offset into account int previousAddress = regs.get(ARM_Registers.PC); - //jump to the new address - regs.set(ARM_Registers.PC, previousAddress + getOffset()); - //if we're supposed to link, then write the previous address into the link register if (link) regs.set(ARM_Registers.LR, previousAddress + 4); @@ -685,6 +786,7 @@ } } + /** Branch to another instruction address and switch between ARM32 and Thumb code on the way.*/ private class BranchExchange extends ARM_Instructions.BranchExchange implements ARM_Instruction { @@ -693,8 +795,13 @@ } public void execute() { - int previousAddress = regs.get(ARM_Registers.PC); + //remember the previous address + int previousAddress = regs.get(ARM_Registers.PC) + 8; + + //are we supposed to jump to thumb (thumb=true) or ARM32 (thumb=false)? boolean thumb; + + //the address of the instruction we're jumping to int targetAddress; switch (target.getType()) { @@ -720,7 +827,7 @@ //if we're supposed to link, then write the previous address into the link register if (link) - regs.set(ARM_Registers.LR, previousAddress + 4); + regs.set(ARM_Registers.LR, previousAddress - 4); } public int getSuccessor(int pc) { @@ -734,6 +841,7 @@ } } + /** Multiply two integers into a register, possibly adding the value of a third register on the way. */ private class IntMultiply extends ARM_Instructions.IntMultiply implements ARM_Instruction { @@ -742,11 +850,29 @@ } public void execute() { + //get the two operands + int operand1 = regs.get(Rm); + int operand2 = regs.get(Rs); + + //if any of the operands is the PC, consider ARM's PC offset + if (Rm == ARM_Registers.PC) + operand1 += 8; + + if (Rs == ARM_Registers.PC) + operand2 += 8; + + //calculate the result int result = regs.get(Rm) * regs.get(Rs); - if (accumulate) + if (accumulate) { result += regs.get(Rn); + + //also consider ARM's PC offset when adding the accumulate register + if (Rn == ARM_Registers.PC) + result += 8; + } + //and finally, update the register map regs.set(Rd, result); if (updateConditionCodes) { @@ -755,10 +881,14 @@ } public int getSuccessor(int pc) { - return pc + 4; + if (Rd != ARM_Registers.PC) + return pc + 4; + else + return -1; } } + /** Move the value of the program status register into a register. */ private class MoveFromStatusRegister extends ARM_Instructions.MoveFromStatusRegister implements ARM_Instruction { @@ -768,22 +898,23 @@ } public void execute() { - int statusRegisterValue; + //do we have to transfer the saved or the current PSR? if (transferSavedPSR) { - statusRegisterValue = regs.getSPSR(); - } else { - statusRegisterValue = regs.getCPSR(); + regs.set(Rd, regs.getSPSR()); + } + else { + regs.set(Rd, regs.getCPSR()); } - - regs.set(Rd, statusRegisterValue); } public int getSuccessor(int pc) { + //Rd should never be the PC, so we can safely predict the next instruction return pc + 4; } } + /** Invoke a software interrupt. */ private class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt implements ARM_Instruction { @@ -801,6 +932,8 @@ } + /** Transfers a single data item (either a byte, half-byte or word) between a register and memory. + * This operation can either be a load from or a store to memory. */ private class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer implements ARM_Instruction { @@ -808,6 +941,7 @@ super(instr); } + /** Resolves the address of the memory slot, that is involved in the transfer. */ private int resolveAddress() { //acquire the base address @@ -885,15 +1019,18 @@ } public void execute() { + //should we simulate a user-mode memory access? if (forceUserMode) { //TODO: Implement user mode memory access throw new RuntimeException( "Forced user mode memory access is not yet supported."); } + //get the address of the memory, that we're supposed access int address = resolveAddress(); if (isLoad) { + //we are loading a value from memory. Load it into this variable. int value; switch (size) { @@ -919,8 +1056,10 @@ throw new RuntimeException("Unexpected memory size: " + size); } + //finally, write the variable into a register regs.set(Rd, value); } else { + //we are store a value from a register to memory. int value = regs.get(Rd); switch (size) { @@ -941,6 +1080,8 @@ } } + //should the memory address, which we accessed, be written back into a register? This is used for continuos + //memory accesses if (writeBack) { if (preIndexing) regs.set(Rn, address); @@ -960,6 +1101,8 @@ } } + /** Represents an undefined instruction, will throw a runtime error when this instruction + * is executed. */ private class UndefinedInstruction implements ARM_Instruction { private final int instruction; @@ -981,7 +1124,9 @@ } } - class InterpreterFactory implements + /** This class will create instances of the different interpreter instructions. It is being "controlled" by + * the ARM_InstructionDecoder, which uses an abstract factory pattern to decode an instruction. */ + private class InterpreterFactory implements ARM_InstructionFactory<ARM_Instruction> { public ARM_Instruction createDataProcessing(int instr) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-18 17:40:18
|
Revision: 69 http://svn.sourceforge.net/pearcolator/?rev=69&view=rev Author: michael_baer Date: 2007-04-18 10:40:18 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Intermediate commit: First version of an ARM interpreter that is able to run a small loop. Modified Paths: -------------- src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/memory/DebugMemory.java Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/Main.java 2007-04-18 17:40:18 UTC (rev 69) @@ -8,9 +8,12 @@ */ package org.binarytranslator; +import java.io.File; + import org.binarytranslator.generic.execution.DynamicTranslationController; import org.binarytranslator.generic.execution.ExecutionController; import org.binarytranslator.generic.execution.GdbController; +import org.binarytranslator.generic.execution.InterpreterController; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -60,11 +63,18 @@ return; } + //check if the user actually supplied an executable name if (DBT_Options.executableFile == null) { System.err.println("Missing executable file name"); showUsage(); return; } + + //also make sure that the said executable really exists + if (!new File(DBT_Options.executableFile).exists()) { + System.err.println("The specified executable '" + DBT_Options.executableFile + "' could not be found."); + return; + } ProcessSpace ps; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-18 17:40:18 UTC (rev 69) @@ -7,7 +7,6 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorDataProcessing; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorDataTransfer; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorRegisterTransfer; -import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CountLeadingZeros; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.IntMultiply; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.LongMultiply; @@ -143,7 +142,10 @@ * @return A human readable form of this instructions condition. */ private String cond(Instruction instr) { - return instr.getCondition().name(); + if (instr.getCondition() == Condition.AL) + return ""; + else + return instr.getCondition().name(); } /** @@ -157,7 +159,7 @@ private final String operand(OperandWrapper op) { switch (op.getType()) { case Immediate: - return String.format("#%x", op.getImmediate()); + return String.format("#%d", op.getImmediate()); case ImmediateShiftedRegister: return String.format("r%d %s #%d", op.getRegister(), op.getShiftType(), @@ -165,9 +167,9 @@ case PcRelative: if (address != -1) - return String.format("#%x", op.getOffset() + address + 8); + return String.format("#0x%x", op.getOffset() + address + 8); else - return String.format("#<%x + pc>", op.getOffset()); + return String.format("#<%d + pc>", op.getOffset()); case Register: return "r" + op.getRegister(); @@ -193,14 +195,15 @@ // Filter instructions that only take one parameter if (instr.getOpcode() != DataProcessing.Opcode.MOV - && instr.getOpcode() != DataProcessing.Opcode.MVN) { + && instr.getOpcode() != DataProcessing.Opcode.MVN + && instr.getOpcode() != DataProcessing.Opcode.CLZ) { optionalParam = ", " + operand(instr.getOperand2()); } else optionalParam = ""; - setResult(String.format("%s r%d, r%d %s", mnemonic, instr.getRd(), instr - .getRn(), optionalParam)); + setResult(String.format("%s r%d, r%d%s", mnemonic, instr.getRd(), instr + .getOperandRegister(), optionalParam)); } public void visit(SingleDataTransfer instr) { @@ -308,7 +311,7 @@ public void visit(SoftwareInterrupt instr) { - setResult(String.format("SWI%s #%x", cond(instr), instr + setResult(String.format("SWI%s #0x%x", cond(instr), instr .getInterruptNumber())); } @@ -317,15 +320,15 @@ String mnemonic = instr.link() ? "BL" : "B"; if (address != -1) - setResult(String.format("%s%s #%x", mnemonic, cond(instr), instr.getOffset() + address + 8)); + setResult(String.format("%s%s #%d", mnemonic, cond(instr), instr.getOffset() + address + 8)); else - setResult(String.format("%s%s #<%x + pc>", mnemonic, cond(instr), instr.getOffset())); + setResult(String.format("%s%s #<%d + pc>", mnemonic, cond(instr), instr.getOffset())); } public void visit(BranchExchange instr) { String mnemonic = instr.link ? "BLX" : "BX"; - setResult(String.format("%s%s #%x", mnemonic, cond(instr), operand(instr + setResult(String.format("%s%s #%d", mnemonic, cond(instr), operand(instr .target()))); } @@ -407,11 +410,5 @@ setResult(String.format("MSR%s %s, %s", cond(instr), fields, operand(instr.getSource()))); } - - public void visit(CountLeadingZeros instr) { - - setResult(String.format("CLZ%s r%s r%s ", cond(instr), instr.getRd(), - instr.getRm())); - } } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-18 17:40:18 UTC (rev 69) @@ -180,7 +180,7 @@ //bit 6 and 7 are clear if (Utils.getBit(instr, 4)) { if (Utils.getBit(instr, 22)) - return factory.createCountLeadingZeros(instr); + return factory.createDataProcessing(instr); //should be a CLZ instruction else return factory.createBranchExchange(instr); } @@ -249,7 +249,6 @@ T createCoprocessorRegisterTransfer(int instr); T createMoveFromStatusRegister(int instr); T createMoveToStatusRegister(int instr); - T createCountLeadingZeros(int instr); T createUndefinedInstruction(int instr); } @@ -283,10 +282,6 @@ return new CoprocessorRegisterTransfer(instr); } - public Instruction createCountLeadingZeros(int instr) { - return new CountLeadingZeros(instr); - } - public Instruction createDataProcessing(int instr) { return new DataProcessing(instr); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-18 17:40:18 UTC (rev 69) @@ -19,5 +19,4 @@ void visit(CoprocessorRegisterTransfer instr); void visit(MoveFromStatusRegister instr); void visit(MoveToStatusRegister instr); - void visit(CountLeadingZeros instr); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-18 17:40:18 UTC (rev 69) @@ -28,7 +28,7 @@ protected final Condition condition; private Instruction(int instr) { - condition = Condition.values()[(byte) Utils.getBits(instr, 28, 31)]; + condition = Condition.values()[(instr & 0xF0000000) >>> 28]; } /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ @@ -190,6 +190,22 @@ return new PcRelativeOperand(offset); } + public static OperandWrapper decodeDataProcessingOperand(int instr) { + if (Utils.getBit(instr, 25)) { + //this is a right-rotated immediate value + byte shiftAmount = (byte)(Utils.getBits(instr, 8, 11) << 2); + int value = instr & 0xFF; + + if (shiftAmount == 0) + return new ImmediateOperand(value); + else + return new RightRotatedImmediateOperand(value, shiftAmount); + } + else { + return decodeShiftedRegister(instr); + } + } + /** Creates an operand wrapper, that represents a register shifted by an immediate or a register, depending on the instruction. */ public static OperandWrapper decodeShiftedRegister(int instr) { ShiftType shift = ShiftType.values()[Utils.getBits(instr, 5, 6)]; @@ -283,6 +299,39 @@ } } + /** Represents an immediate value operand. */ + protected static class RightRotatedImmediateOperand extends ImmediateOperand { + + /** @see #getShiftAmount() */ + protected final byte shiftAmount; + + protected RightRotatedImmediateOperand(int immediate, byte shiftAmount) { + super(Integer.rotateRight(immediate, shiftAmount)); + this.shiftAmount = shiftAmount; + } + + @Override + public int getImmediate() { + return immediate; + } + + /** The amount of shifting that had to be performed to create this immediate. */ + @Override + public byte getShiftAmount() { + return shiftAmount; + } + + @Override + public ShiftType getShiftType() { + return ShiftType.ROR; + } + + @Override + public Type getType() { + return Type.Immediate; + } + } + protected static class PcRelativeOperand extends OperandWrapper { protected final int offset; @@ -392,14 +441,13 @@ } /** Represents a Data Processing instruction. */ - public static class DataProcessing extends - TwoRegistersTemplate { + public static class DataProcessing extends Instruction { /** A list of possible DataProcessing operations. The list is orded in ascendingly, with the * first opcode corresponding to opcode 0 (zero) in the opcode field of an ARM data processing * instruction. */ public enum Opcode { - AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN + AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN, CLZ } /** @see #hasSetConditionCodes() */ @@ -411,18 +459,42 @@ /** @see #getOperand2() */ protected final OperandWrapper operand2; + /** @see #getOperandRegister() */ + protected final byte operandRegister; + + /** @see #getRd() */ + protected final byte Rd; + public DataProcessing(int instr) { super(instr); + + Rd = (byte) Utils.getBits(instr, 12, 15); updateConditionCodes = Utils.getBit(instr, 20); - opcode = Opcode.values()[(byte) Utils.getBits(instr, 21, 24)]; - - if (Utils.getBit(instr, 25)) - operand2 = OperandWrapper.createImmediate(Integer.rotateRight(instr & 0xFF, Utils.getBits(instr, 8, 11) << 2)); - else - operand2 = OperandWrapper.decodeShiftedRegister(instr); + + if (Utils.getBits(instr, 20, 27) == 0x16 && Utils.getBits(instr, 4, 7) == 1) { + //this is a CLZ instruction, which we're catching and merging into the data processing instructions + operandRegister = (byte) (instr & 0xF); + opcode = Opcode.CLZ; + operand2 = OperandWrapper.createImmediate(0); + } + else { + operandRegister = (byte) Utils.getBits(instr, 16, 19); + opcode = Opcode.values()[(byte) Utils.getBits(instr, 21, 24)]; + operand2 = OperandWrapper.decodeDataProcessingOperand(instr); + } } + /** Returns the number of the operation's destination register, starting from 0.*/ + public final byte getRd() { + return Rd; + } + + /** Returns the number of the operation's first operand register, starting from 0.*/ + public final byte getOperandRegister() { + return operandRegister; + } + /** Returns the opcode, that specifies the data processing operation, which is to be performed. */ public final Opcode getOpcode() { return opcode; @@ -498,9 +570,9 @@ size = TransferSize.Word; if (Utils.getBit(instr, 25)) - offset = OperandWrapper.createImmediate(instr & 0xFF); + offset = OperandWrapper.decodeShiftedRegister(instr); else - offset = OperandWrapper.decodeShiftedRegister(instr); + offset = OperandWrapper.createImmediate(instr & 0xFFF); } else { //this is a byte or half-word transfer @@ -524,6 +596,9 @@ //The decoder should make sure that we're never being called with this combination if (DBT.VerifyAssertions) DBT._assert(!signExtend || isLoad); } + + //this instruction variant yields an undefined result + if (DBT.VerifyAssertions) DBT._assert(Rd != 15 || !writeBack); } /** Returns true, if this memory access shall be treated as if it had been done in user mode. */ @@ -760,7 +835,7 @@ public Branch(int instr) { super(instr); link = Utils.getBit(instr, 24); - offset = instr & 0xFFF; + offset = Utils.signExtend((instr & 0xFFF) << 2, 14); } /** Should the current PC be put into the lr? */ @@ -1082,13 +1157,9 @@ transferExtension = Utils.getBit(instr, 17); transferStatus = Utils.getBit(instr, 18); transferFlags = Utils.getBit(instr, 19); - transferSavedPSR = Utils.getBit(instr, 22); - if (Utils.getBit(instr, 25)) - sourceOperand = OperandWrapper.createImmediate((instr & 0xFF) << Utils.getBits(instr, 8, 11)); - else - sourceOperand = OperandWrapper.decodeShiftedRegister(instr); + sourceOperand = OperandWrapper.decodeDataProcessingOperand(instr); } /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ @@ -1126,36 +1197,4 @@ visitor.visit(this); } } - - /** Represents a CLZ instruction. */ - public static class CountLeadingZeros extends Instruction { - - /** @see #getRm() */ - protected final byte Rm; - - /** @see #getRd() */ - protected final byte Rd; - - public CountLeadingZeros(int instr) { - super(instr); - - Rm = (byte) (instr & 0xF); - Rd = (byte) Utils.getBits(instr, 12, 15); - } - - /** Returns the source register for this operation. */ - public final byte getRm() { - return Rm; - } - - /** Returns the destination register for this operation. */ - public final byte getRd() { - return Rd; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-18 17:40:18 UTC (rev 69) @@ -1,43 +1,116 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; -import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.generic.decoder.Interpreter; -import org.binarytranslator.generic.decoder.Interpreter.Instruction; -public class ARM_Interpreter { +public class ARM_Interpreter implements Interpreter { protected final ARM_ProcessSpace ps; - protected final ARM_Registers regs; + protected final InterpreterFactory instructionFactory; public ARM_Interpreter(ARM_ProcessSpace ps) { this.ps = ps; this.regs = ps.registers; + instructionFactory = new InterpreterFactory(); } + public Instruction decode(int pc) { + + int binaryInstruction = ps.memory.loadInstruction32(pc); + ARM_Instruction instruction = ARM_InstructionDecoder.decode(binaryInstruction, instructionFactory); + + if (instruction.getCondition() != Condition.AL) { + return new ConditionalDecorator(instruction); + } + + return instruction; + } + + private interface ARM_Instruction extends Interpreter.Instruction { + Condition getCondition(); + } + private final class ConditionalDecorator implements Interpreter.Instruction { - protected final Interpreter.Instruction conditionalInstruction; + protected final ARM_Instruction conditionalInstruction; - protected ConditionalDecorator(Interpreter.Instruction i) { + protected ConditionalDecorator(ARM_Instruction i) { conditionalInstruction = i; } - + public void execute() { - conditionalInstruction.execute(); + if (isConditionTrue()) + conditionalInstruction.execute(); } public int getSuccessor(int pc) { return -1; } + + private boolean isConditionTrue() { + switch (conditionalInstruction.getCondition()) { + case AL: + return true; + + case CC: + return !regs.isCarrySet(); + + case CS: + return regs.isCarrySet(); + + case EQ: + return regs.isZeroSet(); + + case GE: + return regs.isNegativeSet() == regs.isOverflowSet(); + + case GT: + return (regs.isNegativeSet() == regs.isOverflowSet()) && regs.isZeroSet(); + + case HI: + return regs.isCarrySet() && !regs.isZeroSet(); + + case LE: + return regs.isZeroSet() || (regs.isNegativeSet() == regs.isOverflowSet()); + + case LS: + return !regs.isCarrySet() || regs.isZeroSet(); + + case LT: + return regs.isNegativeSet() != regs.isOverflowSet(); + + case MI: + return regs.isNegativeSet(); + + case NE: + return !regs.isZeroSet(); + + case NV: + return false; + + case PL: + return !regs.isNegativeSet(); + + case VC: + return !regs.isOverflowSet(); + + case VS: + return regs.isOverflowSet(); + + default: + throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); + } + } } private abstract class DataProcessing extends ARM_Instructions.DataProcessing - implements Interpreter.Instruction { + implements ARM_Instruction { protected boolean shifterCarryOut; @@ -59,43 +132,59 @@ switch (operand.getShiftType()) { case ASR: - if (shiftAmount > 32) - shiftAmount = 32; + if (shiftAmount >= 32) { + shifterCarryOut = Utils.getBit(value, 31); + return shifterCarryOut ? 0xFFFFFFFF : 0; + } if (shiftAmount == 0) { shifterCarryOut = regs.isCarrySet(); return value; - } else { - shifterCarryOut = Utils.getBit(value, shiftAmount - 1); - return value >>> shiftAmount; } + + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >>> shiftAmount; case LSL: - if (shiftAmount > 32) - shiftAmount = 32; + if (shiftAmount > 32) { + shifterCarryOut = false; + return 0; + } + if (shiftAmount == 32) { + shifterCarryOut = Utils.getBit(value, 31); + return 0; + } + if (shiftAmount == 0) { shifterCarryOut = regs.isCarrySet(); return value; - } else { - shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); - return value << shiftAmount; } + shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); + return value << shiftAmount; + case LSR: - if (shiftAmount > 32) - shiftAmount = 32; + if (shiftAmount > 32) { + shifterCarryOut = false; + return 0; + } + + if (shiftAmount == 32) { + shifterCarryOut = Utils.getBit(value, 31); + return 0; + } if (shiftAmount == 0) { shifterCarryOut = regs.isCarrySet(); return value; - } else { - shifterCarryOut = Utils.getBit(value, shiftAmount - 1); - return value >> shiftAmount; } + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >> shiftAmount; + case ROR: if (shiftAmount == 0) { @@ -120,6 +209,15 @@ } } + protected int resolveOperand1() { + + if (operandRegister == ARM_Registers.PC) { + return regs.get(operandRegister) + 8; + } + + return regs.get(operandRegister); + } + protected int resolveOperand2() { int value; @@ -131,6 +229,8 @@ shifterCarryOut = regs.isCarrySet(); else shifterCarryOut = (value & 0x80000000) != 0; + + return value; case Register: shifterCarryOut = regs.isCarrySet(); @@ -147,7 +247,6 @@ } } - public abstract void execute(); protected final void setFlagsForResult(int result) { @@ -160,7 +259,7 @@ } } } - + protected final void setFlagsForAdd(int lhs, int rhs) { if (updateConditionCodes) { @@ -177,7 +276,7 @@ } public int getSuccessor(int pc) { - if (Rd == 15) + if (Rd != 15) return pc + 4; else return -1; @@ -189,11 +288,10 @@ protected DataProcessing_And(int instr) { super(instr); } - @Override public void execute() { - int result = regs.get(Rn) & resolveOperand2(); + int result = resolveOperand1() & resolveOperand2(); regs.set(Rd, result); setFlagsForResult(result); } @@ -207,7 +305,7 @@ @Override public void execute() { - int result = regs.get(Rn) ^ resolveOperand2(); + int result = resolveOperand1() ^ resolveOperand2(); regs.set(Rd, result); setFlagsForResult(result); } @@ -218,16 +316,12 @@ public DataProcessing_Add(int instr) { super(instr); } - - protected int resolveOperand1() { - return regs.get(Rn); - } - + public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); int result = operand1 + operand2; - + regs.set(Rd, result); setFlagsForAdd(operand1, operand2); } @@ -260,6 +354,7 @@ private class DataProcessing_Adc extends DataProcessing_Add { protected int cachedOperand1; + protected int cachedOperand2; protected DataProcessing_Adc(int instr) { @@ -307,7 +402,7 @@ return -cachedOperand2; } } - + private class DataProcessing_Rsc extends DataProcessing_Adc { protected DataProcessing_Rsc(int instr) { @@ -319,7 +414,7 @@ return -cachedOperand1; } } - + private class DataProcessing_Tst extends DataProcessing { protected DataProcessing_Tst(int instr) { @@ -328,10 +423,10 @@ @Override public void execute() { - setFlagsForResult(regs.get(Rn) & resolveOperand2()); + setFlagsForResult(resolveOperand1() & resolveOperand2()); } } - + private class DataProcessing_Teq extends DataProcessing { protected DataProcessing_Teq(int instr) { @@ -340,10 +435,10 @@ @Override public void execute() { - setFlagsForResult(regs.get(Rn) ^ resolveOperand2()); + setFlagsForResult(resolveOperand1() ^ resolveOperand2()); } } - + private class DataProcessing_Cmp extends DataProcessing { protected DataProcessing_Cmp(int instr) { @@ -352,10 +447,10 @@ @Override public void execute() { - setFlagsForAdd(regs.get(Rn), -resolveOperand2()); + setFlagsForAdd(resolveOperand1(), -resolveOperand2()); } } - + private class DataProcessing_Cmn extends DataProcessing { protected DataProcessing_Cmn(int instr) { @@ -364,10 +459,10 @@ @Override public void execute() { - setFlagsForAdd(regs.get(Rn), resolveOperand2()); + setFlagsForAdd(resolveOperand1(), resolveOperand2()); } } - + private class DataProcessing_Orr extends DataProcessing { protected DataProcessing_Orr(int instr) { @@ -376,12 +471,12 @@ @Override public void execute() { - int result = regs.get(Rn) | resolveOperand2(); + int result = resolveOperand1() | resolveOperand2(); regs.set(Rd, result); setFlagsForResult(result); } } - + private class DataProcessing_Mov extends DataProcessing { protected DataProcessing_Mov(int instr) { @@ -395,7 +490,7 @@ setFlagsForResult(result); } } - + private class DataProcessing_Bic extends DataProcessing { protected DataProcessing_Bic(int instr) { @@ -404,12 +499,12 @@ @Override public void execute() { - int result = regs.get(Rn) & (~resolveOperand2()); + int result = resolveOperand1() & (~resolveOperand2()); regs.set(Rd, result); setFlagsForResult(result); } } - + private class DataProcessing_Mvn extends DataProcessing { protected DataProcessing_Mvn(int instr) { @@ -424,125 +519,175 @@ } } - private class Swap extends ARM_Instructions.Swap implements Interpreter.Instruction { + private class DataProcessing_Clz extends DataProcessing { + protected DataProcessing_Clz(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = Integer.numberOfLeadingZeros(resolveOperand1()); + regs.set(Rd, result); + } + } + + private class Swap extends ARM_Instructions.Swap implements + ARM_Instruction { + public Swap(int instr) { super(instr); } public void execute() { int memAddr = regs.get(Rn); - + //swap exchanges the value of a memory address with the value in a register int tmp = ps.memory.load32(memAddr); ps.memory.store16(memAddr, regs.get(Rm)); - + //according to the ARM architecture reference, the value loaded from a memory address is rotated //according to the number of ones in the first two bits of the address regs.set(Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); } public int getSuccessor(int pc) { - return pc+4; + return pc + 4; } } - - private class BlockDataTransfer extends ARM_Instructions.BlockDataTransfer implements Interpreter.Instruction { + private class BlockDataTransfer extends ARM_Instructions.BlockDataTransfer + implements ARM_Instruction { + + /** the lowest address that we're reading a register from / writing a register to */ + private final int startAddress; + + /** An array that contains the registers to be transferd in ascending order. + * The list is delimited by setting the entry after the last register index to -1. + * The PC is not included in this list, if it shall be transferred. */ + private final int[] registersToTransfer = new int[16]; + + /** True if the PC should be transferred to, false otherwise. */ + private final boolean transferPC; + public BlockDataTransfer(int instr) { super(instr); - } - public void execute() { - //start address ignores the last two bits - int startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + transferPC = transferRegister(15); + int registerCount = 0; - //build a map of registers that are to be transfered - int registerCount = 0; - boolean transferPC = false; - int[] registersToTransfer = new int[16]; - for (int i = 0; i < 14; i++) if (transferRegister(i)) { registersToTransfer[registerCount++] = i; } - - //also remember if we're supposed to transfer the pc, but don't include it in the register list - transferPC = transferRegister(15); - + + registersToTransfer[registerCount] = -1; + + //build the address, which generally ignores the last two bits if (!incrementBase) { - if (postIndexing) - startAddress -= (registerCount + (transferPC ? -1 : 0)) * 4; //post-indexing, backward reading - else - startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; //pre-indexing, backward-reading + if (postIndexing) { + //post-indexing, backward reading + startAddress = regs.get(baseRegister) & 0xFFFFFFFC + - (registerCount + (transferPC ? -1 : 0)) * 4; + } else { + //pre-indexing, backward-reading + startAddress = regs.get(baseRegister) & 0xFFFFFFFC + - (registerCount + (transferPC ? 1 : 0)) * 4; + } + } else { + if (postIndexing) { + //post-indexing, forward reading + startAddress = regs.get(baseRegister) & 0xFFFFFFFC - 4; + } else { + //pre-indexing, forward reading + startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + } } - else if (postIndexing) { - //post-indexing, forward reading - startAddress -= 4; - } - + } + + public void execute() { + int nextAddress = startAddress; + //are we supposed to load or store multiple registers? if (isLoad) { - //read the actual registers - for (int i = 0; i < registerCount; i++) { - startAddress += 4; - regs.set(registersToTransfer[i], ps.memory.load32(startAddress)); + int nextReg = 0; + + while (registersToTransfer[nextReg] != -1) { + nextAddress += 4; + regs.set(registersToTransfer[nextReg++], ps.memory + .load32(nextAddress)); } - + //if we also transferred the program counter if (transferPC) { - int newpc = ps.memory.load32(startAddress + 4); + nextAddress += 4; + int newpc = ps.memory.load32(nextAddress); regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); - + //shall we switch to thumb mode regs.setThumbMode((newpc & 0x1) != 0); } - } - else { + } else { + int nextReg = 0; + + while (registersToTransfer[nextReg] != -1) { + nextAddress += 4; + ps.memory.store32(nextAddress, regs + .get(registersToTransfer[nextReg++])); + } + //also transfer the program counter, if requested so - if (transferPC) - registersToTransfer[registerCount++] = 15; - - for (int i = 0; i < registerCount; i++) { - startAddress += 4; - ps.memory.store32(startAddress, regs.get(i)); + if (transferPC) { + nextAddress += 4; + ps.memory.store32(nextAddress, regs.get(15)); } } + + if (writeBack) { + //write the last address we read from back to a register + //TODO: Check if we have to consider the different cases? + if (!incrementBase) + nextAddress = startAddress; + + regs.set(baseRegister, nextAddress); + } } public int getSuccessor(int pc) { //if we're loading values into the PC, then we can't tell where this instruction will be going - if (isLoad && transferRegister(ARM_Registers.PC)) + if (isLoad && transferPC) return -1; else - return pc+4; + return pc + 4; } } - - private class Branch extends ARM_Instructions.Branch implements Interpreter.Instruction { + private class Branch extends ARM_Instructions.Branch implements + ARM_Instruction { + public Branch(int instr) { super(instr); } public void execute() { int previousAddress = regs.get(ARM_Registers.PC); - + //jump to the new address regs.set(ARM_Registers.PC, previousAddress + getOffset()); - + //if we're supposed to link, then write the previous address into the link register if (link) regs.set(ARM_Registers.LR, previousAddress + 4); } public int getSuccessor(int pc) { - return pc + getOffset(); + return pc + getOffset() + 8; } } - - private class BranchExchange extends ARM_Instructions.BranchExchange implements Interpreter.Instruction { + private class BranchExchange extends ARM_Instructions.BranchExchange + implements ARM_Instruction { + public BranchExchange(int instr) { super(instr); } @@ -551,13 +696,13 @@ int previousAddress = regs.get(ARM_Registers.PC); boolean thumb; int targetAddress; - + switch (target.getType()) { case PcRelative: targetAddress = previousAddress + target.getOffset(); thumb = true; break; - + case Register: targetAddress = regs.get(target.getRegister()); thumb = (targetAddress & 0x1) != 0; @@ -565,13 +710,14 @@ break; default: - throw new RuntimeException("Unexpected Operand type: " + target.getType()); + throw new RuntimeException("Unexpected Operand type: " + + target.getType()); } - + //jump to the new address regs.set(ARM_Registers.PC, targetAddress); regs.setThumbMode(thumb); - + //if we're supposed to link, then write the previous address into the link register if (link) regs.set(ARM_Registers.LR, previousAddress + 4); @@ -581,55 +727,41 @@ //if we're jumping relative to the PC, then we can predict the next instruction if (target.getType() == OperandWrapper.Type.PcRelative) { return pc + target.getOffset(); - } - else { + } else { //otherwise we can't predict it return -1; } } } - - private class CountLeadingZeros extends ARM_Instructions.CountLeadingZeros implements Interpreter.Instruction { - public CountLeadingZeros(int instr) { - super(instr); - } + private class IntMultiply extends ARM_Instructions.IntMultiply implements + ARM_Instruction { - public void execute() { - int leadingZeros = Integer.numberOfLeadingZeros(regs.get(Rm)); - regs.set(Rd, leadingZeros); - } - - public int getSuccessor(int pc) { - return pc+4; - } - } - - private class IntMultiply extends ARM_Instructions.IntMultiply implements Interpreter.Instruction { - protected IntMultiply(int instr) { super(instr); } public void execute() { int result = regs.get(Rm) * regs.get(Rs); - + if (accumulate) result += regs.get(Rn); - + regs.set(Rd, result); - + if (updateConditionCodes) { regs.setFlags(result < 0, result == 0); } } public int getSuccessor(int pc) { - return pc+4; + return pc + 4; } } - private class MoveFromStatusRegister extends ARM_Instructions.MoveFromStatusRegister implements Interpreter.Instruction { + private class MoveFromStatusRegister extends + ARM_Instructions.MoveFromStatusRegister implements + ARM_Instruction { public MoveFromStatusRegister(int instr) { super(instr); @@ -637,24 +769,24 @@ public void execute() { int statusRegisterValue; - + if (transferSavedPSR) { statusRegisterValue = regs.getSPSR(); - } - else { + } else { statusRegisterValue = regs.getCPSR(); } - + regs.set(Rd, statusRegisterValue); } public int getSuccessor(int pc) { - return pc+4; + return pc + 4; } } - - private class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt implements Interpreter.Instruction { + private class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt + implements ARM_Instruction { + public SoftwareInterrupt(int instr) { super(instr); } @@ -666,33 +798,172 @@ public int getSuccessor(int pc) { return -1; } - + } - - private class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer implements Interpreter.Instruction { + private class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer + implements ARM_Instruction { + public SingleDataTransfer(int instr) { super(instr); } - public void execute() { + private int resolveAddress() { + + //acquire the base address + int base = regs.get(Rn); + //take ARM's PC offset into account + if (Rn == 15) + base += 8; + + //if we are not pre-indexing, then just use the base register for the memory access + if (!preIndexing) + return base; + + switch (offset.getType()) { + case Immediate: + if (positiveOffset) + return base + offset.getImmediate(); + else + return base - offset.getImmediate(); + + case Register: + int offsetRegister = regs.get(offset.getRegister()); + if (offset.getRegister() == ARM_Registers.PC) { + offsetRegister += 8; + } + + if (positiveOffset) + return base + offsetRegister; + else + return base - offsetRegister; + + case ImmediateShiftedRegister: + if (offset.getRegister() == 15) + throw new RuntimeException( + "PC-relative memory accesses are not yet supported."); + + int addrOffset = regs.get(offset.getRegister()); + + switch (offset.getShiftType()) { + case ASR: + addrOffset = addrOffset >>> offset.getShiftAmount(); + break; + + case LSL: + addrOffset = addrOffset << offset.getShiftAmount(); + break; + + case LSR: + addrOffset = addrOffset >> offset.getShiftAmount(); + break; + + case ROR: + addrOffset = Integer.rotateRight(addrOffset, offset.getShiftAmount()); + break; + + case RRE: + if (regs.isCarrySet()) + addrOffset = (addrOffset >> 1) | 0x80000000; + else + addrOffset = addrOffset >> 1; + break; + + default: + throw new RuntimeException("Unexpected shift type: " + + offset.getShiftType()); + } + + case PcRelative: + case RegisterShiftedRegister: + default: + throw new RuntimeException("Unexpected operand type: " + + offset.getType()); + } + } + public void execute() { + if (forceUserMode) { + //TODO: Implement user mode memory access + throw new RuntimeException( + "Forced user mode memory access is not yet supported."); + } + + int address = resolveAddress(); + + if (isLoad) { + int value; + + switch (size) { + case Byte: + if (signExtend) + value = ps.memory.loadSigned8(address); + else + value = ps.memory.loadUnsigned8(address); + break; + + case HalfWord: + if (signExtend) + value = ps.memory.loadSigned16(address); + else + value = ps.memory.loadUnsigned16(address); + break; + + case Word: + value = ps.memory.load32(address); + break; + + default: + throw new RuntimeException("Unexpected memory size: " + size); + } + + regs.set(Rd, value); + } else { + int value = regs.get(Rd); + + switch (size) { + case Byte: + ps.memory.store8(address, value); + break; + + case HalfWord: + ps.memory.store16(address, value); + break; + + case Word: + ps.memory.store32(address, value); + break; + + default: + throw new RuntimeException("Unexpected memory size: " + size); + } + } + + if (writeBack) { + if (preIndexing) + regs.set(Rn, address); + else { + //TODO: calculate the post-indexed address + //and set it to Rn + } + } + } + public int getSuccessor(int pc) { //if we're loading to the PC, then the next instruction is undefined - if (Rd == ARM_Registers.PC) + if (Rd == ARM_Registers.PC && isLoad) return -1; - - return pc+4; + + return pc + 4; } - } - - private class UndefinedInstruction implements Interpreter.Instruction { - + + private class UndefinedInstruction implements ARM_Instruction { + private final int instruction; - + public UndefinedInstruction(int instr) { this.instruction = instr; } @@ -704,12 +975,16 @@ public int getSuccessor(int pc) { return -1; } + + public Condition getCondition() { + return Condition.AL; + } } class InterpreterFactory implements - ARM_InstructionFactory<Interpreter.Instruction> { + ARM_InstructionFactory<ARM_Instruction> { - public Interpreter.Instruction createDataProcessing(int instr) { + public ARM_Instruction createDataProcessing(int instr) { Opcode opcode = Opcode.values()[Utils.getBits(instr, 21, 24)]; switch (opcode) { @@ -745,6 +1020,9 @@ return new DataProcessing_Teq(instr); case TST: return new DataProcessing_Tst(instr); + + case CLZ: + return new DataProcessing_Clz(instr); default: throw new RuntimeException("Unexpected Data Procesing opcode: " @@ -752,70 +1030,68 @@ } } - public Instruction createBlockDataTransfer(int instr) { + public ARM_Instruction createBlockDataTransfer(int instr) { return new BlockDataTransfer(instr); } - public Instruction createBranch(int instr) { + public ARM_Instruction createBranch(int instr) { return new Branch(instr); } - public Instruction createBranchExchange(int instr) { + public ARM_Instruction createBranchExchange(int instr) { return new BranchExchange(instr); } - public Instruction createCoprocessorDataProcessing(int instr) { + public ARM_Instruction createCoprocessorDataProcessing(int instr) { //TODO: Implement coprocessor instructions - throw new RuntimeException("Coprocessor instructions are not yet supported."); + throw new RuntimeException( + "Coprocessor instructions are not yet supported."); } - public Instruction createCoprocessorDataTransfer(int instr) { -// TODO: Implement coprocessor instructions - throw new RuntimeException("Coprocessor instructions are not yet supported."); + public ARM_Instruction createCoprocessorDataTransfer(int instr) { + // TODO: Implement coprocessor instructions + throw new RuntimeException( + "Coprocessor instructions are not yet supported."); } - public Instruction createCoprocessorRegisterTransfer(int instr) { -// TODO: Implement coprocessor instructions - throw new RuntimeException("Coprocessor instructions are not yet supported."); + public ARM_Instruction createCoprocessorRegisterTransfer(int instr) { + // TODO: Implement coprocessor instructions + throw new RuntimeException( + "Coprocessor instructions are not yet supported."); } - public Instruction createCountLeadingZeros(int instr) { - return new CountLeadingZeros(instr); - } - - public Instruction createIntMultiply(int instr) { + public ARM_Instruction createIntMultiply(int instr) { return new IntMultiply(instr); } - public Instruction createLongMultiply(int instr) { + public ARM_Instruction createLongMultiply(int instr) { throw new RuntimeException("Long Multiplications are not yet supported."); } - public Instruction createMoveFromStatusRegister(int instr) { + public ARM_Instruction createMoveFromStatusRegister(int instr) { return new MoveFromStatusRegister(instr); } - public Instruction createMoveToStatusRegister(int instr) { + public ARM_Instruction createMoveToStatusRegister(int instr) { //TODO: Implement Register -> CPSR transfers - throw new RuntimeException("Modifying the status register using MSR is not yet supported."); + throw new RuntimeException( + "Modifying the status register using MSR is not yet supported."); } - public Instruction createSingleDataTransfer(int instr) { - // TODO Auto-generated method stub - return null; + public ARM_Instruction createSingleDataTransfer(int instr) { + return new SingleDataTransfer(instr); } - public Instruction createSoftwareInterrupt(int instr) { + public ARM_Instruction createSoftwareInterrupt(int instr) { return new SoftwareInterrupt(instr); } - public Instruction createSwap(int instr) { + public ARM_Instruction createSwap(int instr) { return new Swap(instr); } - public Instruction createUndefinedInstruction(int instr) { + public ARM_Instruction createUndefinedInstruction(int instr) { return new UndefinedInstruction(instr); } } - } Modified: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-18 17:40:18 UTC (rev 69) @@ -20,7 +20,8 @@ } /** - * Extracts a subsequence of bits from a word. + * Extracts a subsequence of bits from a word and shifts the beginning of that subsequence to + * a zero based-number. * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. * @param word * The word that is to be examined. @@ -33,7 +34,8 @@ */ static final int getBits(int word, int from, int to) { if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to <= 31); + DBT._assert(from < to && from >= 0 && to < 31); + return (word & ((1 << (to + 1)) - 1)) >> from; } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-18 17:40:18 UTC (rev 69) @@ -2,10 +2,11 @@ import java.io.IOException; import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.decoder.ARM_Interpreter; import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; -import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.generic.memory.ByteAddressedMemory; +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.memory.DebugMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; @@ -14,18 +15,10 @@ public abstract class ARM_ProcessSpace extends ProcessSpace { - /* - * Instance data - */ - /** - * Registers used by this process - */ + /** Registers used by this process */ public ARM_Registers registers; - /* - * Utility functions - */ /** * Debug information @@ -40,16 +33,9 @@ } } - /* - * Methods - */ - - /** - * Constructor - */ protected ARM_ProcessSpace() { registers = new ARM_Registers(); - memory = new ByteAddressedMemory(); + memory = new DebugMemory(); } /** @@ -82,13 +68,10 @@ return new ARM_ImageProcessSpace(); } } - - /** - * Run a single instruction - */ - public void runOneInstruction() throws BadInstructionException { - // TODO - throw new RuntimeException("Not yet implemented"); + + @Override + public Interpreter createInstructionInterpreter() throws UnsupportedOperationException { + return new ARM_Interpreter(this); } /** Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-18 14:34:18 UTC (rev 68) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-18 17:40:18 UTC (rev 69) @@ -198,5 +198,20 @@ public boolean isCarrySet() { return flagCarry; } + + /** Returns true if the zero flag is set, false otherwise. */ + public boolean isZeroSet() { + return flagZero; + } + + /** Returns true if the overflow flag is set, false otherwise. */ + public boolean isOverflowSet() { + return flagOverflow; + } + + /** Returns true if the negative flag is set, false otherwise. */ + public boolean isNegativeSet() { + return flagNegative; + } } Added: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java (rev 0) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-04-18 17:40:18 UTC (rev 69) @@ -0,0 +1,31 @@ +package org.binarytranslator.generic.execution; + +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.os.process.ProcessSpace; + +public class InterpreterController extends ExecutionController { + + public InterpreterController(ProcessSpace ps) { + super(ps); + } + + @Override + public void run() { + Interpreter interpreter = ps.createInstructionInterpreter(); + int pc = ps.getCurrentInstructionAddress(); + + while (!ps.finished) { + + Interpreter.Instruction instruction = interpreter.decode(pc); + pc = instruction.getSuccessor(pc); + + System.out.println("Interpreting instruction: " + instruction.toString()); + + instruction.execute(); + + if (pc == -1) + pc = ps.getCurrentInstructionAddress(); + } + } + +} Added: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java (rev 0) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-04-18 17:40:18 UTC (rev 69) @@ -0,0 +1,539 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ +package org.binarytranslator.generic.memory; + +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import org.binarytranslator.DBT_Options; +import org.binarytranslator.vmInterface.TranslationHelper; +import org.jikesrvm.compilers.opt.ir.OPT_Operand; +import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; + +/** + * A copy of byte-addressed memory, that does not allow the translation of accesses to bytecode. + * This is stricly for debugging purposes, as it allows the Pearcolator interpreter to be executed + * in a windows environment. + */ +public class DebugMemory extends Memory { + /** + * The size of pages + */ + private static final int PAGE_SIZE = 4096; + + /** + * Bits in offset + */ + private static final int OFFSET_BITS = 12; + + /** + * The number of pages + */ + private static final int NUM_PAGES = 0x100000; + + /** + * The maximum amount of RAM available + */ + protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES; + + /** + * The memory backing store + */ + private byte readableMemory[][]; + + private byte writableMemory[][]; + + private byte executableMemory[][]; + + /** + * Do we have more optimal nio mmap operation? + */ + private boolean HAVE_java_nio_FileChannelImpl_nio_mmap_file = false; + + /** + * Constructor - used when this is the instatiated class + */ + public DebugMemory() { + readableMemory = new byte[NUM_PAGES][]; + writableMemory = new byte[NUM_PAGES][]; + executableMemory = new byte[NUM_PAGES][]; + } + + /** + * Return the offset part of the address + */ + private static final int getOffset(int address) { + return address & (PAGE_SIZE - 1); + } + + /** + * Return the page table entry part of the address + */ + private static final int getPTE(int address) { + return address >>> OFFSET_BITS; + } + + /** + * Find free consecutive pages + * + * @param pages + * the number of pages required + * @return the address found + */ + private final int findFreePages(int pages) { + starting_page_search: for (int i = 0; i < NUM_PAGES; i++) { + if ((readableMemory[i] == null) && (writableMemory[i] == null) + && (executableMemory[i] == null)) { + int start = i; + int end = i + pages; + for (; i <= end; i++) { + if ((readableMemory[i] != null) || (writableMemory[i] != null) + || (executableMemory[i] != null)) { + continue starting_page_search; + } + } + return start << OFFSET_BITS; + } + } + throw new Error( + "No mappable consecutive pages found for an anonymous map of size" + + (pages * PAGE_SIZE)); + } + + /** + * Map an anonymous page of memory + * + * @param addr + * the address to map or NULL if don't care + * @param len + * the amount of memory to map + * @param read + * is the page readable + * @param write + * is the page writable + * @param exec + * is the page executable + */ + public int map(int addr, int len, boolean read, boolean write, boolean exec) + throws MemoryMapException { + // Check address is page aligned + if ((addr % PAGE_SIZE) != 0) { + MemoryMapException.unalignedAddress(addr); + } + // Create memory + int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; + byte pages[][] = new byte[num_pages][PAGE_SIZE]; + // Find address if not specified + if (addr == 0) { + addr = findFreePages(num_pages); + } + if (DBT_Options.debugMemory) { + System.err.println("Anonymous mapping: addr=0x" + + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -") + + (write ? "w" : "-") + (exec ? "x" : "-")); + } + // Get page table entry + int pte = getPTE(addr); + for (int i = 0; i < num_pages; i++) { + // Check pages aren't already allocated + if ((readableMemory[pte + i] != null) + || (writableMemory[pte + i] != null) + || (executableMemory[pte + i] != null)) { + throw new Error("Memory map of already mapped location addr=0x" + + Integer.toHexString(addr) + " len=" + len); + } + // Allocate pages + if (read) { + readableMemory[pte + i] = pages[i]; + } + if (write) { + writableMemory[pte + i] = pages[i]; + } + if (exec) { + executableMemory[pte + i] = pages[i]; + } + } + return addr; + } + + /** + * Map a page of memory from file + * + * @param file + * the file map in from + * @param addr + * the address to map or NULL if don't care + * @param len + * the amount of memory to map + * @param read + * is the page readable + * @param write + * is the page writable + * @param exec + * is the page executable + */ + public int map(RandomAccessFile file, long offset, int addr, int len, + boolean read, boolean write, boolean exec) throws MemoryMapException { + // Check address is page aligned + if ((addr % PAGE_SIZE) != 0) { + MemoryMapException.unalignedAddress(addr); + } + // Check file offset is page aligned + /* + if ((offset % PAGE_SIZE) != 0) { + MemoryMapException.unalignedFileOffset(offset); + } + */ + + // Calculate number of pages + int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; + // Find address if not specified + if (addr == 0) { + addr = findFreePages(num_pages); + } + if (DBT_Options.debugMemory) { + System.err.println("Mapping file " + file + " offset=" + offset + + " addr=0x" + Integer.toHexString(addr) + " len=" + len + + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-")); + } + try { + // Get page table entry + int pte = getPTE(addr); + // Can we optimise the reads to use mmap? + if (!HAVE_java_nio_FileChannelImpl_nio_mmap_file) { + // Sub-optimal + file.seek(offset); + for (int i = 0; i < num_pages; i++) { + // Check pages aren't already allocated + if ((readableMemory[pte + i] != null) + || (writableMemory[pte + i] != null) + || (executableMemory[pte + i] != null)) { + throw new Error("Memory map of already mapped location addr=0x" + + Integer.toHexString(addr) + " len=" + len); + } + // Allocate page + byte page[] = new byte[PAGE_SIZE]; + if (i == 0) { // first read, start from offset upto a page length + file.read(page, getOffset(addr), PAGE_SIZE - getOffset(addr)); + } else if (i == (num_pages - 1)) { // last read + file.read(page, 0, ((len - getOffset(addr)) % PAGE_SIZE)); + } else { + file.read(page); + } + if (read) { + readableMemory[pte + i] = page; + } + if (write) { + writableMemory[pte + i] = page; + } + if (exec) { + executableMemory[pte + i] = page; + } + } + } else { + for (int i = 0; i < num_pages; i++) { + // Check pages aren't already allocated + if ((readableMemory[pte + i] != null) + || (writableMemory[pte + i] != null) + || (executableMemory[pte + i] != null)) { + throw new Error("Memory map of already mapped location addr=0x" + + Integer.toHexString(addr) + " len=" + len); + } + // Allocate page + if (read && write) { + readableMemory[pte + i] = file.getChannel().map( + FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE), + P... [truncated message content] |
From: <cap...@us...> - 2007-04-18 14:34:19
|
Revision: 68 http://svn.sourceforge.net/pearcolator/?rev=68&view=rev Author: captain5050 Date: 2007-04-18 07:34:18 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Update IA32.rules in Jikes RVM to reflect BooleanCmp changes Modified Paths: -------------- rvmroot.patch Modified: rvmroot.patch =================================================================== --- rvmroot.patch 2007-04-18 14:31:50 UTC (rev 67) +++ rvmroot.patch 2007-04-18 14:34:18 UTC (rev 68) @@ -1,6 +1,6 @@ Index: build.xml =================================================================== ---- build.xml (revision 11998) +--- build.xml (revision 12035) +++ build.xml (working copy) @@ -803,8 +803,8 @@ debugLevel="lines,source" @@ -45,7 +45,7 @@ <!-- * Section for building the boot image * --> Index: rvm/src-generated/opt-ir/InstructionFormatList.dat =================================================================== ---- rvm/src-generated/opt-ir/InstructionFormatList.dat (revision 11995) +--- rvm/src-generated/opt-ir/InstructionFormatList.dat (revision 12035) +++ rvm/src-generated/opt-ir/InstructionFormatList.dat (working copy) @@ -149,6 +149,14 @@ "U Cond OPT_ConditionOperand" "U BranchProfile OPT_BranchProfileOperand" @@ -64,7 +64,7 @@ "D Result OPT_RegisterOperand" "U Val1 OPT_Operand" "U Val2 OPT_Operand" \ Index: rvm/src-generated/opt-ir/OperatorList.dat =================================================================== ---- rvm/src-generated/opt-ir/OperatorList.dat (revision 11995) +--- rvm/src-generated/opt-ir/OperatorList.dat (revision 12035) +++ rvm/src-generated/opt-ir/OperatorList.dat (working copy) @@ -1255,6 +1255,20 @@ @@ -87,9 +87,49 @@ # Load a singed byte # NOTE: Because of our strategy of using explict guard instructions, there is no # way in the HIR/LIR that the actual load instruction can except. +Index: rvm/src-generated/opt-burs/ia32/IA32.rules +=================================================================== +--- rvm/src-generated/opt-burs/ia32/IA32.rules (revision 12035) ++++ rvm/src-generated/opt-burs/ia32/IA32.rules (working copy) +@@ -575,8 +575,9 @@ + boolcmp: BOOLEAN_CMP_INT(r,riv) + 13 + EMIT_INSTRUCTION +-pushCOND(BooleanCmp.getCond(P(p))); \ +-EMIT(MIR_Compare.mutate(P(p), IA32_CMP, BooleanCmp.getVal1(P(p)), BooleanCmp.getVal2(P(p)))); ++OPT_ConditionOperand cond = BooleanCmp.getCond(P(p)); \ ++pushCOND(cond); \ ++EMIT_Compare(P(p), cond, BooleanCmp.getVal1(P(p)), BooleanCmp.getVal2(P(p))); + + r: BOOLEAN_CMP_INT(r,INT_CONSTANT) + VR(p) == 0 && EQ_NE(BooleanCmp.getCond(P(p)))?37:INFINITE +@@ -662,8 +663,9 @@ + boolcmp: BOOLEAN_CMP_INT(load32,riv) + 15 + EMIT_INSTRUCTION +-pushCOND(BooleanCmp.getCond(P(p))); \ +-EMIT(MIR_Compare.mutate(PL(p), IA32_CMP, consumeMO(), BooleanCmp.getVal2(P(p)))); ++OPT_ConditionOperand cond = BooleanCmp.getCond(P(p)); \ ++pushCOND(cond); \ ++EMIT_Compare(P(p), cond, consumeMO(), BooleanCmp.getVal2(P(p))); + + r: BOOLEAN_CMP_INT(r,load32) + 41 +@@ -675,8 +677,9 @@ + boolcmp: BOOLEAN_CMP_INT(r,load32) + 15 + EMIT_INSTRUCTION +-pushCOND(BooleanCmp.getCond(P(p))); \ +-EMIT(MIR_Compare.mutate(PR(p), IA32_CMP, BooleanCmp.getVal1(P(p)), consumeMO())); ++OPT_ConditionOperand cond = BooleanCmp.getCond(P(p)); \ ++pushCOND(cond); \ ++EMIT_Compare(P(p), cond, BooleanCmp.getVal1(P(p)), consumeMO()); + + stm: BYTE_STORE(boolcmp, OTHER_OPERAND(riv,riv)) + 15 Index: rvm/src/OptDummy.java =================================================================== ---- rvm/src/OptDummy.java (revision 11995) +--- rvm/src/OptDummy.java (revision 12035) +++ rvm/src/OptDummy.java (working copy) @@ -20,4 +20,5 @@ static org.jikesrvm.compilers.opt.OPT_Compiler a; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-18 14:31:49
|
Revision: 67 http://svn.sourceforge.net/pearcolator/?rev=67&view=rev Author: captain5050 Date: 2007-04-18 07:31:50 -0700 (Wed, 18 Apr 2007) Log Message: ----------- More support in Jikes RVM for new BooleanCmp and BooleanCmp2 operators Added Paths: ----------- ext/org/jikesrvm/compilers/opt/OPT_ConvertToLowLevelIR.java ext/org/jikesrvm/compilers/opt/ia32/ ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java Added: ext/org/jikesrvm/compilers/opt/OPT_ConvertToLowLevelIR.java =================================================================== --- ext/org/jikesrvm/compilers/opt/OPT_ConvertToLowLevelIR.java (rev 0) +++ ext/org/jikesrvm/compilers/opt/OPT_ConvertToLowLevelIR.java 2007-04-18 14:31:50 UTC (rev 67) @@ -0,0 +1,1258 @@ +/* + * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). + * The Jikes RVM project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright IBM Corp. 2001, 2004 + */ +package org.jikesrvm.compilers.opt; + +import org.jikesrvm.*; +import org.jikesrvm.runtime.VM_Entrypoints; +import org.jikesrvm.runtime.VM_Magic; +import org.jikesrvm.classloader.*; +import org.jikesrvm.compilers.opt.ir.*; +import org.jikesrvm.memorymanagers.mminterface.MM_Constants; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*; +import static org.jikesrvm.compilers.opt.OPT_Constants.*; +import static org.jikesrvm.VM_Constants.*; +import org.vmmagic.unboxed.*; + +/** + * Converts all remaining instructions with HIR-only operators into + * an equivalent sequence of LIR operators. + * + * @author John Whaley + * @author Mauricio J. Serrano + * @author Jong-Deok Choi + * @author Dave Grove + * @author Stephen Fink + * @author Igor Pechtchanski + * @modified Peter F. Sweeney + */ +public abstract class OPT_ConvertToLowLevelIR extends OPT_IRTools { + + /** + * We have slightly different ideas of what the LIR should look like + * for IA32 and PowerPC. The main difference is that for IA32 + * instead of bending over backwards in BURS to rediscover array + * loads, (where we can use base + index*scale addressing modes), + * we'll leave array loads in the LIR. + */ + static final boolean LOWER_ARRAY_ACCESS = VM.BuildForPowerPC; + /** + * Plant virtual calls via the JTOC rather than from the tib of an + * object when possible + */ + static final boolean CALL_VIA_JTOC = false; + /** + * Converts the given HIR to LIR. + * + * @param ir IR to convert + */ + static void convert (OPT_IR ir, OPT_Options options) { + boolean didArrayStoreCheck = false; + for (OPT_Instruction s = ir.firstInstructionInCodeOrder(); + s != null; + s = s.nextInstructionInCodeOrder()) { + + switch (s.getOpcode()) { + case BOOLEAN_CMP2_INT_AND_opcode: + { + OPT_RegisterOperand r1 = ir.regpool.makeTempInt(); + OPT_RegisterOperand r2 = ir.regpool.makeTempInt(); + s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_INT, r1, + BooleanCmp2.getVal1(s), BooleanCmp2.getVal2(s), + BooleanCmp2.getCond1(s), BooleanCmp2.getBranchProfile1(s))); + s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_INT, r2, + BooleanCmp2.getVal3(s), BooleanCmp2.getVal4(s), + BooleanCmp2.getCond2(s), BooleanCmp2.getBranchProfile2(s))); + Binary.mutate(s, INT_AND, BooleanCmp2.getResult(s), r1.copyRO(), r2.copyRO()); + break; + } + case BOOLEAN_CMP2_INT_OR_opcode: + { + OPT_RegisterOperand r1 = ir.regpool.makeTempInt(); + OPT_RegisterOperand r2 = ir.regpool.makeTempInt(); + s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_INT, r1, + BooleanCmp2.getVal1(s), BooleanCmp2.getVal2(s), + BooleanCmp2.getCond1(s), BooleanCmp2.getBranchProfile1(s))); + s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_INT, r2, + BooleanCmp2.getVal3(s), BooleanCmp2.getVal4(s), + BooleanCmp2.getCond2(s), BooleanCmp2.getBranchProfile2(s))); + Binary.mutate(s, INT_OR, BooleanCmp2.getResult(s), r1.copyRO(), r2.copyRO()); + break; + } + case GETSTATIC_opcode: + { + OPT_LocationOperand loc = GetStatic.getClearLocation(s); + OPT_RegisterOperand result = GetStatic.getClearResult(s); + OPT_Operand address = ir.regpool.makeJTOCOp(ir,s); + OPT_Operand offset = GetStatic.getClearOffset(s); + Load.mutate(s, OPT_IRTools.getLoadOp(loc.getFieldRef(), true), + result, address, offset, loc); + } + break; + + case PUTSTATIC_opcode: + { + OPT_LocationOperand loc = PutStatic.getClearLocation(s); + OPT_Operand value = PutStatic.getClearValue(s); + OPT_Operand address = ir.regpool.makeJTOCOp(ir,s); + OPT_Operand offset = PutStatic.getClearOffset(s); + Store.mutate(s, OPT_IRTools.getStoreOp(loc.getFieldRef(), true), + value, address, offset, loc); + } + break; + + case PUTFIELD_opcode: + { + OPT_LocationOperand loc = PutField.getClearLocation(s); + OPT_Operand value = PutField.getClearValue(s); + OPT_Operand address = PutField.getClearRef(s); + OPT_Operand offset = PutField.getClearOffset(s); + Store.mutate(s, OPT_IRTools.getStoreOp(loc.getFieldRef(), false), + value, address, offset, loc, PutField.getClearGuard(s)); + } + break; + + case GETFIELD_opcode: + { + OPT_LocationOperand loc = GetField.getClearLocation(s); + OPT_RegisterOperand result = GetField.getClearResult(s); + OPT_Operand address = GetField.getClearRef(s); + OPT_Operand offset = GetField.getClearOffset(s); + Load.mutate(s, OPT_IRTools.getLoadOp(loc.getFieldRef(), false), + result, address, offset, loc, GetField.getClearGuard(s)); + } + break; + + case INT_ALOAD_opcode: + doArrayLoad(s, ir, INT_LOAD, 2); + break; + + case LONG_ALOAD_opcode: + doArrayLoad(s, ir, LONG_LOAD, 3); + break; + + case FLOAT_ALOAD_opcode: + doArrayLoad(s, ir, FLOAT_LOAD, 2); + break; + + case DOUBLE_ALOAD_opcode: + doArrayLoad(s, ir, DOUBLE_LOAD, 3); + break; + + case REF_ALOAD_opcode: + doArrayLoad(s, ir, REF_LOAD, LOG_BYTES_IN_ADDRESS); + break; + + case BYTE_ALOAD_opcode: + doArrayLoad(s, ir, BYTE_LOAD, 0); + break; + + case UBYTE_ALOAD_opcode: + doArrayLoad(s, ir, UBYTE_LOAD, 0); + break; + + case USHORT_ALOAD_opcode: + doArrayLoad(s, ir, USHORT_LOAD, 1); + break; + + case SHORT_ALOAD_opcode: + doArrayLoad(s, ir, SHORT_LOAD, 1); + break; + + case INT_ASTORE_opcode: + doArrayStore(s, ir, INT_STORE, 2); + break; + + case LONG_ASTORE_opcode: + doArrayStore(s, ir, LONG_STORE, 3); + break; + + case FLOAT_ASTORE_opcode: + doArrayStore(s, ir, FLOAT_STORE, 2); + break; + + case DOUBLE_ASTORE_opcode: + doArrayStore(s, ir, DOUBLE_STORE, 3); + break; + + case REF_ASTORE_opcode: + doArrayStore(s, ir, REF_STORE, LOG_BYTES_IN_ADDRESS); + break; + + case BYTE_ASTORE_opcode: + doArrayStore(s, ir, BYTE_STORE, 0); + break; + + case SHORT_ASTORE_opcode: + doArrayStore(s, ir, SHORT_STORE, 1); + break; + + case CALL_opcode: + s = callHelper(s, ir); + break; + + case SYSCALL_opcode: + // If the SYSCALL is using a symbolic address, convert that to + // a sequence of loads off the BootRecord to find the appropriate field. + if (Call.getMethod(s) != null) { + expandSysCallTarget(s, ir); + } + break; + + case TABLESWITCH_opcode: + s = tableswitch(s, ir); + break; + + case LOOKUPSWITCH_opcode: + s = lookup(s, ir); + break; + + case OBJARRAY_STORE_CHECK_opcode: + s = OPT_DynamicTypeCheckExpansion.arrayStoreCheck(s, ir, true); + didArrayStoreCheck = true; + break; + + case OBJARRAY_STORE_CHECK_NOTNULL_opcode: + s = OPT_DynamicTypeCheckExpansion.arrayStoreCheck(s, ir, false); + didArrayStoreCheck = true; + break; + + case CHECKCAST_opcode: + case CHECKCAST_UNRESOLVED_opcode: + s = OPT_DynamicTypeCheckExpansion.checkcast(s, ir); + break; + + case CHECKCAST_NOTNULL_opcode: + s = OPT_DynamicTypeCheckExpansion.checkcastNotNull(s, ir); + break; + + case MUST_IMPLEMENT_INTERFACE_opcode: + s = OPT_DynamicTypeCheckExpansion.mustImplementInterface(s, ir); + break; + + case IG_CLASS_TEST_opcode: + IfCmp.mutate(s, REF_IFCMP, null, + getTIB(s, ir, + InlineGuard.getClearValue(s), + InlineGuard.getClearGuard(s)), + getTIB(s, ir, InlineGuard.getGoal(s).asType()), + OPT_ConditionOperand.NOT_EQUAL(), + InlineGuard.getClearTarget(s), + InlineGuard.getClearBranchProfile(s)); + break; + + case IG_METHOD_TEST_opcode: + { + OPT_MethodOperand methOp = InlineGuard.getClearGoal(s).asMethod(); + OPT_Operand t1 = + getTIB(s, ir, + InlineGuard.getClearValue(s), + InlineGuard.getClearGuard(s)); + OPT_Operand t2 = + getTIB(s, ir, methOp.getTarget().getDeclaringClass()); + IfCmp.mutate(s, REF_IFCMP, null, + getInstanceMethod(s, ir, t1, methOp.getTarget()), + getInstanceMethod(s, ir, t2, methOp.getTarget()), + OPT_ConditionOperand.NOT_EQUAL(), + InlineGuard.getClearTarget(s), + InlineGuard.getClearBranchProfile(s)); + break; + } + + case INSTANCEOF_opcode: + case INSTANCEOF_UNRESOLVED_opcode: + s = OPT_DynamicTypeCheckExpansion.instanceOf(s, ir); + break; + + case INSTANCEOF_NOTNULL_opcode: + s = OPT_DynamicTypeCheckExpansion.instanceOfNotNull(s, ir); + break; + + case INT_ZERO_CHECK_opcode: + { + TrapIf.mutate(s, TRAP_IF, + ZeroCheck.getClearGuardResult(s), + ZeroCheck.getClearValue(s), IC(0), + OPT_ConditionOperand.EQUAL(), + OPT_TrapCodeOperand.DivByZero()); + } + break; + + case LONG_ZERO_CHECK_opcode: + { + TrapIf.mutate(s, TRAP_IF, + ZeroCheck.getClearGuardResult(s), + ZeroCheck.getClearValue(s), LC(0), + OPT_ConditionOperand.EQUAL(), + OPT_TrapCodeOperand.DivByZero()); + } + break; + + case BOUNDS_CHECK_opcode: + { + // get array_length from array_ref + OPT_RegisterOperand array_length = + InsertGuardedUnary(s, ir, ARRAYLENGTH, VM_TypeReference.Int, + BoundsCheck.getClearRef(s), + BoundsCheck.getClearGuard(s)); + // In UN-signed comparison, a negative index will look like a very + // large positive number, greater than array length. + // Thus length LLT index is false iff 0 <= index <= length + TrapIf.mutate(s, TRAP_IF, + BoundsCheck.getClearGuardResult(s), + array_length.copyD2U(), + BoundsCheck.getClearIndex(s), + OPT_ConditionOperand.LOWER_EQUAL(), + OPT_TrapCodeOperand.ArrayBounds()); + } + break; + + case GET_CLASS_OBJECT_opcode: + { + OPT_Operand TIB = + getTIB(s, ir, (OPT_TypeOperand)Unary.getClearVal(s)); + OPT_RegisterOperand type = ir.regpool.makeTemp(VM_TypeReference.VM_Type); + s.insertBefore(Unary.create(GET_TYPE_FROM_TIB, type, TIB)); + // Get the java.lang.Class object from the VM_Type object + // TODO: Valid location operand? + Load.mutate(s, REF_LOAD, Unary.getClearResult(s), type.copyD2U(), + AC(VM_Entrypoints.classForTypeField.getOffset()), null); + } + break; + + case RESOLVE_MEMBER_opcode: + s = resolveMember(s, ir); + break; + + default: + break; + } + } + // Eliminate possible redundant trap block from array store checks + if(didArrayStoreCheck) { + branchOpts.perform(ir, true); + } + } + + private static OPT_BranchOptimizations branchOpts = new OPT_BranchOptimizations(-1, true, true); + + /** + * Expand a tableswitch. + * @param s the instruction to expand + * @param ir the containing IR + * @return the last OPT_Instruction in the generated LIR sequence. + */ + static OPT_Instruction tableswitch (OPT_Instruction s, OPT_IR ir) { + + + OPT_Instruction s2; + int lowLimit = TableSwitch.getLow(s).value; + int highLimit = TableSwitch.getHigh(s).value; + int number = highLimit - lowLimit + 1; + if (VM.VerifyAssertions) + VM._assert(number > 0); // also checks that there are < 2^31 targets + OPT_Operand val = TableSwitch.getClearValue(s); + OPT_BranchOperand defaultLabel = TableSwitch.getClearDefault(s); + if (number < 8) { // convert into a lookupswitch + OPT_Instruction l = LookupSwitch.create(LOOKUPSWITCH, val, null, + null, defaultLabel, + TableSwitch.getClearDefaultBranchProfile(s), + number*3); + for (int i = 0; i < number; i++) { + LookupSwitch.setMatch(l, i, IC(lowLimit + i)); + LookupSwitch.setTarget(l, i, TableSwitch.getClearTarget(s, i)); + LookupSwitch.setBranchProfile(l, i, + TableSwitch.getClearBranchProfile(s,i)); + } + s.insertFront(l); + return s.remove(); + } + OPT_RegisterOperand reg = val.asRegister(); + OPT_BasicBlock BB1 = s.getBasicBlock(); + OPT_BasicBlock BB2 = BB1.splitNodeAt(s, ir); + OPT_BasicBlock defaultBB = defaultLabel.target.getBasicBlock(); + + /******* First basic block */ + OPT_RegisterOperand t; + if (lowLimit != 0) { + t = InsertBinary(s, ir, INT_ADD, VM_TypeReference.Int, reg, IC(-lowLimit)); + } else { + t = reg.copyU2U(); + } + OPT_BranchProfileOperand defaultProb = TableSwitch.getClearDefaultBranchProfile(s); + s.replace(IfCmp.create(INT_IFCMP, null, t, IC(highLimit - lowLimit), + OPT_ConditionOperand.HIGHER(), + defaultLabel, defaultProb)); + // Reweight branches to account for the default branch going. If + // the default probability was ALWAYS then when we recompute the + // weight to be a proportion of the total number of branches. + final boolean defaultIsAlways = defaultProb.takenProbability >= 1f; + final float weight = defaultIsAlways ? + 1f / number + : 1f / (1f - defaultProb.takenProbability); + + /********** second Basic Block ******/ + s2 = LowTableSwitch.create(LOWTABLESWITCH, t.copyRO(), number*2); + boolean containsDefault = false; + for (int i = 0; i < number; i++) { + OPT_BranchOperand b = TableSwitch.getClearTarget(s, i); + LowTableSwitch.setTarget(s2, i, b); + OPT_BranchProfileOperand bp = TableSwitch.getClearBranchProfile(s,i); + if (defaultIsAlways) + bp.takenProbability = weight; + else + bp.takenProbability *= weight; + LowTableSwitch.setBranchProfile(s2, i, bp); + if (b.target == defaultLabel.target) + containsDefault = true; + } + // Fixup the CFG and code order. + BB1.insertOut(BB2); + BB1.insertOut(defaultBB); + ir.cfg.linkInCodeOrder(BB1, BB2); + if (!containsDefault) + BB2.deleteOut(defaultBB); + // Simplify a fringe case... + // if all targets of the LOWTABLESWITCH are the same, + // then just use a GOTO instead of the LOWTABLESWITCH. + // This actually happens (very occasionally), and is easy to test for. + if (BB2.getNumberOfNormalOut() == 1) { + BB2.appendInstruction(Goto.create(GOTO, + LowTableSwitch.getTarget(s2, 0))); + } else { + BB2.appendInstruction(s2); + } + // continue at next BB + s = BB2.lastInstruction(); + + return s; + } + + /** + * Expand a lookupswitch. + * @param switchInstr The instruction to expand + * @param ir The containing IR + * @return the next {@link OPT_Instruction} after the generated LIR sequence. + */ + static OPT_Instruction lookup (OPT_Instruction switchInstr, OPT_IR ir) { + OPT_Instruction bbend = switchInstr.nextInstructionInCodeOrder(); + OPT_BasicBlock thisBB = bbend.getBasicBlock(); + OPT_BasicBlock nextBB = thisBB.nextBasicBlockInCodeOrder(); + // Blow away the old Normal ControlFlowGraph edges to prepare for new links + thisBB.deleteNormalOut(); + switchInstr.remove(); + OPT_BranchOperand defTarget = LookupSwitch.getClearDefault(switchInstr); + OPT_BasicBlock defaultBB = defTarget.target.getBasicBlock(); + int high = LookupSwitch.getNumberOfTargets(switchInstr) - 1; + if (high < 0) { + // no cases in switch; just jump to defaultBB + thisBB.appendInstruction(Goto.create(GOTO, defTarget)); + thisBB.insertOut(defaultBB); + } else { + OPT_Operand match = LookupSwitch.getValue(switchInstr); + if (match.isConstant()) { + // switch on a constant + int value = match.asIntConstant().value; + int numMatches = LookupSwitch.getNumberOfMatches(switchInstr); + OPT_BranchOperand target = LookupSwitch.getDefault(switchInstr); + for (int i=0; i<numMatches; i++) { + if (value == LookupSwitch.getMatch(switchInstr, i).value) { + target = LookupSwitch.getTarget(switchInstr, i); + break; + } + } + thisBB.appendInstruction(Goto.create(GOTO, target)); + thisBB.insertOut(target.target.getBasicBlock()); + } else { + OPT_RegisterOperand reg = match.asRegister(); + + // If you're not already at the end of the code order + if (nextBB != null) + ir.cfg.breakCodeOrder(thisBB, nextBB); + // generate the binary search tree into thisBB + OPT_BasicBlock lastNewBB = + _lookupswitchHelper(switchInstr, reg, defaultBB, ir, thisBB, 0, + high, Integer.MIN_VALUE, Integer.MAX_VALUE); + if (nextBB != null) + ir.cfg.linkInCodeOrder(lastNewBB, nextBB); + } + } + + // skip all the instrs just inserted by _lookupswitchHelper + if (nextBB != null) + return nextBB.firstInstruction(); + else + return thisBB.lastInstruction(); + } + + /** + * Helper function to generate the binary search tree for + * a lookupswitch bytecode + * + * @param switchInstr the lookupswitch instruction + * @param defaultBB the basic block of the default case + * @param ir the ir object + * @param curBlock the basic block to insert instructions into + * @param reg the RegisterOperand that contains the valued being switched on + * @param low the low index of cases (operands of switchInstr) + * @param high the high index of cases (operands of switchInstr) + * @param min + * @param max + * @return the last basic block created + */ + private static OPT_BasicBlock _lookupswitchHelper(OPT_Instruction switchInstr, + OPT_RegisterOperand reg, + OPT_BasicBlock defaultBB, + OPT_IR ir, + OPT_BasicBlock curBlock, + int low, + int high, + int min, + int max) { + if (VM.VerifyAssertions) + VM._assert(low <= high, "broken control logic in _lookupswitchHelper"); + + int middle = (low + high) >> 1; // find middle + + // The following are used below to store the computed branch + // probabilities for the branches that are created to implement + // the binary search. Used only if basic block frequencies available + float lessProb = 0.0f; + float greaterProb = 0.0f; + float equalProb = 0.0f; + float sum=0.0f; + + // Sum the probabilities for all targets < middle + for (int i=low; i < middle; i++) { + lessProb += LookupSwitch.getBranchProfile(switchInstr,i).takenProbability; + } + + // Sum the probabilities for all targets > middle + for (int i=middle+1; i <= high; i++) { + greaterProb += LookupSwitch.getBranchProfile(switchInstr,i).takenProbability; + } + equalProb = LookupSwitch.getBranchProfile(switchInstr,middle).takenProbability; + + // The default case is a bit of a kludge. We know the total + // probability of executing the default case, but we have no + // idea which paths are taken to get there. For now, we'll + // assume that all paths that went to default were because the + // value was less than the smallest switch value. This ensures + // that all basic block appearing in the switch will have the + // correct weights (but the blocks in the binary switch + // generated may not). + if (low == 0) + lessProb += LookupSwitch.getDefaultBranchProfile(switchInstr).takenProbability; + + // Now normalize them so they are relative to the sum of the + // branches being considered in this piece of the subtree + sum = lessProb + equalProb + greaterProb; + if (sum > 0) { // check for divide by zero + lessProb /= sum; + equalProb /= sum; + greaterProb /= sum; + } + + OPT_IntConstantOperand val = + LookupSwitch.getClearMatch(switchInstr, middle); + int value = val.value; + OPT_BasicBlock greaterBlock = + middle == high ? defaultBB : curBlock.createSubBlock(0, ir); + OPT_BasicBlock lesserBlock = + low == middle ? defaultBB : curBlock.createSubBlock(0, ir); + // Generate this level of tests + OPT_BranchOperand branch = + LookupSwitch.getClearTarget(switchInstr, middle); + OPT_BasicBlock branchBB = branch.target.getBasicBlock(); + curBlock.insertOut(branchBB); + if (low != high) { + if (value == min) { + curBlock.appendInstruction(IfCmp.create(INT_IFCMP, null, + reg.copy(), val, + OPT_ConditionOperand.EQUAL(), + branchBB.makeJumpTarget(), + new OPT_BranchProfileOperand(equalProb))); + } else { + + // To compute the probability of the second compare, the first + // probability must be removed since the second branch is + // considered only if the first fails. + float secondIfProb = 0.0f; + sum = equalProb + greaterProb; + if (sum > 0) // if divide by zero, leave as is + secondIfProb = equalProb/sum; + + curBlock.appendInstruction(IfCmp2.create(INT_IFCMP2, null, + reg.copy(), val, + OPT_ConditionOperand.LESS(), + lesserBlock.makeJumpTarget(), + new OPT_BranchProfileOperand(lessProb), + OPT_ConditionOperand.EQUAL(), + branchBB.makeJumpTarget(), + new OPT_BranchProfileOperand(secondIfProb))); + curBlock.insertOut(lesserBlock); + } + } else { // Base case: middle was the only case left to consider + if (min == max) { + curBlock.appendInstruction(Goto.create(GOTO, branch)); + curBlock.insertOut(branchBB); + } else { + curBlock.appendInstruction(IfCmp.create(INT_IFCMP, null, + reg.copy(), val, + OPT_ConditionOperand.EQUAL(), + branchBB.makeJumpTarget(), + new OPT_BranchProfileOperand(equalProb))); + OPT_BasicBlock newBlock = curBlock.createSubBlock(0, ir); + curBlock.insertOut(newBlock); + ir.cfg.linkInCodeOrder(curBlock, newBlock); + curBlock = newBlock; + curBlock.appendInstruction(defaultBB.makeGOTO()); + curBlock.insertOut(defaultBB); + } + } + // Generate sublevels as needed and splice together instr & bblist + if (middle < high) { + curBlock.insertOut(greaterBlock); + ir.cfg.linkInCodeOrder(curBlock, greaterBlock); + curBlock = _lookupswitchHelper(switchInstr, reg, defaultBB, ir, + greaterBlock, middle + 1, high, + value + 1, max); + } + if (low < middle) { + ir.cfg.linkInCodeOrder(curBlock, lesserBlock); + curBlock = _lookupswitchHelper(switchInstr, reg, defaultBB, ir, + lesserBlock, low, middle - 1, min, + value - 1); + } + return curBlock; + } + + /** + * Expand an array load. + * @param s the instruction to expand + * @param ir the containing IR + * @param op the load operator to use + * @param logwidth the log base 2 of the element type's size + */ + public static void doArrayLoad (OPT_Instruction s, OPT_IR ir, + OPT_Operator op, + int logwidth) { + if (LOWER_ARRAY_ACCESS) { + OPT_RegisterOperand result = ALoad.getClearResult(s); + OPT_Operand array = ALoad.getClearArray(s); + OPT_Operand index = ALoad.getClearIndex(s); + OPT_Operand offset; + OPT_LocationOperand loc = ALoad.getClearLocation(s); + if (index instanceof OPT_IntConstantOperand){ // constant propagation + offset = AC(Address.fromIntZeroExtend(((OPT_IntConstantOperand)index).value << logwidth)); + } else { + if (logwidth != 0) { + offset = InsertBinary(s, ir, INT_SHL, VM_TypeReference.Int, index, IC(logwidth)); + offset = InsertUnary(s, ir, INT_2ADDRZerExt, VM_TypeReference.Offset, offset.copy()); + } else { + offset = InsertUnary(s, ir, INT_2ADDRZerExt, VM_TypeReference.Offset, index); + } + } + Load.mutate(s, op, result, array, offset, loc, ALoad.getClearGuard(s)); + } + } + + /** + * Expand an array store. + * @param s the instruction to expand + * @param ir the containing IR + * @param op the store operator to use + * @param logwidth the log base 2 of the element type's size + */ + public static void doArrayStore (OPT_Instruction s, OPT_IR ir, + OPT_Operator op, + int logwidth) { + if (LOWER_ARRAY_ACCESS) { + OPT_Operand value = AStore.getClearValue(s); + OPT_Operand array = AStore.getClearArray(s); + OPT_Operand index = AStore.getClearIndex(s); + OPT_Operand offset; + OPT_LocationOperand loc = AStore.getClearLocation(s); + if (index instanceof OPT_IntConstantOperand) {// constant propagation + offset = AC(Address.fromIntZeroExtend(((OPT_IntConstantOperand)index).value << logwidth)); + } else { + if (logwidth != 0) { + offset = InsertBinary(s, ir, INT_SHL, VM_TypeReference.Int, index, IC(logwidth)); + offset = InsertUnary(s, ir, INT_2ADDRZerExt, VM_TypeReference.Offset, offset.copy()); + } else { + offset = InsertUnary(s, ir, INT_2ADDRZerExt, VM_TypeReference.Offset, index); + } + } + Store.mutate(s, op, value, array, offset, loc, AStore.getClearGuard(s)); + } + } + + + /** + * Helper method for call expansion. + * @param v the call instruction + * @param ir the containing IR + * @return the last expanded instruction + */ + static OPT_Instruction callHelper(OPT_Instruction v, OPT_IR ir) { + if (!Call.hasMethod(v)) { + if (VM.VerifyAssertions) VM._assert(Call.getAddress(v) instanceof OPT_RegisterOperand); + return v; // nothing to do....very low level call to address already in the register. + } + + OPT_MethodOperand methOp = Call.getMethod(v); + + // Handle recursive invocations. + if (methOp.hasPreciseTarget() && methOp.getTarget() == ir.method) { + Call.setAddress(v, new OPT_BranchOperand(ir.firstInstructionInCodeOrder())); + return v; + } + + /* RRB 100500 */ + // generate direct call to specialized method if the method operand + // has been marked as a specialized call. + if (VM.runningVM) { + OPT_SpecializedMethod spMethod = methOp.spMethod; + if (spMethod != null) { + int smid = spMethod.getSpecializedMethodIndex(); + Call.setAddress(v, getSpecialMethod(v, ir, smid)); + return v; + } + } + + // Used mainly (only?) by OSR + if (methOp.hasDesignatedTarget()) { + Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + methOp.jtocOffset)); + return v; + } + + if (methOp.isStatic()) { + if (VM.VerifyAssertions) VM._assert(Call.hasAddress(v)); + Call.setAddress(v, + InsertLoadOffsetJTOC(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + Call.getClearAddress(v))); + } else if (methOp.isVirtual()) { + if (VM.VerifyAssertions) VM._assert(Call.hasAddress(v)); + if (CALL_VIA_JTOC && methOp.hasPreciseTarget()) { + // Call to precise type can go via JTOC + VM_Method target = methOp.getTarget(); + Call.setAddress(v, + InsertLoadOffsetJTOC(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + target.findOrCreateJtocOffset() + )); + } + else { + OPT_Operand tib = getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy()); + Call.setAddress(v, InsertLoadOffset(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + tib, Call.getClearAddress(v), null, TG())); + } + } else if (methOp.isSpecial()) { + VM_Method target = methOp.getTarget(); + if (target == null || target.isObjectInitializer() || target.isStatic()) { + // target == null => we are calling an unresolved <init> method. + Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + Call.getClearAddress(v))); + } else { + if (CALL_VIA_JTOC) { + Call.setAddress(v, + InsertLoadOffsetJTOC(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + target.findOrCreateJtocOffset() + )); + } + else { + // invoking a virtual method; do it via TIB of target's declaring class. + OPT_Operand tib = getTIB(v, ir, target.getDeclaringClass()); + Call.setAddress(v, InsertLoadOffset(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + tib, Call.getClearAddress(v), null, TG())); + } + } + } else { + if (VM.VerifyAssertions) VM._assert(methOp.isInterface()); + if (VM.VerifyAssertions) VM._assert(!Call.hasAddress(v)); + if (VM.BuildForIMTInterfaceInvocation) { + // SEE ALSO: OPT_FinalMIRExpansion (for hidden parameter) + OPT_Operand RHStib = + getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy()); + VM_InterfaceMethodSignature sig = VM_InterfaceMethodSignature.findOrCreate(methOp.getMemberRef()); + Offset offset = sig.getIMTOffset(); + OPT_RegisterOperand address = null; + if (VM.BuildForEmbeddedIMT) { + address = InsertLoadOffset(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + RHStib.copy(), + offset); + } else { + OPT_RegisterOperand IMT = InsertLoadOffset(v, ir, REF_LOAD, + VM_TypeReference.JavaLangObjectArray, + RHStib.copy(), + Offset.fromIntZeroExtend(TIB_IMT_TIB_INDEX << LOG_BYTES_IN_ADDRESS)); + address = InsertLoadOffset(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + IMT.copyD2U(), + offset); + + } + Call.setAddress(v, address); + } else if (VM.BuildForITableInterfaceInvocation && + VM.DirectlyIndexedITables && + methOp.hasTarget() && + methOp.getTarget().getDeclaringClass().isResolved()) { + VM_Class I = methOp.getTarget().getDeclaringClass(); + OPT_Operand RHStib = + getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy()); + OPT_RegisterOperand iTables = + InsertLoadOffset(v, ir, REF_LOAD, + VM_TypeReference.JavaLangObjectArray, + RHStib.copy(), + Offset.fromIntZeroExtend(TIB_ITABLES_TIB_INDEX << LOG_BYTES_IN_ADDRESS)); + OPT_RegisterOperand iTable = + InsertLoadOffset(v, ir, REF_LOAD, + VM_TypeReference.JavaLangObjectArray, + iTables.copyD2U(), + Offset.fromIntZeroExtend(I.getInterfaceId()<<LOG_BYTES_IN_ADDRESS)); + OPT_RegisterOperand address = + InsertLoadOffset(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + iTable.copyD2U(), + Offset.fromIntZeroExtend(VM_InterfaceInvocation.getITableIndex(I, + methOp.getMemberRef().getName(), + methOp.getMemberRef().getDescriptor())<<LOG_BYTES_IN_ADDRESS)); + Call.setAddress(v, address); + } else { + int itableIndex = -1; + if (VM.BuildForITableInterfaceInvocation && methOp.hasTarget()) { + VM_Class I = methOp.getTarget().getDeclaringClass(); + // search ITable variant + itableIndex = VM_InterfaceInvocation.getITableIndex(I, + methOp.getMemberRef().getName(), + methOp.getMemberRef().getDescriptor()); + } + if (itableIndex == -1) { + // itable index is not known at compile-time. + // call "invokeinterface" to resolve the object and method id + // into a method address + OPT_RegisterOperand realAddrReg = + ir.regpool.makeTemp(VM_TypeReference.CodeArray); + VM_Method target = VM_Entrypoints.invokeInterfaceMethod; + OPT_Instruction vp = + Call.create2(CALL, realAddrReg, AC(target.getOffset()), + OPT_MethodOperand.STATIC(target), + Call.getParam(v, 0).asRegister().copyU2U(), + IC(methOp.getMemberRef().getId())); + vp.position = v.position; + vp.bcIndex = RUNTIME_SERVICES_BCI; + v.insertBack(vp); + callHelper(vp, ir); + Call.setAddress(v, realAddrReg.copyD2U()); + return v; + } else { + // itable index is known at compile-time. + // call "findITable" to resolve object + interface id into + // itable address + OPT_RegisterOperand iTable = + ir.regpool.makeTemp(VM_TypeReference.JavaLangObjectArray); + OPT_Operand RHStib = + getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy()); + VM_Method target = VM_Entrypoints.findItableMethod; + OPT_Instruction fi = + Call.create2(CALL, iTable, AC(target.getOffset()), + OPT_MethodOperand.STATIC(target), + RHStib, IC(methOp.getTarget().getDeclaringClass().getInterfaceId())); + fi.position = v.position; + fi.bcIndex = RUNTIME_SERVICES_BCI; + v.insertBack(fi); + callHelper(fi, ir); + OPT_RegisterOperand address = + InsertLoadOffset(v, ir, REF_LOAD, + VM_TypeReference.CodeArray, + iTable.copyD2U(), Offset.fromIntZeroExtend(itableIndex<<LOG_BYTES_IN_ADDRESS)); + Call.setAddress(v, address); + return v; + } + } + } + return v; + } + + /** + * Generate the code to resolve a member (field/method) reference. + * @param s the RESOLVE_MEMBER instruction to expand + * @param ir the containing ir object + * @return the last expanded instruction + */ + private static OPT_Instruction resolveMember(OPT_Instruction s, OPT_IR ir) { + OPT_Operand memberOp = Unary.getClearVal(s); + OPT_RegisterOperand offset = Unary.getClearResult(s); + int dictId; + if (memberOp instanceof OPT_LocationOperand) { + dictId = ((OPT_LocationOperand)memberOp).getFieldRef().getId(); + } else { + dictId = ((OPT_MethodOperand)memberOp).getMemberRef().getId(); + } + + + OPT_BranchProfileOperand bp = OPT_BranchProfileOperand.never(); + OPT_BasicBlock predBB = s.getBasicBlock(); + OPT_BasicBlock succBB = predBB.splitNodeAt(s.getPrev(), ir); + OPT_BasicBlock testBB = predBB.createSubBlock(s.bcIndex, ir, 1f - bp.takenProbability); + OPT_BasicBlock resolveBB = predBB.createSubBlock(s.bcIndex, ir, bp.takenProbability); + s.remove(); + + // Get the offset from the appropriate VM_ClassLoader array + // and check to see if it is valid + OPT_RegisterOperand offsetTable = + getStatic(testBB.lastInstruction(), ir, VM_Entrypoints.memberOffsetsField); + testBB.appendInstruction(Load.create(INT_LOAD, offset.copyRO(), offsetTable, + AC(Offset.fromIntZeroExtend(dictId << LOG_BYTES_IN_INT)), + new OPT_LocationOperand(VM_TypeReference.Int), + TG())); + testBB.appendInstruction(Unary.create(INT_2ADDRSigExt, offset, offset.copy())); + testBB.appendInstruction(IfCmp.create(REF_IFCMP, null, + offset.copy(), + AC(Address.fromIntSignExtend(NEEDS_DYNAMIC_LINK)), + OPT_ConditionOperand.EQUAL(), + resolveBB.makeJumpTarget(), + bp)); + + // Handle the offset being invalid + resolveBB.appendInstruction(CacheOp.mutate(s, RESOLVE, memberOp)); + resolveBB.appendInstruction(testBB.makeGOTO()); + + // Put together the CFG links & code order + predBB.insertOut(testBB); + ir.cfg.linkInCodeOrder(predBB, testBB); + testBB.insertOut(succBB); + testBB.insertOut(resolveBB); + ir.cfg.linkInCodeOrder(testBB, succBB); + resolveBB.insertOut(testBB); // backedge + ir.cfg.addLastInCodeOrder(resolveBB); // stick resolution code in outer space. + return testBB.lastInstruction(); + } + + + /** + * Insert a binary instruction before s in the instruction stream. + * @param s the instruction to insert before + * @param ir the containing IR + * @param operator the operator to insert + * @param type the type of the result + * @param o1 the first operand + * @param o2 the second operand + * @return the result operand of the inserted instruction + */ + public static OPT_RegisterOperand InsertBinary (OPT_Instruction s, OPT_IR ir, + OPT_Operator operator, + VM_TypeReference type, + OPT_Operand o1, + OPT_Operand o2) { + OPT_RegisterOperand t = ir.regpool.makeTemp(type); + s.insertBack(Binary.create(operator, t, o1, o2)); + return t.copyD2U(); + } + + /** + * Insert a unary instruction before s in the instruction stream. + * @param s the instruction to insert before + * @param ir the containing IR + * @param operator the operator to insert + * @param type the type of the result + * @param o1 the operand + * @return the result operand of the inserted instruction + */ + static OPT_RegisterOperand InsertUnary (OPT_Instruction s, OPT_IR ir, + OPT_Operator operator, + VM_TypeReference type, + OPT_Operand o1) { + OPT_RegisterOperand t = ir.regpool.makeTemp(type); + s.insertBack(Unary.create(operator, t, o1)); + return t.copyD2U(); + } + + /** + * Insert a guarded unary instruction before s in the instruction stream. + * @param s the instruction to insert before + * @param ir the containing IR + * @param operator the operator to insert + * @param type the type of the result + * @param o1 the operand + * @param guard the guard operand + * @return the result operand of the inserted instruction + */ + static OPT_RegisterOperand InsertGuardedUnary (OPT_Instruction s, OPT_IR ir, + OPT_Operator operator, + VM_TypeReference type, + OPT_Operand o1, + OPT_Operand guard) { + OPT_RegisterOperand t = ir.regpool.makeTemp(type); + s.insertBack(GuardedUnary.create(operator, t, o1, guard)); + return t.copyD2U(); + } + + /** + * Insert a load off the JTOC before s in the instruction stream. + * @param s the instruction to insert before + * @param ir the containing IR + * @param operator the operator to insert + * @param type the type of the result + * @param offset the offset to load at + * @return the result operand of the inserted instruction + */ + static OPT_RegisterOperand InsertLoadOffsetJTOC (OPT_Instruction s, + OPT_IR ir, + OPT_Operator operator, + VM_TypeReference type, + Offset offset) { + return InsertLoadOffset(s, ir, operator, type, ir.regpool.makeJTOCOp(ir,s), + AC(offset), new OPT_LocationOperand(offset), null); + } + + /** + * Insert a load off the JTOC before s in the instruction stream. + * @param s the instruction to insert before + * @param ir the containing IR + * @param operator the operator to insert + * @param type the type of the result + * @param offset the offset to load at + * @return the result operand of the inserted instruction + */ + static OPT_RegisterOperand InsertLoadOffsetJTOC (OPT_Instruction s, + OPT_IR ir, + OPT_Operator operator, + VM_TypeReference type, + OPT_Operand offset) { + return InsertLoadOffset(s, ir, operator, type, ir.regpool.makeJTOCOp(ir,s), + offset, null, null); + } + + /** + * Insert a load off before s in the instruction stream. + * @param s the instruction to insert before + * @param ir the containing IR + * @param operator the operator to insert + * @param type the type of the result + * @param reg2 the base to load from + * @param offset the offset to load at + * @return the result operand of the inserted instruction + */ + static OPT_RegisterOperand InsertLoadOffset (OPT_Instruction s, OPT_IR ir, + OPT_Operator operator, + VM_TypeReference type, + OPT_Operand reg2, + Offset offset) { + return InsertLoadOffset(s, ir, operator, type, reg2, offset, null, null); + } + + /** + * Insert a load off before s in the instruction stream. + * @param s the instruction to insert before + * @param ir the containing IR + * @param operator the operator to insert + * @param type the type of the result + * @param reg2 the base to load from + * @param offset the offset to load at + * @param guard the guard operand + * @return the result operand of the inserted instruction + */ + static OPT_RegisterOperand InsertLoadOffset (OPT_Instruction s, OPT_IR ir, + OPT_Operator operator, + VM_TypeReference type, + OPT_Operand reg2, + Offset offset, + OPT_Operand guard) { + return InsertLoadOffset(s, ir, operator, type, reg2, offset, null, guard); + } + + /** + * Insert a load off before s in the instruction stream. + * @param s the instruction to insert before + * @param ir the containing IR + * @param operator the operator to insert + * @param type the type of the result + * @param reg2 the base to load from + * @param offset the offset to load at + * @param loc the location operand + * @param guard the guard operand + * @return the result operand of the inserted instruction + */ + static OPT_RegisterOperand InsertLoadOffset (OPT_Instruction s, OPT_IR ir, + OPT_Operator operator, + VM_TypeReference type, + OPT_Operand reg2, + Offset offset, + OPT_LocationOperand loc, + OPT_Operand guard) { + return InsertLoadOffset(s, ir, operator, type, reg2, AC(offset), loc, guard); + } + + /** + * Insert a load off before s in the instruction stream. + * @param s the instruction to insert before + * @param ir the containing IR + * @param operator the operator to insert + * @param type the type of the result + * @param reg2 the base to load from + * @param offset the offset to load at + * @param loc the location operand + * @param guard the guard operand + * @return the result operand of the inserted instruction + */ + static OPT_RegisterOperand InsertLoadOffset (OPT_Instruction s, OPT_IR ir, + OPT_Operator operator, + VM_TypeReference type, + OPT_Operand reg2, + OPT_Operand offset, + OPT_LocationOperand loc, + OPT_Operand guard) { + OPT_RegisterOperand regTarget = ir.regpool.makeTemp(type); + OPT_Instruction s2 = Load.create(operator, regTarget, reg2, offset, + loc, guard); + s.insertBack(s2); + return regTarget.copyD2U(); + } + + /** get the tib from the object pointer to by obj */ + static OPT_Operand getTIB (OPT_Instruction s, OPT_IR ir, + OPT_Operand obj, + OPT_Operand guard) { + if (obj.isObjectConstant()) { + // NB Constant types must already be resolved + try { + VM_Type type = obj.getType().resolve(); + return new OPT_TIBConstantOperand(type); + } catch(NoClassDefFoundError e) { + if (VM.runningVM) throw e; + // Class not found during bootstrap due to chasing a class + // only valid in the bootstrap JVM + } + } + OPT_RegisterOperand res = + ir.regpool.makeTemp(VM_TypeReference.JavaLangObjectArray); + OPT_Instruction s2 = GuardedUnary.create(GET_OBJ_TIB, res, obj, guard); + s.insertBack(s2); + return res.copyD2U(); + } + + /** get the class tib for type */ + static OPT_Operand getTIB (OPT_Instruction s, OPT_IR ir, VM_Type type) { + return new OPT_TIBConstantOperand(type); + //return getTIB(s, ir, new OPT_TypeOperand(type)); + } + + /** get the class tib for type */ + static OPT_Operand getTIB (OPT_Instruction s, OPT_IR ir, + OPT_TypeOperand type) { + VM_Type t = type.getVMType(); + if (VM.BuildForIA32 && !MM_Constants.MOVES_TIBS && + VM.runningVM && t != null && t.isResolved()) { + Address addr = VM_Magic.objectAsAddress(t.getTypeInformationBlock()); + return new OPT_AddressConstantOperand(addr); + } else if (!t.isResolved()) { + OPT_RegisterOperand res = + ir.regpool.makeTemp(VM_TypeReference.JavaLangObjectArray); + s.insertBack(Unary.create(GET_CLASS_TIB, res, type)); + return res.copyD2U(); + } else { + return new OPT_TIBConstantOperand(t); + } + } + + /** + * Get an instance method from a TIB + */ + static OPT_RegisterOperand getInstanceMethod (OPT_Instruction s, OPT_IR ir, + OPT_Operand tib, + VM_Method method) { + return InsertLoadOffset(s, ir, REF_LOAD, + VM_TypeReference.CodeArray, + tib, method.getOffset()); + } + + /** + * Load an instance field. + * @param s + * @param ir + * @param obj + * @param field + */ + public static OPT_RegisterOperand getField (OPT_Instruction s, OPT_IR ir, + OPT_RegisterOperand obj, + VM_Field field) { + return getField(s, ir, obj, field, null); + } + + /** + * Load an instance field. + * @param s + * @param ir + * @param obj + * @param field + * @param guard + */ + static OPT_RegisterOperand getField (OPT_Instruction s, OPT_IR ir, + OPT_RegisterOperand obj, + VM_Field field, OPT_Operand guard) { + return InsertLoadOffset(s, ir, OPT_IRTools.getLoadOp(field.getType(), + field.isStatic()), + field.getType(), obj, field.getOffset(), + new OPT_LocationOperand(field), guard); + } + + /* RRB 100500 */ + /** + * support for direct call to specialized method. + */ + static OPT_RegisterOperand getSpecialMethod (OPT_Instruction s, OPT_IR ir, + int smid) { + // First, get the pointer to the JTOC offset pointing to the + // specialized Method table + OPT_RegisterOperand reg = + InsertLoadOffsetJTOC(s, ir, REF_LOAD, + VM_TypeReference.JavaLangObjectArray, + VM_Entrypoints.specializedMethodsField.getOffset()); + OPT_RegisterOperand instr = + InsertLoadOffset(s, ir, REF_LOAD, + VM_TypeReference.CodeArray, + reg, Offset.fromIntZeroExtend(smid << LOG_BYTES_IN_INT)); + return instr; + } + + /** + * Expand symbolic SysCall target into a chain of loads from the bootrecord to + * the desired target address. + */ + public static void expandSysCallTarget(OPT_Instruction s, OPT_IR ir) { + OPT_MethodOperand sysM = Call.getMethod(s); + OPT_RegisterOperand t1 = getStatic(s, ir, VM_Entrypoints.the_boot_recordField); + VM_Field target = sysM.getMemberRef().asFieldReference().resolve(); + OPT_Operand ip = getField(s, ir, t1, target); + Call.setAddress(s, ip); + } + + + /** + * Load a static field. + * @param s + * @param ir + * @param field + */ + public static OPT_RegisterOperand getStatic (OPT_Instruction s, OPT_IR ir, + VM_Field field) { + return InsertLoadOffsetJTOC(s, ir, + OPT_IRTools.getLoadOp(field.getType(), + field.isStatic()), + field.getType(), field.getOffset()); + } +} Added: ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java =================================================================== --- ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java (rev 0) +++ ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java 2007-04-18 14:31:50 UTC (rev 67) @@ -0,0 +1,2340 @@ +/* + * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). + * The Jikes RVM project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright IBM Corp. 2001 + */ +package org.jikesrvm.compilers.opt.ia32; + +import org.jikesrvm.VM; +import org.jikesrvm.runtime.VM_Entrypoints; +import org.jikesrvm.runtime.VM_Magic; +import org.jikesrvm.runtime.VM_Runtime; +import org.jikesrvm.classloader.*; +import org.jikesrvm.compilers.opt.ir.ia32.*; +import org.jikesrvm.compilers.opt.OPT_BURS; +import org.jikesrvm.compilers.opt.OPT_BURS_MemOp_Helpers; +import org.jikesrvm.compilers.opt.OPT_DefUse; +import org.jikesrvm.compilers.opt.OPT_OptimizingCompilerException; +import org.jikesrvm.compilers.opt.ir.Binary; +import org.jikesrvm.compilers.opt.ir.BinaryAcc; +import org.jikesrvm.compilers.opt.ir.CacheOp; +import org.jikesrvm.compilers.opt.ir.Call; +import org.jikesrvm.compilers.opt.ir.CondMove; +import org.jikesrvm.compilers.opt.ir.GuardedBinary; +import org.jikesrvm.compilers.opt.ir.IfCmp; +import org.jikesrvm.compilers.opt.ir.LowTableSwitch; +import org.jikesrvm.compilers.opt.ir.MIR_BinaryAcc; +import org.jikesrvm.compilers.opt.ir.MIR_Call; +import org.jikesrvm.compilers.opt.ir.MIR_Compare; +import org.jikesrvm.compilers.opt.ir.MIR_CompareExchange; +import org.jikesrvm.compilers.opt.ir.MIR_CondBranch; +import org.jikesrvm.compilers.opt.ir.MIR_CondMove; +import org.jikesrvm.compilers.opt.ir.MIR_ConvertDW2QW; +import org.jikesrvm.compilers.opt.ir.MIR_Divide; +import org.jikesrvm.compilers.opt.ir.MIR_DoubleShift; +import org.jikesrvm.compilers.opt.ir.MIR_LowTableSwitch; +import org.jikesrvm.compilers.opt.ir.MIR_Move; +import org.jikesrvm.compilers.opt.ir.MIR_Multiply; +import org.jikesrvm.compilers.opt.ir.MIR_Nullary; +import org.jikesrvm.compilers.opt.ir.MIR_RDTSC; +import org.jikesrvm.compilers.opt.ir.MIR_Set; +import org.jikesrvm.compilers.opt.ir.MIR_Test; +import org.jikesrvm.compilers.opt.ir.MIR_TrapIf; +import org.jikesrvm.compilers.opt.ir.MIR_Unary; +import org.jikesrvm.compilers.opt.ir.MIR_UnaryAcc; +import org.jikesrvm.compilers.opt.ir.MIR_UnaryNoRes; +import org.jikesrvm.compilers.opt.ir.Move; +import org.jikesrvm.compilers.opt.ir.Nullary; +import org.jikesrvm.compilers.opt.ir.OPT_BranchOperand; +import org.jikesrvm.compilers.opt.ir.OPT_BranchProfileOperand; +import org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand; +import org.jikesrvm.compilers.opt.ir.OPT_ConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_DoubleConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_FloatConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_InlinedOsrTypeInfoOperand; +import org.jikesrvm.compilers.opt.ir.OPT_Instruction; +import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_LocationOperand; +import org.jikesrvm.compilers.opt.ir.OPT_LongConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_MemoryOperand; +import org.jikesrvm.compilers.opt.ir.OPT_MethodOperand; +import org.jikesrvm.compilers.opt.ir.OPT_Operand; +import org.jikesrvm.compilers.opt.ir.OPT_Operator; +import org.jikesrvm.compilers.opt.ir.OPT_Register; +import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperandEnumeration; +import org.jikesrvm.compilers.opt.ir.OPT_StackLocationOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TrapCodeOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TrueGuardOperand; +import org.jikesrvm.compilers.opt.ir.OsrPoint; +import org.jikesrvm.compilers.opt.ir.Prologue; +import org.jikesrvm.compilers.opt.ir.TrapIf; +import org.jikesrvm.compilers.opt.ir.Unary; + +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*; +import org.vmmagic.unboxed.Offset; + +/** + * Contains IA32-specific helper functions for BURS. + * + * @author Dave Grove + * @author Stephen Fink + * @author Ian Rogers + */ +abstract class OPT_BURS_Helpers extends OPT_BURS_MemOp_Helpers { + /** Constant log10(2), supported as an x87 constant */ + private static final double LG2 = Double + .parseDouble("0.3010299956639811952256464283594894482"); + + /** Constant ln(2), supported as an x87 constant */ + private static final double LN2 = Double + .parseDouble("0.6931471805599453094286904741849753009"); + + /** Constant log2(e), supported as an x87 constant */ + private static final double L2E = Double + .parseDouble("1.4426950408889634073876517827983434472"); + + /** Constant log2(10), supported as an x87 constant */ + private static final double L2T = Double + .parseDouble("3.3219280948873623478083405569094566090"); + + /** + * When emitting certain rules this holds the condition code state to be + * consumed by a parent rule + */ + private OPT_ConditionOperand cc; + + /** Constructor */ + OPT_BURS_Helpers(OPT_BURS burs) { + super(burs); + } + + /** + * Follow a chain of Move operations filtering back to a def + * + * @param use the place to start from + * @return the operand at the start of the chain + */ + protected static OPT_Operand follow(OPT_Operand use) { + if (!use.isRegister()) { + return use; + } else { + OPT_RegisterOperand rop = use.asRegister(); + OPT_RegisterOperandEnumeration defs = OPT_DefUse.defs(rop.register); + if (!defs.hasMoreElements()) { + return use; + } else { + OPT_Operand def = defs.next(); + if (defs.hasMoreElements()) { + return def; + } else { + OPT_Instruction instr = def.instruction; + if (Move.conforms(instr)) { + return follow(Move.getVal(instr)); + } else if (MIR_Move.conforms(instr)) { + return follow(MIR_Move.getValue(instr)); + } else { + return def; + } + }... [truncated message content] |
From: <cap...@us...> - 2007-04-18 14:27:26
|
Revision: 66 http://svn.sourceforge.net/pearcolator/?rev=66&view=rev Author: captain5050 Date: 2007-04-18 07:27:27 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Support for overflow from multiply Modified Paths: -------------- ext/org/jikesrvm/compilers/opt/ir/OPT_ConditionOperand.java ext/org/jikesrvm/compilers/opt/ir/ia32/OPT_IA32ConditionOperand.java Modified: ext/org/jikesrvm/compilers/opt/ir/OPT_ConditionOperand.java =================================================================== --- ext/org/jikesrvm/compilers/opt/ir/OPT_ConditionOperand.java 2007-04-18 14:26:40 UTC (rev 65) +++ ext/org/jikesrvm/compilers/opt/ir/OPT_ConditionOperand.java 2007-04-18 14:27:27 UTC (rev 66) @@ -109,6 +109,11 @@ /** Would is bit a not set in b? */ public static final int NO_RBIT_TEST = 35; + /** Would a*b cause an overflow? */ + public static final int OVERFLOW_FROM_MUL = 36; + /** Would a*b not cause an overflow? */ + public static final int NO_OVERFLOW_FROM_MUL = 37; + /* Results from evaluations */ /** Evaluation result is false */ public static final int FALSE = 0; @@ -310,6 +315,15 @@ } /** + * Create the condition code operand for OVERFLOW_FROM_ADD + * + * @return a newly created condition code operand + */ + public static OPT_ConditionOperand OVERFLOW_FROM_MUL() { + return new OPT_ConditionOperand(OVERFLOW_FROM_MUL); + } + + /** * Is x higher (unsigned >) than y? */ private static boolean higher(int x, int y) { @@ -373,6 +387,15 @@ } /** + * Would x*y overflow a register? + */ + private static boolean overflow_from_mul(int x, int y) { + int z = x * y; + long z2 = ((long)x) * ((long)y); + return (long)z != z2; + } + + /** * Would is bit y of x set? */ private static boolean bit_test(int x, int y) { @@ -507,6 +530,8 @@ case NO_BIT_TEST: case RBIT_TEST: case NO_RBIT_TEST: + case OVERFLOW_FROM_MUL: + case NO_OVERFLOW_FROM_MUL: return true; default: return false; @@ -845,6 +870,8 @@ case NO_BIT_TEST: case RBIT_TEST: case NO_RBIT_TEST: + case OVERFLOW_FROM_MUL: + case NO_OVERFLOW_FROM_MUL: return UNKNOWN; default: throw new OPT_OptimizingCompilerException("invalid condition " + this); @@ -891,6 +918,8 @@ case NO_BIT_TEST: return bit_test(v1, v2) ? FALSE : TRUE; case RBIT_TEST: return bit_test(v2, v1) ? TRUE : FALSE; case NO_RBIT_TEST: return bit_test(v2, v1) ? FALSE : TRUE; + case OVERFLOW_FROM_MUL: return overflow_from_mul(v1, v2) ? TRUE : FALSE; + case NO_OVERFLOW_FROM_MUL: return overflow_from_mul(v1, v2) ? FALSE : TRUE; } throw new OPT_OptimizingCompilerException("invalid condition " + this); } @@ -1055,6 +1084,10 @@ case NO_BIT_TEST: value = BIT_TEST; break; case RBIT_TEST: value = NO_RBIT_TEST; break; case NO_RBIT_TEST: value = RBIT_TEST; break; + + case OVERFLOW_FROM_MUL: value = NO_OVERFLOW_FROM_MUL; break; + case NO_OVERFLOW_FROM_MUL: value = OVERFLOW_FROM_MUL; break; + default: OPT_OptimizingCompilerException.UNREACHABLE(); } @@ -1118,6 +1151,10 @@ case NO_BIT_TEST: value = NO_RBIT_TEST; break; case RBIT_TEST: value = BIT_TEST; break; case NO_RBIT_TEST: value = NO_BIT_TEST; break; + + case OVERFLOW_FROM_MUL: break; // mul is commutative + case NO_OVERFLOW_FROM_MUL: break; + default: OPT_OptimizingCompilerException.UNREACHABLE(); } @@ -1183,6 +1220,9 @@ case RBIT_TEST: return "rbt"; case NO_RBIT_TEST: return "!rbt"; + case OVERFLOW_FROM_MUL: return "overflow(*)"; + case NO_OVERFLOW_FROM_MUL: return "nooverflow(*)"; + default: return "UNKNOWN"; } } Modified: ext/org/jikesrvm/compilers/opt/ir/ia32/OPT_IA32ConditionOperand.java =================================================================== --- ext/org/jikesrvm/compilers/opt/ir/ia32/OPT_IA32ConditionOperand.java 2007-04-18 14:26:40 UTC (rev 65) +++ ext/org/jikesrvm/compilers/opt/ir/ia32/OPT_IA32ConditionOperand.java 2007-04-18 14:27:27 UTC (rev 66) @@ -171,14 +171,36 @@ value = LGT; break; case OPT_ConditionOperand.LOWER: + case OPT_ConditionOperand.CARRY_FROM_ADD: + case OPT_ConditionOperand.BORROW_FROM_SUB: + case OPT_ConditionOperand.BORROW_FROM_RSUB: + case OPT_ConditionOperand.BIT_TEST: + case OPT_ConditionOperand.RBIT_TEST: value = LLT; break; case OPT_ConditionOperand.HIGHER_EQUAL: + case OPT_ConditionOperand.NO_CARRY_FROM_ADD: + case OPT_ConditionOperand.NO_BORROW_FROM_SUB: + case OPT_ConditionOperand.NO_BORROW_FROM_RSUB: + case OPT_ConditionOperand.NO_BIT_TEST: + case OPT_ConditionOperand.NO_RBIT_TEST: value = LGE; break; case OPT_ConditionOperand.LOWER_EQUAL: value = LLE; break; + case OPT_ConditionOperand.OVERFLOW_FROM_ADD: + case OPT_ConditionOperand.OVERFLOW_FROM_SUB: + case OPT_ConditionOperand.OVERFLOW_FROM_RSUB: + case OPT_ConditionOperand.OVERFLOW_FROM_MUL: + value = O; + break; + case OPT_ConditionOperand.NO_OVERFLOW_FROM_ADD: + case OPT_ConditionOperand.NO_OVERFLOW_FROM_SUB: + case OPT_ConditionOperand.NO_OVERFLOW_FROM_RSUB: + case OPT_ConditionOperand.NO_OVERFLOW_FROM_MUL: + value = NO; + break; case OPT_ConditionOperand.CMPL_EQUAL: case OPT_ConditionOperand.CMPL_GREATER: case OPT_ConditionOperand.CMPG_LESS: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-18 14:26:41
|
Revision: 65 http://svn.sourceforge.net/pearcolator/?rev=65&view=rev Author: captain5050 Date: 2007-04-18 07:26:40 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Segmentation fault exception and a little more debugging Modified Paths: -------------- src/org/binarytranslator/generic/fault/BadInstructionException.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Added Paths: ----------- src/org/binarytranslator/generic/fault/SegmentationFault.java Modified: src/org/binarytranslator/generic/fault/BadInstructionException.java =================================================================== --- src/org/binarytranslator/generic/fault/BadInstructionException.java 2007-04-18 14:25:47 UTC (rev 64) +++ src/org/binarytranslator/generic/fault/BadInstructionException.java 2007-04-18 14:26:40 UTC (rev 65) @@ -10,7 +10,7 @@ import org.binarytranslator.generic.os.process.ProcessSpace; -public class BadInstructionException extends Exception { +public class BadInstructionException extends RuntimeException { private final int pc; private final ProcessSpace ps; Added: src/org/binarytranslator/generic/fault/SegmentationFault.java =================================================================== --- src/org/binarytranslator/generic/fault/SegmentationFault.java (rev 0) +++ src/org/binarytranslator/generic/fault/SegmentationFault.java 2007-04-18 14:26:40 UTC (rev 65) @@ -0,0 +1,23 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2007 + */ +package org.binarytranslator.generic.fault; + +/** + * @author Ian Rogers + */ +public class SegmentationFault extends RuntimeException { + private final int address; + /** + * Constructor + */ + public SegmentationFault(int address) { + super("SegFault at 0x"+Integer.toHexString(address)); + this.address = address; + } +} Modified: src/org/binarytranslator/generic/memory/ByteAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-04-18 14:25:47 UTC (rev 64) +++ src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-04-18 14:26:40 UTC (rev 65) @@ -11,6 +11,7 @@ import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import org.binarytranslator.DBT_Options; +import org.binarytranslator.generic.fault.SegmentationFault; /** * ByteAddressedMemory: @@ -436,8 +437,12 @@ * @return the result */ public int load32(int addr) { - return (loadSigned8(addr + 3) << 24) | (loadUnsigned8(addr + 2) << 16) - | (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr); + try { + return (loadSigned8(addr + 3) << 24) | (loadUnsigned8(addr + 2) << 16) + | (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr); + } catch (Exception e) { + throw new SegmentationFault(addr); + } } /** Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-18 14:25:47 UTC (rev 64) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-04-18 14:26:40 UTC (rev 65) @@ -159,6 +159,7 @@ */ public void doSysCall() { int sysCallNumber = src.getSysCallNumber(); + System.err.println("Syscall "+ sysCallToString(sysCallNumber)); systemCallTable[sysCallNumber].doSysCall(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-18 14:25:46
|
Revision: 64 http://svn.sourceforge.net/pearcolator/?rev=64&view=rev Author: captain5050 Date: 2007-04-18 07:25:47 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Fix white space Modified Paths: -------------- src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java 2007-04-18 14:24:41 UTC (rev 63) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxStackInitializer.java 2007-04-18 14:25:47 UTC (rev 64) @@ -15,12 +15,10 @@ import org.binarytranslator.generic.memory.MemoryMapException; /** - * This class captures the common parts of stack initialization for a - * process. - * - * From the System V ABI specification shows the initial process stack - * varies across architectures, but in general it should look like: - * + * This class captures the common parts of stack initialization for a process. + * From the System V ABI specification shows the initial process stack varies + * across architectures, but in general it should look like: + * * <pre> * ----------- High address * Unspecified @@ -52,351 +50,374 @@ * ----------- * Argument count * ----------- Low address - *</pre> + * </pre> */ public class LinuxStackInitializer { /* - * ABI constants - */ + * ABI constants + */ /** - * Class capturing auxiliary vector types - */ + * Class capturing auxiliary vector types + */ public final static class AuxiliaryVectorType { - /** - * The auxiliary vector has no fixed length; instead an entry of - * this type denotes the end of the vector. The corresponding - * value of a_un is undefined. - */ - public final static int AT_NULL=0; - /** - * This type indicates the entry has no meaning. The corresponding - * value of a_un is undefined. - */ - public final static int AT_IGNORE=1; - /** - * As Chapter 5 in the System V ABI describes, exec(BA_OS) may - * pass control to an interpreter program. When this happens, the - * system places either an entry of type AT_EXECFD or one of type - * AT_PHDR in the auxiliary vector. The entry for type AT_EXECFD - * uses the a_val member to contain a file descriptor open to read - * the application program’s object file. - */ - public final static int AT_EXECFD=2; - /** - * Under some conditions, the system creates the memory image of - * the application program before passing control to an - * interpreter program. When this happens, the a_ptr member of the - * AT_PHDR entry tells the interpreter where to find the program - * header table in the memory image. If the AT_PHDR entry is - * present, entries of types AT_PHENT, AT_PHNUM, and AT_ENTRY must - * also be present. See the section Program Header in Chapter 5 of - * the System V ABI and the section Program Loading in Chapter 5 - * of this processor supplement for more information about the - * program header table. - */ - public final static int AT_PHDR=3; - /** - * The a_val member of this entry holds the size, in bytes, of one - * entry in the program header table to which the AT_PHDR entry - * points. - */ - public final static int AT_PHENT=4; - /** - * The a_val member of this entry holds the size, in bytes, of one - * entry in the program header table to which the AT_PHDR entry - * points. - */ - public final static int AT_PHNUM=5; - /** - * If present, this entry’s a_val member gives the system page - * size in bytes. The same information is also available through - * sysconf(BA_OS). - */ - public final static int AT_PAGESZ=6; - /** - * The a_ptr member of this entry holds the base address at which - * the interpreter program was loaded into memory. See the section - * Program Header in Chapter 5 of the System V ABI for more - * information about the base address. - */ - public final static int AT_BASE=7; - /** - * If present, the a_val member of this entry holds 1-bit - * flags. Bits with undefined semantics are set to zero. - */ - public final static int AT_FLAGS=8; - /** - * The a_ptr member of this entry holds the entry point of the - * application program to which the interpreter program should - * transfer control. - */ - public final static int AT_ENTRY=9; - /** - * The a_val member of this entry is non-zero if the dynamic - * linker should examine LD_LIBRARY_PATH when searching for shared - * objects of the process based on the security considerations in - * the Shared Object Dependency section in Chapter 5 of the gABI. - * Defined in the i386 System V ABI spec. - */ - public final static int AT_LIBPATH=10; - /** - * Program is not an ELF. This conflicting definition for type 10 - * occurs in elf.h - */ - public final static int AT_NOTELF=10; - /** - * The a_val member of this entry will be set to: - * 0, if no floating point support exists; - * 1, if floating point software emulation exists; - * 3, if it has an 80287 chip; - * 4, if it has an 80387 or 80487 chip. - * Defined in the i386 System V ABI spec. - */ - public final static int AT_FPHW=11; - /** - * Real UID. Defined in elf.h - */ - public final static int AT_UID=11; - /** - * The a_val member of this entry holds the device number of the - * file from which the dynamic linker is loaded. - * Defined in the i386 System V ABI spec. - */ - public final static int AT_INTP_DEVICE=12; - /** - * Effective UID. Defined in elf.h - */ - public final static int AT_EUID=12; - /** - * The a_val member of this entry holds the inode of the file from - * which the dynamic linker is loaded. - * Defined in the i386 System V ABI spec. - */ - public final static int AT_INTP_INODE=12; - /** - * Real gid. Defined in elf.h - */ - public final static int AT_GID=13; - /** - * Effective gid. Defined in elf.h - */ - public final static int AT_EGID=14; - /** - * String identifying CPU for optimizations - */ - public final static int AT_PLATFORM=15; - /** - * Arch dependent hints at CPU capabilities - */ - public final static int AT_HWCAP=16; - /** - * Frequency at which times() increments - */ - public final static int AT_CLKTCK=17; - /** - * The a_val member of this entry gives the data cache block size - * for processors on the system on which this program is - * running. If the processors have unified caches, AT_DCACHEBSIZE - * is the same as AT_UCACHEBSIZE - */ - public final static int AT_DCACHEBSIZE=19; - /** - * The a_val member of this entyr gives the instruction cache - * block size for processors on the system on which this program - * is running. If the processors have unified caches, - * AT_DCACHEBSIZE is the same as AT_UCACHEBSIZE. - */ - public final static int AT_ICACHEBSIZE=20; - /** - * The a_val member of this entry is zero if the processors on the - * system on which this program is running do not have a unified - * instruction and data cache. Otherwise it gives the cache block - * size. - */ - public final static int AT_UCACHEBSIZE=21; - /** - * All entries of this type should be ignored. - */ - public final static int AT_IGNOREPPC=22; - /** - * Boolean, was exec setuid-like? - */ - public final static int AT_SECURE=23; - /** - * X86 Specific: The sysinfo page is a shared page in the kernel, - * aka Virtual Dynamically Shared Object (VDSO), this is the entry - * point into that page - */ - public final static int AT_SYSINFO=32; - /** - * X86 Specific: The sysinfo page is a shared page in the kernel, - * aka Virtual Dynamically Shared Object (VDSO), this is the ELF - * header for that page - */ - public final static int AT_SYSINFO_EHDR=33; + /** + * The auxiliary vector has no fixed length; instead an entry of this type + * denotes the end of the vector. The corresponding value of a_un is + * undefined. + */ + public final static int AT_NULL = 0; + + /** + * This type indicates the entry has no meaning. The corresponding value of + * a_un is undefined. + */ + public final static int AT_IGNORE = 1; + + /** + * As Chapter 5 in the System V ABI describes, exec(BA_OS) may pass control + * to an interpreter program. When this happens, the system places either an + * entry of type AT_EXECFD or one of type AT_PHDR in the auxiliary vector. + * The entry for type AT_EXECFD uses the a_val member to contain a file + * descriptor open to read the application program’s object file. + */ + public final static int AT_EXECFD = 2; + + /** + * Under some conditions, the system creates the memory image of the + * application program before passing control to an interpreter program. + * When this happens, the a_ptr member of the AT_PHDR entry tells the + * interpreter where to find the program header table in the memory image. + * If the AT_PHDR entry is present, entries of types AT_PHENT, AT_PHNUM, and + * AT_ENTRY must also be present. See the section Program Header in Chapter + * 5 of the System V ABI and the section Program Loading in Chapter 5 of + * this processor supplement for more information about the program header + * table. + */ + public final static int AT_PHDR = 3; + + /** + * The a_val member of this entry holds the size, in bytes, of one entry in + * the program header table to which the AT_PHDR entry points. + */ + public final static int AT_PHENT = 4; + + /** + * The a_val member of this entry holds the size, in bytes, of one entry in + * the program header table to which the AT_PHDR entry points. + */ + public final static int AT_PHNUM = 5; + + /** + * If present, this entry’s a_val member gives the system page size in + * bytes. The same information is also available through sysconf(BA_OS). + */ + public final static int AT_PAGESZ = 6; + + /** + * The a_ptr member of this entry holds the base address at which the + * interpreter program was loaded into memory. See the section Program + * Header in Chapter 5 of the System V ABI for more information about the + * base address. + */ + public final static int AT_BASE = 7; + + /** + * If present, the a_val member of this entry holds 1-bit flags. Bits with + * undefined semantics are set to zero. + */ + public final static int AT_FLAGS = 8; + + /** + * The a_ptr member of this entry holds the entry point of the application + * program to which the interpreter program should transfer control. + */ + public final static int AT_ENTRY = 9; + + /** + * The a_val member of this entry is non-zero if the dynamic linker should + * examine LD_LIBRARY_PATH when searching for shared objects of the process + * based on the security considerations in the Shared Object Dependency + * section in Chapter 5 of the gABI. Defined in the i386 System V ABI spec. + */ + public final static int AT_LIBPATH = 10; + + /** + * Program is not an ELF. This conflicting definition for type 10 occurs in + * elf.h + */ + public final static int AT_NOTELF = 10; + + /** + * The a_val member of this entry will be set to: 0, if no floating point + * support exists; 1, if floating point software emulation exists; 3, if it + * has an 80287 chip; 4, if it has an 80387 or 80487 chip. Defined in the + * i386 System V ABI spec. + */ + public final static int AT_FPHW = 11; + + /** + * Real UID. Defined in elf.h + */ + public final static int AT_UID = 11; + + /** + * The a_val member of this entry holds the device number of the file from + * which the dynamic linker is loaded. Defined in the i386 System V ABI + * spec. + */ + public final static int AT_INTP_DEVICE = 12; + + /** + * Effective UID. Defined in elf.h + */ + public final static int AT_EUID = 12; + + /** + * The a_val member of this entry holds the inode of the file from which the + * dynamic linker is loaded. Defined in the i386 System V ABI spec. + */ + public final static int AT_INTP_INODE = 12; + + /** + * Real gid. Defined in elf.h + */ + public final static int AT_GID = 13; + + /** + * Effective gid. Defined in elf.h + */ + public final static int AT_EGID = 14; + + /** + * String identifying CPU for optimizations + */ + public final static int AT_PLATFORM = 15; + + /** + * Arch dependent hints at CPU capabilities + */ + public final static int AT_HWCAP = 16; + + /** + * Frequency at which times() increments + */ + public final static int AT_CLKTCK = 17; + + /** + * The a_val member of this entry gives the data cache block size for + * processors on the system on which this program is running. If the + * processors have unified caches, AT_DCACHEBSIZE is the same as + * AT_UCACHEBSIZE + */ + public final static int AT_DCACHEBSIZE = 19; + + /** + * The a_val member of this entyr gives the instruction cache block size for + * processors on the system on which this program is running. If the + * processors have unified caches, AT_DCACHEBSIZE is the same as + * AT_UCACHEBSIZE. + */ + public final static int AT_ICACHEBSIZE = 20; + + /** + * The a_val member of this entry is zero if the processors on the system on + * which this program is running do not have a unified instruction and data + * cache. Otherwise it gives the cache block size. + */ + public final static int AT_UCACHEBSIZE = 21; + + /** + * All entries of this type should be ignored. + */ + public final static int AT_IGNOREPPC = 22; + + /** + * Boolean, was exec setuid-like? + */ + public final static int AT_SECURE = 23; + + /** + * X86 Specific: The sysinfo page is a shared page in the kernel, aka + * Virtual Dynamically Shared Object (VDSO), this is the entry point into + * that page + */ + public final static int AT_SYSINFO = 32; + + /** + * X86 Specific: The sysinfo page is a shared page in the kernel, aka + * Virtual Dynamically Shared Object (VDSO), this is the ELF header for that + * page + */ + public final static int AT_SYSINFO_EHDR = 33; } - /** - * Set up the process stack to: - * <pre> - * ----------- stackTop - * 0 word - * ----------- stackTop - 4 - * Information block, including argument strings, environment strings, - * auxiliary information - * ... - * (size varies) - * ----------- infoBlockStart - * Null auxiliary vector entry - * ----------- - * Auxiliary vector - * ... - * (2-word entries) - * ----------- - * 0 word - * ----------- - * Environment pointers - * ... - * (one word each) - * ----------- - * 0 word - * ----------- - * Argument pointers - * ... - * (Argument count words) - * ----------- - * Argument count - * ----------- Low address - *</pre> - * @param argv the command line arguments of the PPC binary (starting with its name, C style). - * @param env the environment variables. - * @param the auxiliary vector, including the terminating AT_NULL (two zeroes). - * @return the bottom of the stack in memory - */ - public static int stackInit(Memory memory, int stackTop, String[] env, int[] auxVector) { - - //grab the vector of command line options that are to be delivered to the linux program + /** + * Set up the process stack to: + * + * <pre> + * ----------- stackTop + * 0 word + * ----------- stackTop - 4 + * Information block, including argument strings, environment strings, + * auxiliary information + * ... + * (size varies) + * ----------- infoBlockStart + * Null auxiliary vector entry + * ----------- + * Auxiliary vector + * ... + * (2-word entries) + * ----------- + * 0 word + * ----------- + * Environment pointers + * ... + * (one word each) + * ----------- + * 0 word + * ----------- + * Argument pointers + * ... + * (Argument count words) + * ----------- + * Argument count + * ----------- Low address + * </pre> + * + * @param argv the command line arguments of the PPC binary (starting with its + * name, C style). + * @param env the environment variables. + * @param the auxiliary vector, including the terminating AT_NULL (two + * zeroes). + * @return the bottom of the stack in memory + */ + public static int stackInit(Memory memory, int stackTop, String[] env, + int[] auxVector) { + + // grab the vector of command line options that are to be delivered to the + // linux program String[] argv = DBT_Options.executableArguments; - - // --- - // First create the information block by concatenating all strings - // together, then compute pointers to values in the information - // block to be held lower down the initial stack - // --- - // The infoBlock as a byte array - byte[] infoBlockBytes; - // Starting address for the infoBlock - int infoBlockStart; - { - StringBuffer infoBlock = new StringBuffer(); - for(int a = 0 ; a < argv.length ; a++) { - infoBlock.append(argv[a]); - infoBlock.append('\0'); // NB Java Strings are not null terminated. - } - for(int e = 0 ; e < env.length ; e++) { - infoBlock.append(env[e]); - infoBlock.append('\0'); - } - // Add up to 3bytes of padding to word align - switch(infoBlock.length() % 4) { - case 1: infoBlock.append('\0'); - case 2: infoBlock.append('\0'); - case 3: infoBlock.append('\0'); - default: - } - try { - infoBlockBytes = infoBlock.toString().getBytes("US-ASCII"); - } - catch(UnsupportedEncodingException e) { - // Failing to encode the info block into bytes is a fatal error - throw new Error("Failed to convert infoBlock into US-ASCII bytes", e); - } - infoBlockStart = stackTop - 4 - infoBlock.length(); - } - // Array to hold pointers to arguments and environment variables - int[] argPtr = new int[argv.length]; - int[] envPtr = new int[env.length]; - // Compute pointer values into the infoBlock for arguments and - // environment variables - { - int ptr = infoBlockStart; - for(int i = 0 ; i < argv.length ; i++) { - argPtr[i] = ptr+1; - ptr += argv[i].length() + 1; - } - for(int i = 0 ; i < env.length ; i++) { - envPtr[i] = ptr+1; - ptr += env[i].length() + 1; - } - } - // --- - // Create the pages of memory for the stack - // --- - { - // how big the initial stack will be - int initialStackSize = - 4 + // 0 word + - infoBlockBytes.length + // information block size + - (auxVector.length * 4)+ // 1 word per auxiliary vector item + - 4 + // 0 word + - (env.length * 4) + // 1 pointer per environment variable + - 4 + // 0 word + - (argv.length * 4) + // 1 pointer per argument + - 4; // argc - - // Round this up to a page - initialStackSize = memory.truncateToNextPage(initialStackSize); - - try { - memory.map(stackTop - initialStackSize - 8192, initialStackSize + 8192, - true, true, false); // read/write/no execute - } - catch(MemoryMapException e) { - // Failing to create the stack is a fatal error - throw new Error("Failed to create stack", e); - } - } - // --- - // Place the values into memory - // --- - int stackPtr = stackTop; - { - // 0 word - stackPtr -= 4; - memory.store32(stackPtr, 0); - // information block - for(int i = 0 ; i < infoBlockBytes.length ; i++) { - stackPtr --; - memory.store8(stackPtr, infoBlockBytes[i]); - } - // auxiliary vector - for(int i = (auxVector.length-1); i >= 0 ; i--) { - stackPtr -= 4; - memory.store32(stackPtr, auxVector[i]); - } - // 0 word - stackPtr -= 4; - memory.store32(stackPtr, 0); - // environment variables - for(int i = (envPtr.length-1); i >= 0 ; i--) { - stackPtr -= 4; - memory.store32(stackPtr, envPtr[i]); - } - // 0 word - stackPtr -= 4; - memory.store32(stackPtr, 0); - // arguments - for(int i = (argPtr.length-1); i >= 0 ; i--) { - stackPtr -= 4; - memory.store32(stackPtr, argPtr[i]); - } - // argc - stackPtr -= 4; - memory.store32(stackPtr, argPtr.length); - } - return stackPtr; + // --- + // First create the information block by concatenating all strings + // together, then compute pointers to values in the information + // block to be held lower down the initial stack + // --- + // The infoBlock as a byte array + byte[] infoBlockBytes; + // Starting address for the infoBlock + int infoBlockStart; + { + StringBuffer infoBlock = new StringBuffer(); + + for (int a = 0; a < argv.length; a++) { + infoBlock.append(argv[a]); + infoBlock.append('\0'); // NB Java Strings are not null terminated. + } + for (int e = 0; e < env.length; e++) { + infoBlock.append(env[e]); + infoBlock.append('\0'); + } + // Add up to 3bytes of padding to word align + switch (infoBlock.length() & 3) { + case 1: + infoBlock.append('\0'); + case 2: + infoBlock.append('\0'); + case 3: + infoBlock.append('\0'); + default: + } + try { + infoBlockBytes = infoBlock.toString().getBytes("US-ASCII"); + } catch (UnsupportedEncodingException e) { + // Failing to encode the info block into bytes is a fatal error + throw new Error("Failed to convert infoBlock into US-ASCII bytes", e); + } + infoBlockStart = stackTop - 4 - infoBlock.length(); + } + // Array to hold pointers to arguments and environment variables + int[] argPtr = new int[argv.length]; + int[] envPtr = new int[env.length]; + // Compute pointer values into the infoBlock for arguments and + // environment variables + { + int ptr = infoBlockStart; + for (int i = 0; i < argv.length; i++) { + argPtr[i] = ptr + 1; + ptr += argv[i].length() + 1; + } + for (int i = 0; i < env.length; i++) { + envPtr[i] = ptr + 1; + ptr += env[i].length() + 1; + } + } + // --- + // Create the pages of memory for the stack + // --- + { + // how big the initial stack will be + int initialStackSize = 4 + // 0 word + + infoBlockBytes.length + // information block size + + (auxVector.length * 4) + // 1 word per auxiliary vector item + + 4 + // 0 word + + (env.length * 4) + // 1 pointer per environment variable + + 4 + // 0 word + + (argv.length * 4) + // 1 pointer per argument + + 4; // argc + + // Round this up to a page + initialStackSize = memory.truncateToNextPage(initialStackSize); + + try { + memory.map(stackTop - initialStackSize - 8192, initialStackSize + 8192, + true, true, false); // read/write/no execute + } catch (MemoryMapException e) { + // Failing to create the stack is a fatal error + throw new Error("Failed to create stack", e); + } + } + // --- + // Place the values into memory + // --- + int stackPtr = stackTop; + { + // 0 word + stackPtr -= 4; + memory.store32(stackPtr, 0); + // information block + for (int i = 0; i < infoBlockBytes.length; i++) { + stackPtr--; + memory.store8(stackPtr, infoBlockBytes[i]); + } + // auxiliary vector + for (int i = (auxVector.length - 1); i >= 0; i--) { + stackPtr -= 4; + memory.store32(stackPtr, auxVector[i]); + } + // 0 word + stackPtr -= 4; + memory.store32(stackPtr, 0); + // environment variables + for (int i = (envPtr.length - 1); i >= 0; i--) { + stackPtr -= 4; + memory.store32(stackPtr, envPtr[i]); + } + // 0 word + stackPtr -= 4; + memory.store32(stackPtr, 0); + // arguments + for (int i = (argPtr.length - 1); i >= 0; i--) { + stackPtr -= 4; + memory.store32(stackPtr, argPtr[i]); + } + // argc + stackPtr -= 4; + memory.store32(stackPtr, argPtr.length); + } + return stackPtr; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-18 14:24:40
|
Revision: 63 http://svn.sourceforge.net/pearcolator/?rev=63&view=rev Author: captain5050 Date: 2007-04-18 07:24:41 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Support for div and imul Modified Paths: -------------- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-18 14:24:25 UTC (rev 62) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-18 14:24:41 UTC (rev 63) @@ -95,13 +95,8 @@ /* 0x02 */new X86_Add_OpcodeDecoder(8, true, 0, false),// 8bit, has // ModRM, no imm, // rm is src - /* 0x03 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src + /* 0x03 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false), + // 16/32bit, has ModRM, no imm, rm is src /* 0x04 */new X86_Add_OpcodeDecoder(8, false, 8, false),// 8bit, no ModRM, // 8bit imm /* 0x05 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 @@ -637,19 +632,14 @@ /* 0xF4 */null, /* 0xF5 */null, /* 0xF6 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 8bit, - // ModRM, - // 8bit - // imm, - // rm - // is - // dest + // ModRM, 8bit imm, rm is dest new X86_Test_OpcodeDecoder(8, true, 8), // 0 null, // 1 new X86_Not_OpcodeDecoder(8), // 2 - 8bit new X86_Neg_OpcodeDecoder(8), // 3 - 8bit - new X86_Mul_OpcodeDecoder(8), // 3 - 8bit + new X86_Mul_OpcodeDecoder(8), // 4 - 8bit null, // 5 - null, // 6 + new X86_Div_OpcodeDecoder(8), // 6 - 8bit null // 7 }), /* 0xF7 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 16/32bit, @@ -666,7 +656,7 @@ new X86_Neg_OpcodeDecoder(_16BIT ? 16 : 32), // 3 - 16/32bit new X86_Mul_OpcodeDecoder(_16BIT ? 16 : 32), // 4 - 16/32bit null, // 5 - null, // 6 + new X86_Div_OpcodeDecoder(_16BIT ? 16 : 32), // 6 - 16/32bit null // 7 }), /* 0xF8 */null, @@ -764,12 +754,9 @@ */ public static int translateInstruction(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc) { - System.err.println("Translating "+pc); X86_InstructionDecoder decoder = getDecoder(ps, pc); if (DBT_Options.debugInstr) { - System.err.println("Disassembling "+pc); System.err.println(decoder.disassemble(ps, pc)); - System.err.println("After disassembling "+pc); } return decoder.translate(translationHelper, ps, lazy, pc); } @@ -2073,7 +2060,8 @@ /* 0xAC */null, /* 0xAD */null, /* 0xAE */null, - /* 0xAF */null, + /* 0xAF */new X86_Imul_OpcodeDecoder(_16BIT ? 16 : 32, 0, false), + // 16/32bit, no imm, not edx:eax /* 0xB0 */null, /* 0xB1 */null, @@ -2081,87 +2069,84 @@ /* 0xB3 */null, /* 0xB4 */null, /* 0xB5 */null, - /* 0xB6 */new X86_MovZX_OpcodeDecoder(_16BIT ? 16 : 32, 8), // dest 16/32bit, - // src 8bit - /* 0xB7 */new X86_MovZX_OpcodeDecoder(32, 16), // dest 32bit, src 16bit - /* 0xB8 */null, - /* 0xB9 */null, - /* 0xBA */null, - /* 0xBB */null, - /* 0xBC */null, - /* 0xBD */null, - /* 0xBE */new X86_MovSX_OpcodeDecoder(_16BIT ? 16 : 32, 8), // dest - // 16/32bit, - // src 8bit - /* 0xBF */new X86_MovSX_OpcodeDecoder(32, 16), // dest 32bit, src 16bit + /* 0xB6 */new X86_MovZX_OpcodeDecoder(_16BIT ? 16 : 32, 8), // dest 16/32bit, src 8bit + /* 0xB7 */new X86_MovZX_OpcodeDecoder(32, 16), // dest 32bit, src 16bit + /* 0xB8 */null, + /* 0xB9 */null, + /* 0xBA */null, + /* 0xBB */null, + /* 0xBC */null, + /* 0xBD */null, + /* 0xBE */new X86_MovSX_OpcodeDecoder(_16BIT ? 16 : 32, 8), // dest 16/32bit, src 8bit + /* 0xBF */new X86_MovSX_OpcodeDecoder(32, 16), // dest 32bit, src 16bit - /* 0xC0 */null, - /* 0xC1 */null, - /* 0xC2 */null, - /* 0xC3 */null, - /* 0xC4 */null, - /* 0xC5 */null, - /* 0xC6 */null, - /* 0xC7 */null, - /* 0xC8 */null, - /* 0xC9 */null, - /* 0xCA */null, - /* 0xCB */null, - /* 0xCC */null, - /* 0xCD */null, - /* 0xCE */null, - /* 0xCF */null, + /* 0xC0 */null, + /* 0xC1 */null, + /* 0xC2 */null, + /* 0xC3 */null, + /* 0xC4 */null, + /* 0xC5 */null, + /* 0xC6 */null, + /* 0xC7 */null, + /* 0xC8 */null, + /* 0xC9 */null, + /* 0xCA */null, + /* 0xCB */null, + /* 0xCC */null, + /* 0xCD */null, + /* 0xCE */null, + /* 0xCF */null, - /* 0xD0 */null, - /* 0xD1 */null, - /* 0xD2 */null, - /* 0xD3 */null, - /* 0xD4 */null, - /* 0xD5 */null, - /* 0xD6 */null, - /* 0xD7 */null, - /* 0xD8 */null, - /* 0xD9 */null, - /* 0xDA */null, - /* 0xDB */null, - /* 0xDC */null, - /* 0xDD */null, - /* 0xDE */null, - /* 0xDF */null, + /* 0xD0 */null, + /* 0xD1 */null, + /* 0xD2 */null, + /* 0xD3 */null, + /* 0xD4 */null, + /* 0xD5 */null, + /* 0xD6 */null, + /* 0xD7 */null, + /* 0xD8 */null, + /* 0xD9 */null, + /* 0xDA */null, + /* 0xDB */null, + /* 0xDC */null, + /* 0xDD */null, + /* 0xDE */null, + /* 0xDF */null, - /* 0xE0 */null, - /* 0xE1 */null, - /* 0xE2 */null, - /* 0xE3 */null, - /* 0xE4 */null, - /* 0xE5 */null, - /* 0xE6 */null, - /* 0xE7 */null, - /* 0xE8 */null, - /* 0xE9 */null, - /* 0xEA */null, - /* 0xEB */null, - /* 0xEC */null, - /* 0xED */null, - /* 0xEE */null, - /* 0xEF */null, + /* 0xE0 */null, + /* 0xE1 */null, + /* 0xE2 */null, + /* 0xE3 */null, + /* 0xE4 */null, + /* 0xE5 */null, + /* 0xE6 */null, + /* 0xE7 */null, + /* 0xE8 */null, + /* 0xE9 */null, + /* 0xEA */null, + /* 0xEB */null, + /* 0xEC */null, + /* 0xED */null, + /* 0xEE */null, + /* 0xEF */null, - /* 0xF0 */null, - /* 0xF1 */null, - /* 0xF2 */null, - /* 0xF3 */null, - /* 0xF4 */null, - /* 0xF5 */null, - /* 0xF6 */null, - /* 0xF7 */null, - /* 0xF8 */null, - /* 0xF9 */null, - /* 0xFA */null, - /* 0xFB */null, - /* 0xFC */null, - /* 0xFD */null, - /* 0xFE */null, - /* 0xFF */null }; + /* 0xF0 */null, + /* 0xF1 */null, + /* 0xF2 */null, + /* 0xF3 */null, + /* 0xF4 */null, + /* 0xF5 */null, + /* 0xF6 */null, + /* 0xF7 */null, + /* 0xF8 */null, + /* 0xF9 */null, + /* 0xFA */null, + /* 0xFB */null, + /* 0xFC */null, + /* 0xFD */null, + /* 0xFE */null, + /* 0xFF */null }; /** * Utility to get a decoder for a particular opcode @@ -3510,6 +3495,15 @@ rhsOp1 = translationHelper.getOverflowFlag(); condOp1 = OPT_ConditionOperand.EQUAL(); break; + case GREATER: + operator = BOOLEAN_CMP2_INT_AND; + lhsOp1 = translationHelper.getZeroFlag(); + rhsOp1 = new OPT_IntConstantOperand(0); + condOp1 = OPT_ConditionOperand.EQUAL(); + lhsOp2 = translationHelper.getSignFlag(); + rhsOp2 = translationHelper.getOverflowFlag(); + condOp2 = OPT_ConditionOperand.EQUAL(); + break; default: TODO(); } @@ -5362,6 +5356,9 @@ } else { addressSize = _16BIT ? 32 : 16; } + if (operandSize != 32) { + TODO(); + } // longs to perform the mul in OPT_RegisterOperand tempLong1 = translationHelper.getTempLong(0); OPT_RegisterOperand tempLong2 = translationHelper.getTempLong(1); @@ -5438,6 +5435,275 @@ } /** + * The decoder for the Imul opcode. This opcode has 3 forms: + * EDX:EAX is the destination, + * reg is the destination with either reg/mem/immediate as a source, + * or reg is the destination with either reg/mem as a source and an immediate + * as the second source. + */ +class X86_Imul_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Is EDX:EAX implicitly the destination of this instruction + */ + final boolean isAccumulatorDestination; + /** + * Constructor, {@see X86_OpcodeDecoder} + */ + X86_Imul_OpcodeDecoder(int size, int immediateSize, boolean isAccumulatorDestination) { + super(size, true, immediateSize, false); + this.isAccumulatorDestination = isAccumulatorDestination; + } + + /** + * Perform the actual translation + * @param translationHelper + * @param ps + * @param lazy + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected int translate(X862IR translationHelper, ProcessSpace ps, + X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, + int displacement, int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int operandSize; + if (prefix3 == null) { + operandSize = this.operandSize; + } else { + switch (this.operandSize) { + case 32: + operandSize = 16; + break; + case 16: + operandSize = 32; + break; + default: + operandSize = -1; + DBT_OptimizingCompilerException.UNREACHABLE(); + } + } + int addressSize; + if (prefix4 == null) { + addressSize = _16BIT ? 16 : 32; + } else { + addressSize = _16BIT ? 32 : 16; + } + + X86_DecodedOperand destination = null; + X86_DecodedOperand source1, source2 = null; + + source1 = modrm.getRM(translationHelper, lazy, sib, displacement, + operandSize, addressSize, + (prefix2 != null) ? prefix2.getSegment() : X86_Registers.DS); + + if (!isAccumulatorDestination) { + destination = modrm.getReg(operandSize); + if (immediateSize > 0) { + // dest = source1 * imm + source2 = X86_DecodedOperand.getImmediate(immediate); + } else { + // dest = dest * source1; + source2 = destination; + } + } + + if (operandSize != 32) { + TODO(); + } + + OPT_RegisterOperand sourceOp1 = translationHelper.getTempInt(1); + source1.readToRegister(translationHelper, lazy, sourceOp1); + if (isAccumulatorDestination) { + // 64bit by 32bit multiply result to go in edx:eax + OPT_RegisterOperand longSourceOp1 = translationHelper.getTempLong(1); + translationHelper.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, + longSourceOp1, sourceOp1.copyRO())); + TODO(); + } else { + OPT_RegisterOperand sourceOp2 = translationHelper.getTempInt(2); + source2.readToRegister(translationHelper, lazy, sourceOp2); + OPT_RegisterOperand temp = translationHelper.getTempInt(3); + translationHelper.appendInstructionToCurrentBlock(Binary.create(INT_MUL, + temp, sourceOp1.copyRO(), sourceOp2.copyRO())); + destination.writeValue(translationHelper, lazy, temp.copyRO()); + OPT_RegisterOperand carry = translationHelper.getCarryFlag(); + translationHelper.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, carry, sourceOp1.copyRO(), sourceOp2.copyRO(), OPT_ConditionOperand + .OVERFLOW_FROM_MUL(), new OPT_BranchProfileOperand())); + OPT_RegisterOperand overflow = translationHelper.getOverflowFlag(); + translationHelper.appendInstructionToCurrentBlock( + Move.create(INT_MOVE, overflow, carry.copyRO())); + } + return pc + length; + } + + /** + * Return "imul" + */ + String getOperatorString() { + return "imul"; + } +} + +/** + * The decoder for the Div opcode + */ +class X86_Div_OpcodeDecoder extends X86_OpcodeDecoder { + /** + * Constructor, {@see X86_OpcodeDecoder} + * @param operandSize + */ + X86_Div_OpcodeDecoder(int operandSize) { + super(operandSize, // operandSize + true, // hasModRM, + 0, // immediateSize + true // isMemoryOperandDestination + ); + } + + /** + * Perform the actual translation + * @param translationHelper + * @param ps + * @param lazy + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected int translate(X862IR translationHelper, ProcessSpace ps, + X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, + int displacement, int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int operandSize; + if (prefix3 == null) { + operandSize = this.operandSize; + } else if (this.operandSize == 32) { + operandSize = 16; + } else { + operandSize = 32; + } + int addressSize; + if (prefix4 == null) { + addressSize = _16BIT ? 16 : 32; + } else { + addressSize = _16BIT ? 32 : 16; + } + if (operandSize != 32) { + TODO(); + } + // longs to perform the div in + OPT_RegisterOperand tempLong1 = translationHelper.getTempLong(0); + OPT_RegisterOperand tempLong2 = translationHelper.getTempLong(1); + // Create EDX:EAX in tempLong1 + OPT_RegisterOperand edx = translationHelper.getGPRegister(lazy, + X86_Registers.EDX, operandSize); + OPT_RegisterOperand eax = translationHelper.getGPRegister(lazy, + X86_Registers.EAX, operandSize); + translationHelper.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, + tempLong1, edx)); + translationHelper.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, + tempLong2, eax)); + translationHelper.appendInstructionToCurrentBlock(Binary.create(LONG_SHL, + tempLong1.copyRO(), tempLong1.copyRO(), new OPT_IntConstantOperand(32))); + translationHelper.appendInstructionToCurrentBlock(Binary.create(LONG_OR, + tempLong1.copyRO(), tempLong1.copyRO(), tempLong2.copyRO())); + // Read unsigned source into tempLong2 + X86_DecodedOperand source; + source = modrm.getRM(translationHelper, lazy, sib, displacement, + operandSize, addressSize, (prefix2 != null) ? prefix2.getSegment() + : X86_Registers.DS); + OPT_RegisterOperand sourceOp = translationHelper.getTempInt(0); + source.readToRegister(translationHelper, lazy, sourceOp); + translationHelper.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, + tempLong2, sourceOp.copyRO())); + translationHelper.appendInstructionToCurrentBlock(Binary.create(LONG_AND, + tempLong2.copyRO(), tempLong2.copyRO(), new OPT_LongConstantOperand(0xFFFFFFFF))); + // Check source isn't zero + OPT_RegisterOperand guard = translationHelper.getTempValidation(0); + translationHelper.appendInstructionToCurrentBlock( + ZeroCheck.create(LONG_ZERO_CHECK, guard, tempLong2.copyRO())); + + // Perform div + OPT_RegisterOperand quotient = translationHelper.getTempLong(2); + OPT_RegisterOperand remainder = translationHelper.getTempLong(3); + translationHelper.appendInstructionToCurrentBlock(GuardedBinary.create(LONG_DIV, + quotient, tempLong1.copyRO(), tempLong2.copyRO(), guard.copyRO())); + translationHelper.appendInstructionToCurrentBlock(GuardedBinary.create(LONG_REM, + remainder, tempLong1.copyRO(), tempLong2.copyRO(), guard.copyRO())); + + // TODO: if the value in EDX:EAX divided by SRC is > 0xFFFFFFFF then a + // divide error exception should be raised + + // Write values + translationHelper.appendInstructionToCurrentBlock(Unary.create(LONG_2INT, + eax.copyRO(), quotient.copyRO())); + translationHelper.appendInstructionToCurrentBlock(Unary.create(LONG_2INT, + edx.copyRO(), remainder.copyRO())); + return pc + length; + } + + /** + * Disassemble the opcode + * @param ps + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immedate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null + */ + protected String disassemble(ProcessSpace ps, int pc, + X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, int displacement, + int immediateSize, int immediate, int length, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + int operandSize; + if (prefix3 == null) { + operandSize = this.operandSize; + } else if (this.operandSize == 32) { + operandSize = 16; + } else { + operandSize = 32; + } + int addressSize; + if (prefix4 == null) { + addressSize = _16BIT ? 16 : 32; + } else { + addressSize = _16BIT ? 32 : 16; + } + + String source; + source = modrm.disassembleRM(sib, displacement, operandSize, addressSize, + (prefix2 != null) ? prefix2.getSegment() : X86_Registers.DS); + return "div " + source; + } +} + +/** * The decoder for the PushA opcode */ class X86_PushA_OpcodeDecoder extends X86_OpcodeDecoder { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-18 14:24:25
|
Revision: 62 http://svn.sourceforge.net/pearcolator/?rev=62&view=rev Author: captain5050 Date: 2007-04-18 07:24:25 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Support for the system call page. Modified Paths: -------------- src/org/binarytranslator/arch/x86/decoder/X862IR.java Modified: src/org/binarytranslator/arch/x86/decoder/X862IR.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-18 14:21:45 UTC (rev 61) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-04-18 14:24:25 UTC (rev 62) @@ -12,6 +12,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; +import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.generic.decoder.DecoderUtils; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; @@ -53,10 +54,37 @@ * @return the next instruction address or -1 */ protected int translateInstruction(Laziness lazy, int pc) { - return X86_InstructionDecoder.translateInstruction((X862IR) this, - (X86_ProcessSpace) ps, (X86_Laziness) lazy, pc); + if (pc != 0xffffe400) { + return X86_InstructionDecoder.translateInstruction((X862IR) this, + (X86_ProcessSpace) ps, (X86_Laziness) lazy, pc); + } else { + return plantSystemCallGateEntry((X86_Laziness) lazy, pc); + } } + /** + * Perform entry from a predetermined address into the Linux kernel + * @param lazy laziness state of registers + * @param pc entry point address + * @return -1 + */ + private int plantSystemCallGateEntry(X86_Laziness lazy, int pc) { + plantSystemCall(lazy, pc); + // Get return address + X86_DecodedOperand source = X86_DecodedOperand.getStack(X86_ProcessSpace._16BIT ? 16 : 32, + X86_ProcessSpace._16BIT ? 16 : 32); + OPT_RegisterOperand temp = getTempInt(0); + source.readToRegister(this, lazy, temp); + + // Increment stack pointer + OPT_RegisterOperand esp = getGPRegister(lazy, X86_Registers.ESP, X86_ProcessSpace._16BIT ? 16 : 32); + appendInstructionToCurrentBlock(Binary.create(INT_ADD, esp, + esp.copyRO(), new OPT_IntConstantOperand(4))); + // Branch + setReturnValueResolveLazinessAndBranchToFinish((X86_Laziness) lazy.clone(), temp.copyRO()); + return -1; + } + // -oO Debug Oo- /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-18 14:21:47
|
Revision: 61 http://svn.sourceforge.net/pearcolator/?rev=61&view=rev Author: captain5050 Date: 2007-04-18 07:21:45 -0700 (Wed, 18 Apr 2007) Log Message: ----------- Simple helloworld tests compiled with GCC Added Paths: ----------- tests/gcc_simple/ tests/gcc_simple/ppc/ tests/gcc_simple/ppc/helloworld tests/gcc_simple/x86/ tests/gcc_simple/x86/helloworld tests/gcc_simple/x86/helloworld.c Added: tests/gcc_simple/ppc/helloworld =================================================================== (Binary files differ) Property changes on: tests/gcc_simple/ppc/helloworld ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: tests/gcc_simple/x86/helloworld =================================================================== (Binary files differ) Property changes on: tests/gcc_simple/x86/helloworld ___________________________________________________________________ Name: svn:executable + * Name: svn:mime-type + application/octet-stream Added: tests/gcc_simple/x86/helloworld.c =================================================================== --- tests/gcc_simple/x86/helloworld.c (rev 0) +++ tests/gcc_simple/x86/helloworld.c 2007-04-18 14:21:45 UTC (rev 61) @@ -0,0 +1,5 @@ +#include <stdio.h> + +int main(int argc, char **argv) { + printf("Helloworld!\n"); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-17 18:11:38
|
Revision: 60 http://svn.sourceforge.net/pearcolator/?rev=60&view=rev Author: michael_baer Date: 2007-04-17 11:11:39 -0700 (Tue, 17 Apr 2007) Log Message: ----------- Temporarily saving progress made while implementing an initial ARM interpreter. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java src/org/binarytranslator/generic/decoder/DisassembledInstruction.java Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/generic/decoder/Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-17 18:11:39 UTC (rev 60) @@ -164,7 +164,10 @@ op.getShiftAmount()); case PcRelative: - return String.format("#%x", op.getOffset() + address + 8); + if (address != -1) + return String.format("#%x", op.getOffset() + address + 8); + else + return String.format("#<%x + pc>", op.getOffset()); case Register: return "r" + op.getRegister(); @@ -312,9 +315,11 @@ public void visit(Branch instr) { String mnemonic = instr.link() ? "BL" : "B"; - setResult(String.format("%s%s #%x", mnemonic, cond(instr), instr - .getOffset() - + address)); + + if (address != -1) + setResult(String.format("%s%s #%x", mnemonic, cond(instr), instr.getOffset() + address + 8)); + else + setResult(String.format("%s%s #<%x + pc>", mnemonic, cond(instr), instr.getOffset())); } public void visit(BranchExchange instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-17 18:11:39 UTC (rev 60) @@ -51,7 +51,7 @@ * An object representation of the decoded instruction. */ static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { - if (getBit(instruction, 27)) { + if (Utils.getBit(instruction, 27)) { return decode_1xx(instruction, factory); } else { @@ -59,29 +59,14 @@ } } - /** - * Checks if a bit is set within a word. - * @param word - * The word that is being examined. - * @param bit - * The number of the bit that is to be checked, starting from zero. - * @return - * True, if the given bit is set within the word, false otherwise. - */ - private static final boolean getBit(int word, int bit) { - if (DBT.VerifyAssertions) - DBT._assert(bit >= 0 && bit <= 31); - return (word & (1 << bit)) != 0; - } - private static <T> T decode_0xx(int instr, ARM_InstructionFactory<T> factory) { if ((instr & 0xF0000000) == 0xF0000000) { return factory.createUndefinedInstruction(instr); } - if (getBit(instr, 26)) { + if (Utils.getBit(instr, 26)) { //opcode: 01 - if (getBit(instr, 25) && getBit(instr, 4)) + if (Utils.getBit(instr, 25) && Utils.getBit(instr, 4)) return factory.createUndefinedInstruction(instr); else return factory.createSingleDataTransfer(instr); @@ -93,7 +78,7 @@ } private static <T> T decode_1xx(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 26)) { + if (Utils.getBit(instr, 26)) { //opcode: 11 return decode_11x( instr, factory); } @@ -104,14 +89,14 @@ } private static <T> T decode_00x(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 25)) + if (Utils.getBit(instr, 25)) return decode_001(instr, factory); else return decode_000(instr, factory); } private static <T> T decode_10x(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 25)) { + if (Utils.getBit(instr, 25)) { //opcode: 101 if ((instr & 0xF0000000) == 0xF0000000) return factory.createBranchExchange(instr); @@ -129,12 +114,12 @@ private static <T> T decode_000(int instr, ARM_InstructionFactory<T> factory) { //opcode: 000 - if (getBit(instr, 24) && !getBit(instr, 23) && !getBit(instr, 20)) { + if (Utils.getBit(instr, 24) && !Utils.getBit(instr, 23) && !Utils.getBit(instr, 20)) { //opcode: 00010xx0 - those are the new instructions, which the ARM ref. manual calls "misc. instructions" return decode_00010xx0(instr, factory); } else { - if (getBit(instr, 4) == false || getBit(instr, 7) == false) + if (Utils.getBit(instr, 4) == false || Utils.getBit(instr, 7) == false) return factory.createDataProcessing(instr); return decode_multiplies_extra_load_stores(instr, factory); @@ -143,11 +128,11 @@ private static <T> T decode_001(int instr, ARM_InstructionFactory<T> factory) { //opcode: 001 - if (!getBit(instr, 24) || getBit(instr, 23) || getBit(instr, 20)) { + if (!Utils.getBit(instr, 24) || Utils.getBit(instr, 23) || Utils.getBit(instr, 20)) { return factory.createDataProcessing(instr); } - if (getBit(instr, 21)) + if (Utils.getBit(instr, 21)) return factory.createMoveToStatusRegister(instr); else return factory.createUndefinedInstruction(instr); @@ -155,13 +140,13 @@ private static <T> T decode_11x(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 25) == false) { + if (Utils.getBit(instr, 25) == false) { //opcode: 110 return factory.createCoprocessorDataTransfer(instr); } //opcode: 111 - if (getBit(instr, 24)) { + if (Utils.getBit(instr, 24)) { //opcode: 1111 if ((instr & 0xF0000000) == 0xF0000000) return factory.createUndefinedInstruction(instr); @@ -170,7 +155,7 @@ } else { //opcode: 1110 - if (getBit(instr, 4)) { + if (Utils.getBit(instr, 4)) { return factory.createCoprocessorDataTransfer(instr); } else { @@ -185,7 +170,7 @@ */ private static <T> T decode_00010xx0(int instr, ARM_InstructionFactory<T> factory) { // - if (getBit(instr, 6) || getBit(instr, 7)) { + if (Utils.getBit(instr, 6) || Utils.getBit(instr, 7)) { //enhanced DSP multiplications, DSP add/subtracts and software breakpoints //we might want to support these in the future, so when in debug mode, catch if any program actually uses them if (DBT.VerifyAssertions) DBT._assert(false); @@ -193,14 +178,14 @@ } else { //bit 6 and 7 are clear - if (getBit(instr, 4)) { - if (getBit(instr, 22)) + if (Utils.getBit(instr, 4)) { + if (Utils.getBit(instr, 22)) return factory.createCountLeadingZeros(instr); else return factory.createBranchExchange(instr); } else { - if (getBit(instr, 21)) + if (Utils.getBit(instr, 21)) return factory.createMoveToStatusRegister(instr); else return factory.createMoveFromStatusRegister(instr); @@ -215,25 +200,25 @@ */ private static <T> T decode_multiplies_extra_load_stores(int instr, ARM_InstructionFactory<T> factory) { //Here, we already know that bits 4 and 7 are set, while bit 25-27 are clear - if (getBit(instr, 6)) { + if (Utils.getBit(instr, 6)) { //load/store signed half-word or two words - if (getBit(instr, 20)) + if (Utils.getBit(instr, 20)) return factory.createSingleDataTransfer(instr); else return factory.createUndefinedInstruction(instr); //two words immediate offset } else { - if (getBit(instr, 5)) { + if (Utils.getBit(instr, 5)) { //load/store half-word return factory.createSingleDataTransfer(instr); } else { //Multiply, multiply long or Swap - if (getBit(instr, 24)) { + if (Utils.getBit(instr, 24)) { return factory.createSwap(instr); } else { - if (getBit(instr, 23)) + if (Utils.getBit(instr, 23)) return factory.createLongMultiply(instr); else return factory.createIntMultiply(instr); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-17 18:11:39 UTC (rev 60) @@ -17,52 +17,6 @@ */ public class ARM_Instructions { - /** - * Checks if a bit is set within a word. - * @param word - * The word that is being examined. - * @param bit - * The number of the bit that is to be checked, starting from zero. - * @return - * True, if the given bit is set within the word, false otherwise. - */ - private static final boolean getBit(int word, int bit) { - if (DBT.VerifyAssertions) - DBT._assert(bit >= 0 && bit <= 31); - return (word & (1 << bit)) != 0; - } - - /** - * Extracts a subsequence of bits from a word. - * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. - * @param word - * The word that is to be examined. - * @param from - * The first bit (starting from 0) that is to be extracted. - * @param to - * The last bit (starting from 0) that is to be extracted from the word. - * @return - * A zero-based version of the bit sequence. - */ - private static final int getBits(int word, int from, int to) { - if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to <= 31); - return (word & ((1 << (to + 1)) - 1)) >> from; - } - - /** - * Sign extends a given value. - * @param value - * The value to sign extends. - * @param bitsUsed - * The number bits used within this values. - * @return - * A sign extended value. - */ - public static int signExtend(int value, int bitsUsed) { - return (value << (32 - bitsUsed)) >> (32 - bitsUsed); - } - /** A base class for all (conditional) ARM instructions. */ public abstract static class Instruction { @@ -74,7 +28,7 @@ protected final Condition condition; private Instruction(int instr) { - condition = Condition.values()[(byte) getBits(instr, 28, 31)]; + condition = Condition.values()[(byte) Utils.getBits(instr, 28, 31)]; } /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ @@ -103,8 +57,8 @@ public TwoRegistersTemplate(int instr) { super(instr); - Rd = (byte) getBits(instr, 12, 15); - Rn = (byte) getBits(instr, 16, 19); + Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); } /** Returns the number of the operation's destination register, starting from 0.*/ @@ -128,7 +82,7 @@ public ThreeRegistersTemplate(int instr) { super(instr); - Rm = (byte) getBits(instr, 0, 3); + Rm = (byte) Utils.getBits(instr, 0, 3); } /** Returns the number of the second operand register, starting from 0.*/ @@ -153,9 +107,9 @@ protected MultiplyTemplate(int instr) { super(instr); - updateConditionCodes = getBit(instr, 20); - accumulate = getBit(instr, 21); - Rs = (byte) getBits(instr, 8, 11); + updateConditionCodes = Utils.getBit(instr, 20); + accumulate = Utils.getBit(instr, 21); + Rs = (byte) Utils.getBits(instr, 8, 11); } /** Returns true, if the condition codes shall be updated by the result of this operation. */ @@ -189,9 +143,9 @@ public CoprocessorTemplate(int instr) { super(instr); - cpNum = (byte) getBits(instr, 8, 11); - Rd = (byte) getBits(instr, 12, 15); - Rn = (byte) getBits(instr, 16, 19); + cpNum = (byte) Utils.getBits(instr, 8, 11); + Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); } /** Returns the coprocessor that shall process this instruction */ @@ -238,32 +192,35 @@ /** Creates an operand wrapper, that represents a register shifted by an immediate or a register, depending on the instruction. */ public static OperandWrapper decodeShiftedRegister(int instr) { - ShiftType shift = ShiftType.values()[getBits(instr, 5, 6)]; + ShiftType shift = ShiftType.values()[Utils.getBits(instr, 5, 6)]; byte shiftedRegister = (byte) (instr & 0xF); - if (getBit(instr, 4)) { + if (Utils.getBit(instr, 4)) { //shift by a register - byte shiftingRegister = (byte)getBits(instr, 8, 11); + byte shiftingRegister = (byte)Utils.getBits(instr, 8, 11); return new RegisterShiftRegisterOperand(shiftedRegister, shift, shiftingRegister); } else { //shift by an immediate - byte immediate = (byte)getBits(instr, 7, 11); + byte immediate = (byte)Utils.getBits(instr, 7, 11); if (immediate == 0) { - //if we are shifting by zero, we might forget about the shift + + if (shift == ShiftType.LSL) { + //If we are shifting by zero with LSL, then this is supposed to denote a register operand + return new RegisterOperand(shiftedRegister); + } + if (shift == ShiftType.ROR) { //However, if the shift type was RotateRight, then ARM meant do a RotateRightExtend by 1 return new RegisterShiftImmediateOperand(shiftedRegister, shift, (byte)1); } - else { - //Otherwise, really forget about the shifting - return new RegisterOperand(shiftedRegister); - } + + //in all other cases, an immediate of zero denotes a shift by 32 + immediate = 32; } - else { - return new RegisterShiftImmediateOperand(shiftedRegister, shift, immediate); - } + + return new RegisterShiftImmediateOperand(shiftedRegister, shift, immediate); } } @@ -305,15 +262,20 @@ /** @see #getImmediate() */ protected final int immediate; - + protected ImmediateOperand(int immediate) { this.immediate = immediate; } - + @Override public int getImmediate() { return immediate; } + + @Override + public byte getShiftAmount() { + return 0; + } @Override public Type getType() { @@ -452,11 +414,11 @@ public DataProcessing(int instr) { super(instr); - updateConditionCodes = getBit(instr, 20); - opcode = Opcode.values()[(byte) getBits(instr, 21, 24)]; + updateConditionCodes = Utils.getBit(instr, 20); + opcode = Opcode.values()[(byte) Utils.getBits(instr, 21, 24)]; - if (getBit(instr, 25)) - operand2 = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); + if (Utils.getBit(instr, 25)) + operand2 = OperandWrapper.createImmediate(Integer.rotateRight(instr & 0xFF, Utils.getBits(instr, 8, 11) << 2)); else operand2 = OperandWrapper.decodeShiftedRegister(instr); } @@ -519,40 +481,40 @@ public SingleDataTransfer(int instr) { super(instr); - preIndexing = getBit(instr, 24); - positiveOffset = getBit(instr, 23); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); + preIndexing = Utils.getBit(instr, 24); + positiveOffset = Utils.getBit(instr, 23); + writeBack = Utils.getBit(instr, 21); + isLoad = Utils.getBit(instr, 20); - if (getBit(instr, 26)) { + if (Utils.getBit(instr, 26)) { //this is an unsigned byte or word transfer signExtend = false; forceUserMode = !preIndexing && writeBack; - if (getBit(instr, 22)) + if (Utils.getBit(instr, 22)) size = TransferSize.Byte; else size = TransferSize.Word; - if (getBit(instr, 25)) + if (Utils.getBit(instr, 25)) offset = OperandWrapper.createImmediate(instr & 0xFF); else offset = OperandWrapper.decodeShiftedRegister(instr); } else { //this is a byte or half-word transfer - if (getBit(instr, 5)) + if (Utils.getBit(instr, 5)) size = TransferSize.HalfWord; else size = TransferSize.Byte; - signExtend = getBit(instr, 6); + signExtend = Utils.getBit(instr, 6); forceUserMode = false; - if (getBit(instr, 22)) { + if (Utils.getBit(instr, 22)) { //immediate offset - offset = OperandWrapper.createImmediate((getBits(instr, 8, 11) << 4) | (instr & 0xF)); + offset = OperandWrapper.createImmediate((Utils.getBits(instr, 8, 11) << 4) | (instr & 0xF)); } else { //register offset @@ -616,7 +578,8 @@ protected IntMultiply(int instr) { super(instr); - if (DBT.VerifyAssertions) DBT._assert(accumulate || Rn == 0); + //check for instruction combinations that show undefined behaviour on ARM + if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } @Override @@ -634,7 +597,10 @@ public LongMultiply(int instr) { super(instr); - unsigned = getBit(instr, 22); + unsigned = Utils.getBit(instr, 22); + + //check for instruction combinations that show undefined behaviour on ARM + if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ @@ -666,7 +632,7 @@ public Swap(int instr) { super(instr); - swapByte = getBit(instr, 22); + swapByte = Utils.getBit(instr, 22); } /** Returns true, if a byte shall be swapped or false, if an int (32 bit) shall be swapped. */ @@ -707,12 +673,12 @@ public BlockDataTransfer(int instr) { super(instr); - postIndexing = getBit(instr, 24); - incrementBase = getBit(instr, 23); - forceUser = getBit(instr, 22); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); - baseRegister = (byte) getBits(instr, 16, 19); + postIndexing = Utils.getBit(instr, 24); + incrementBase = Utils.getBit(instr, 23); + forceUser = Utils.getBit(instr, 22); + writeBack = Utils.getBit(instr, 21); + isLoad = Utils.getBit(instr, 20); + baseRegister = (byte) Utils.getBits(instr, 16, 19); registerList = instr; } @@ -721,7 +687,7 @@ if (DBT.VerifyAssertions) DBT._assert(r >= 0 && r < 16); - return getBit(registerList, r); + return Utils.getBit(registerList, r); } /** True if the base register shall be changed after each single transfer, otherwise changed it before each transfer. */ @@ -793,7 +759,7 @@ public Branch(int instr) { super(instr); - link = getBit(instr, 24); + link = Utils.getBit(instr, 24); offset = instr & 0xFFF; } @@ -823,23 +789,23 @@ protected final boolean link; public BranchExchange(int instr) { - super(getBit(instr, 27) ? 0xE0000000 : instr); + super(Utils.getBit(instr, 27) ? 0xE0000000 : instr); - if (getBit(instr, 27)) { + if (Utils.getBit(instr, 27)) { //this is the immediate version of a BLX link = true; //sign extend jump target - int jumpTarget = signExtend(instr & 0xFFF, 24) << 2; + int jumpTarget = Utils.signExtend(instr & 0xFFF, 24) << 2; //are we addressing a half-byte? - if (getBit(instr, 24)) + if (Utils.getBit(instr, 24)) jumpTarget += 2; target = OperandWrapper.createPcRelative(jumpTarget); } else { - link = getBit(instr, 5); + link = Utils.getBit(instr, 5); target = OperandWrapper.createRegister((byte) (instr & 0xF)); } } @@ -881,16 +847,16 @@ public CoprocessorDataTransfer(int instr) { super(instr); - preIndexing = getBit(instr, 24); - largeTransfer = getBit(instr, 22); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); + preIndexing = Utils.getBit(instr, 24); + largeTransfer = Utils.getBit(instr, 22); + writeBack = Utils.getBit(instr, 21); + isLoad = Utils.getBit(instr, 20); if (!writeBack && !preIndexing) { offset = instr & 0xFF; } else { - if (getBit(instr, 23)) + if (Utils.getBit(instr, 23)) offset = (instr & 0xFF) << 2; else offset = - ((instr & 0xFF) << 2); @@ -960,8 +926,8 @@ public CoprocessorDataProcessing(int instr) { super(instr); - opcode = (byte) getBits(instr, 20, 23); - cpInfo = (byte) getBits(instr, 5, 7); + opcode = (byte) Utils.getBits(instr, 20, 23); + cpInfo = (byte) Utils.getBits(instr, 5, 7); cpRm = (byte) (instr & 0xF); } @@ -1014,10 +980,10 @@ public CoprocessorRegisterTransfer(int instr) { super(instr); - opcode = (byte) getBits(instr, 21, 23); - cpInfo = (byte) getBits(instr, 5, 7); + opcode = (byte) Utils.getBits(instr, 21, 23); + cpInfo = (byte) Utils.getBits(instr, 5, 7); cpRm = (byte) (instr & 0xF); - isLoad = getBit(instr, 20); + isLoad = Utils.getBit(instr, 20); } /** Returns true if this operation is a load from a coprocessor or false if it is a store to coprocessor. */ @@ -1068,8 +1034,8 @@ public MoveFromStatusRegister(int instr) { super(instr); - Rd = (byte) getBits(instr, 12, 15); - transferSavedPSR = getBit(instr, 22); + Rd = (byte) Utils.getBits(instr, 12, 15); + transferSavedPSR = Utils.getBit(instr, 22); } /** Returns the number of the destination register. */ @@ -1112,15 +1078,15 @@ public MoveToStatusRegister(int instr) { super(instr); - transferControl = getBit(instr, 16); - transferExtension = getBit(instr, 17); - transferStatus = getBit(instr, 18); - transferFlags = getBit(instr, 19); + transferControl = Utils.getBit(instr, 16); + transferExtension = Utils.getBit(instr, 17); + transferStatus = Utils.getBit(instr, 18); + transferFlags = Utils.getBit(instr, 19); - transferSavedPSR = getBit(instr, 22); + transferSavedPSR = Utils.getBit(instr, 22); - if (getBit(instr, 25)) - sourceOperand = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); + if (Utils.getBit(instr, 25)) + sourceOperand = OperandWrapper.createImmediate((instr & 0xFF) << Utils.getBits(instr, 8, 11)); else sourceOperand = OperandWrapper.decodeShiftedRegister(instr); } @@ -1174,7 +1140,7 @@ super(instr); Rm = (byte) (instr & 0xF); - Rd = (byte) getBits(instr, 12, 15); + Rd = (byte) Utils.getBits(instr, 12, 15); } /** Returns the source register for this operation. */ Added: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-17 18:11:39 UTC (rev 60) @@ -0,0 +1,821 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.decoder.Interpreter.Instruction; + +public class ARM_Interpreter { + + protected final ARM_ProcessSpace ps; + + protected final ARM_Registers regs; + + public ARM_Interpreter(ARM_ProcessSpace ps) { + this.ps = ps; + this.regs = ps.registers; + } + + private final class ConditionalDecorator implements Interpreter.Instruction { + + protected final Interpreter.Instruction conditionalInstruction; + + protected ConditionalDecorator(Interpreter.Instruction i) { + conditionalInstruction = i; + } + + public void execute() { + conditionalInstruction.execute(); + } + + public int getSuccessor(int pc) { + return -1; + } + } + + private abstract class DataProcessing extends ARM_Instructions.DataProcessing + implements Interpreter.Instruction { + + protected boolean shifterCarryOut; + + protected DataProcessing(int instr) { + super(instr); + } + + protected final int resolveShift(OperandWrapper operand) { + + int value = regs.get(operand.getRegister()); + byte shiftAmount; + + if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) + shiftAmount = operand.getShiftAmount(); + else { + shiftAmount = (byte) (regs.get(operand.getShiftingRegister()) & 0xF); + } + + switch (operand.getShiftType()) { + case ASR: + + if (shiftAmount > 32) + shiftAmount = 32; + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >>> shiftAmount; + } + + case LSL: + + if (shiftAmount > 32) + shiftAmount = 32; + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); + return value << shiftAmount; + } + + case LSR: + + if (shiftAmount > 32) + shiftAmount = 32; + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >> shiftAmount; + } + + case ROR: + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, shiftAmount & 0x1F); + return Integer.rotateRight(value, shiftAmount); + } + + case RRE: + shifterCarryOut = (value & 0x1) != 0; + + if (regs.isCarrySet()) + return (value >> 1) | 0x80000000; + else + return value >> 1; + + default: + throw new RuntimeException("Unexpected shift type: " + + operand.getShiftType()); + } + } + + protected int resolveOperand2() { + int value; + + switch (operand2.getType()) { + case Immediate: + value = operand2.getImmediate(); + + if (operand2.getShiftAmount() == 0) + shifterCarryOut = regs.isCarrySet(); + else + shifterCarryOut = (value & 0x80000000) != 0; + + case Register: + shifterCarryOut = regs.isCarrySet(); + return regs.get(operand2.getRegister()); + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + return resolveShift(operand2); + + case PcRelative: + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand2.getType()); + } + } + + + public abstract void execute(); + + protected final void setFlagsForResult(int result) { + + if (updateConditionCodes) { + if (Rd != 15) { + regs.setFlags(result < 0, result == 0, shifterCarryOut); + } else { + regs.restoreSPSR2CPSR(); + } + } + } + + protected final void setFlagsForAdd(int lhs, int rhs) { + + if (updateConditionCodes) { + if (Rd != 15) { + int result = lhs + rhs; + boolean carry = Utils.unsignedAddOverflow(lhs, rhs); + boolean overflow = Utils.signedAddOverflow(lhs, rhs); + regs.setFlags(result < 0, result == 0, carry, overflow); + } + else { + regs.restoreSPSR2CPSR(); + } + } + } + + public int getSuccessor(int pc) { + if (Rd == 15) + return pc + 4; + else + return -1; + } + } + + private final class DataProcessing_And extends DataProcessing { + + protected DataProcessing_And(int instr) { + super(instr); + } + + + @Override + public void execute() { + int result = regs.get(Rn) & resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private final class DataProcessing_Eor extends DataProcessing { + + protected DataProcessing_Eor(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = regs.get(Rn) ^ resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Add extends DataProcessing { + + public DataProcessing_Add(int instr) { + super(instr); + } + + protected int resolveOperand1() { + return regs.get(Rn); + } + + public void execute() { + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); + int result = operand1 + operand2; + + regs.set(Rd, result); + setFlagsForAdd(operand1, operand2); + } + } + + private final class DataProcessing_Sub extends DataProcessing_Add { + + public DataProcessing_Sub(int instr) { + super(instr); + } + + @Override + protected int resolveOperand2() { + return -super.resolveOperand2(); + } + } + + private final class DataProcessing_Rsb extends DataProcessing_Add { + + protected DataProcessing_Rsb(int instr) { + super(instr); + } + + @Override + protected int resolveOperand1() { + return -super.resolveOperand1(); + } + } + + private class DataProcessing_Adc extends DataProcessing_Add { + + protected int cachedOperand1; + protected int cachedOperand2; + + protected DataProcessing_Adc(int instr) { + super(instr); + } + + @Override + protected int resolveOperand1() { + return cachedOperand1; + } + + @Override + protected int resolveOperand2() { + return cachedOperand2; + } + + @Override + public void execute() { + cachedOperand1 = super.resolveOperand1(); + cachedOperand2 = super.resolveOperand2(); + + if (regs.isCarrySet()) { + if (cachedOperand1 != Integer.MAX_VALUE) { + cachedOperand1++; + } else if (cachedOperand2 != Integer.MAX_VALUE) { + cachedOperand2++; + } else { + regs.setFlags(cachedOperand1 > 0, cachedOperand1 != 0, true, true); + return; + } + } + + super.execute(); + } + } + + private class DataProcessing_Sbc extends DataProcessing_Adc { + + protected DataProcessing_Sbc(int instr) { + super(instr); + } + + @Override + protected int resolveOperand2() { + return -cachedOperand2; + } + } + + private class DataProcessing_Rsc extends DataProcessing_Adc { + + protected DataProcessing_Rsc(int instr) { + super(instr); + } + + @Override + protected int resolveOperand1() { + return -cachedOperand1; + } + } + + private class DataProcessing_Tst extends DataProcessing { + + protected DataProcessing_Tst(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForResult(regs.get(Rn) & resolveOperand2()); + } + } + + private class DataProcessing_Teq extends DataProcessing { + + protected DataProcessing_Teq(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForResult(regs.get(Rn) ^ resolveOperand2()); + } + } + + private class DataProcessing_Cmp extends DataProcessing { + + protected DataProcessing_Cmp(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForAdd(regs.get(Rn), -resolveOperand2()); + } + } + + private class DataProcessing_Cmn extends DataProcessing { + + protected DataProcessing_Cmn(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForAdd(regs.get(Rn), resolveOperand2()); + } + } + + private class DataProcessing_Orr extends DataProcessing { + + protected DataProcessing_Orr(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = regs.get(Rn) | resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Mov extends DataProcessing { + + protected DataProcessing_Mov(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Bic extends DataProcessing { + + protected DataProcessing_Bic(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = regs.get(Rn) & (~resolveOperand2()); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Mvn extends DataProcessing { + + protected DataProcessing_Mvn(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = ~resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class Swap extends ARM_Instructions.Swap implements Interpreter.Instruction { + + public Swap(int instr) { + super(instr); + } + + public void execute() { + int memAddr = regs.get(Rn); + + //swap exchanges the value of a memory address with the value in a register + int tmp = ps.memory.load32(memAddr); + ps.memory.store16(memAddr, regs.get(Rm)); + + //according to the ARM architecture reference, the value loaded from a memory address is rotated + //according to the number of ones in the first two bits of the address + regs.set(Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class BlockDataTransfer extends ARM_Instructions.BlockDataTransfer implements Interpreter.Instruction { + + public BlockDataTransfer(int instr) { + super(instr); + } + + public void execute() { + //start address ignores the last two bits + int startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + + //build a map of registers that are to be transfered + int registerCount = 0; + boolean transferPC = false; + int[] registersToTransfer = new int[16]; + + for (int i = 0; i < 14; i++) + if (transferRegister(i)) { + registersToTransfer[registerCount++] = i; + } + + //also remember if we're supposed to transfer the pc, but don't include it in the register list + transferPC = transferRegister(15); + + if (!incrementBase) { + if (postIndexing) + startAddress -= (registerCount + (transferPC ? -1 : 0)) * 4; //post-indexing, backward reading + else + startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; //pre-indexing, backward-reading + } + else if (postIndexing) { + //post-indexing, forward reading + startAddress -= 4; + } + + //are we supposed to load or store multiple registers? + if (isLoad) { + //read the actual registers + for (int i = 0; i < registerCount; i++) { + startAddress += 4; + regs.set(registersToTransfer[i], ps.memory.load32(startAddress)); + } + + //if we also transferred the program counter + if (transferPC) { + int newpc = ps.memory.load32(startAddress + 4); + regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); + + //shall we switch to thumb mode + regs.setThumbMode((newpc & 0x1) != 0); + } + } + else { + //also transfer the program counter, if requested so + if (transferPC) + registersToTransfer[registerCount++] = 15; + + for (int i = 0; i < registerCount; i++) { + startAddress += 4; + ps.memory.store32(startAddress, regs.get(i)); + } + } + } + + public int getSuccessor(int pc) { + //if we're loading values into the PC, then we can't tell where this instruction will be going + if (isLoad && transferRegister(ARM_Registers.PC)) + return -1; + else + return pc+4; + } + } + + private class Branch extends ARM_Instructions.Branch implements Interpreter.Instruction { + + public Branch(int instr) { + super(instr); + } + + public void execute() { + int previousAddress = regs.get(ARM_Registers.PC); + + //jump to the new address + regs.set(ARM_Registers.PC, previousAddress + getOffset()); + + //if we're supposed to link, then write the previous address into the link register + if (link) + regs.set(ARM_Registers.LR, previousAddress + 4); + } + + public int getSuccessor(int pc) { + return pc + getOffset(); + } + } + + private class BranchExchange extends ARM_Instructions.BranchExchange implements Interpreter.Instruction { + + public BranchExchange(int instr) { + super(instr); + } + + public void execute() { + int previousAddress = regs.get(ARM_Registers.PC); + boolean thumb; + int targetAddress; + + switch (target.getType()) { + case PcRelative: + targetAddress = previousAddress + target.getOffset(); + thumb = true; + break; + + case Register: + targetAddress = regs.get(target.getRegister()); + thumb = (targetAddress & 0x1) != 0; + targetAddress = targetAddress & 0xFFFFFFFE; + break; + + default: + throw new RuntimeException("Unexpected Operand type: " + target.getType()); + } + + //jump to the new address + regs.set(ARM_Registers.PC, targetAddress); + regs.setThumbMode(thumb); + + //if we're supposed to link, then write the previous address into the link register + if (link) + regs.set(ARM_Registers.LR, previousAddress + 4); + } + + public int getSuccessor(int pc) { + //if we're jumping relative to the PC, then we can predict the next instruction + if (target.getType() == OperandWrapper.Type.PcRelative) { + return pc + target.getOffset(); + } + else { + //otherwise we can't predict it + return -1; + } + } + } + + private class CountLeadingZeros extends ARM_Instructions.CountLeadingZeros implements Interpreter.Instruction { + + public CountLeadingZeros(int instr) { + super(instr); + } + + public void execute() { + int leadingZeros = Integer.numberOfLeadingZeros(regs.get(Rm)); + regs.set(Rd, leadingZeros); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class IntMultiply extends ARM_Instructions.IntMultiply implements Interpreter.Instruction { + + protected IntMultiply(int instr) { + super(instr); + } + + public void execute() { + int result = regs.get(Rm) * regs.get(Rs); + + if (accumulate) + result += regs.get(Rn); + + regs.set(Rd, result); + + if (updateConditionCodes) { + regs.setFlags(result < 0, result == 0); + } + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class MoveFromStatusRegister extends ARM_Instructions.MoveFromStatusRegister implements Interpreter.Instruction { + + public MoveFromStatusRegister(int instr) { + super(instr); + } + + public void execute() { + int statusRegisterValue; + + if (transferSavedPSR) { + statusRegisterValue = regs.getSPSR(); + } + else { + statusRegisterValue = regs.getCPSR(); + } + + regs.set(Rd, statusRegisterValue); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt implements Interpreter.Instruction { + + public SoftwareInterrupt(int instr) { + super(instr); + } + + public void execute() { + ps.doSysCall(); + } + + public int getSuccessor(int pc) { + return -1; + } + + } + + private class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer implements Interpreter.Instruction { + + public SingleDataTransfer(int instr) { + super(instr); + } + + public void execute() { + + } + + public int getSuccessor(int pc) { + //if we're loading to the PC, then the next instruction is undefined + if (Rd == ARM_Registers.PC) + return -1; + + return pc+4; + } + + } + + private class UndefinedInstruction implements Interpreter.Instruction { + + private final int instruction; + + public UndefinedInstruction(int instr) { + this.instruction = instr; + } + + public void execute() { + throw new RuntimeException("Undefined instruction: " + instruction); + } + + public int getSuccessor(int pc) { + return -1; + } + } + + class InterpreterFactory implements + ARM_InstructionFactory<Interpreter.Instruction> { + + public Interpreter.Instruction createDataProcessing(int instr) { + Opcode opcode = Opcode.values()[Utils.getBits(instr, 21, 24)]; + + switch (opcode) { + case ADC: + return new DataProcessing_Adc(instr); + case ADD: + return new DataProcessing_Add(instr); + case AND: + return new DataProcessing_And(instr); + case BIC: + return new DataProcessing_Bic(instr); + case CMN: + return new DataProcessing_Cmn(instr); + case CMP: + return new DataProcessing_Cmp(instr); + case EOR: + return new DataProcessing_Eor(instr); + case MOV: + return new DataProcessing_Mov(instr); + case MVN: + return new DataProcessing_Mvn(instr); + case ORR: + return new DataProcessing_Orr(instr); + case RSB: + return new DataProcessing_Rsb(instr); + case RSC: + return new DataProcessing_Rsc(instr); + case SBC: + return new DataProcessing_Sbc(instr); + case SUB: + return new DataProcessing_Sub(instr); + case TEQ: + return new DataProcessing_Teq(instr); + case TST: + return new DataProcessing_Tst(instr); + + default: + throw new RuntimeException("Unexpected Data Procesing opcode: " + + opcode); + } + } + + public Instruction createBlockDataTransfer(int instr) { + return new BlockDataTransfer(instr); + } + + public Instruction createBranch(int instr) { + return new Branch(instr); + } + + public Instruction createBranchExchange(int instr) { + return new BranchExchange(instr); + } + + public Instruction createCoprocessorDataProcessing(int instr) { + //TODO: Implement coprocessor instructions + throw new RuntimeException("Coprocessor instructions are not yet supported."); + } + + public Instruction createCoprocessorDataTransfer(int instr) { +// TODO: Implement coprocessor instructions + throw new RuntimeException("Coprocessor instructions are not yet supported."); + } + + public Instruction createCoprocessorRegisterTransfer(int instr) { +// TODO: Implement coprocessor instructions + throw new RuntimeException("Coprocessor instructions are not yet supported."); + } + + public Instruction createCountLeadingZeros(int instr) { + return new CountLeadingZeros(instr); + } + + public Instruction createIntMultiply(int instr) { + return new IntMultiply(instr); + } + + public Instruction createLongMultiply(int instr) { + throw new RuntimeException("Long Multiplications are not yet supported."); + } + + public Instruction createMoveFromStatusRegister(int instr) { + return new MoveFromStatusRegister(instr); + } + + public Instruction createMoveToStatusRegister(int instr) { + //TODO: Implement Register -> CPSR transfers + throw new RuntimeException("Modifying the status register using MSR is not yet supported."); + } + + public Instruction createSingleDataTransfer(int instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createSoftwareInterrupt(int instr) { + return new SoftwareInterrupt(instr); + } + + public Instruction createSwap(int instr) { + return new Swap(instr); + } + + public Instruction createUndefinedInstruction(int instr) { + return new UndefinedInstruction(instr); + } + } + +} Added: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-17 18:11:39 UTC (rev 60) @@ -0,0 +1,84 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.DBT; + +class Utils { + + /** + * Checks if a bit is set within a word. + * @param word + * The word that is being examined. + * @param bit + * The number of the bit that is to be checked, starting from zero. + * @return + * True, if the given bit is set within the word, false otherwise. + */ + static final boolean getBit(int word, int bit) { + if (DBT.VerifyAssertions) + DBT._assert(bit >= 0 && bit <= 31); + return (word & (1 << bit)) != 0; + } + + /** + * Extracts a subsequence of bits from a word. + * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. + * @param word + * The word that is to be examined. + * @param from + * The first bit (starting from 0) that is to be extracted. + * @param to + * The last bit (starting from 0) that is to be extracted from the word. + * @return + * A zero-based version of the bit sequence. + */ + static final int getBits(int word, int from, int to) { + if (DBT.VerifyAssertions) + DBT._assert(from < to && from >= 0 && to <= 31); + return (word & ((1 << (to + 1)) - 1)) >> from; + } + + /** + * Sign extends a given value. + * @param value + * The value to sign extends. + * @param bitsUsed + * The number bits used within this values. + * @return + * A sign extended value. + */ + static int signExtend(int value, int bitsUsed) { + return (value << (32 - bitsUsed)) >> (32 - bitsUsed); + } + + /** + * Returns true, if the addition of both operands as unsigned integers will cause an overflow. + * This basically checks <code> operand1 + operand2 > Integer.MAX_VALUE</code>. + */ + static boolean unsignedAddOverflow(int operand1, int operand2) { + return operand1 > Integer.MAX_VALUE - operand2; + } + + /** + * Returns true, if the subtraction of both operand1 - operand2 (both unsigned) will be a negative number. + * That only happens when <code>operand1 < operand2</code> + */ + static boolean unsignedSubOverflow(int operand1, int operand2) { + return operand1 < operand2; + } + + /** + * Returns true, if the addition of both operands as unsigned integers will cause an overflow. + * The algorithm for this code was taken from http://msdn2.microsoft.com/en-us/library/ms972705.aspx. + */ + static boolean signedAddOverflow(int operand1, int operand2) { + //overflow can only occur when both signs differ + if ((operand1 ^ operand2) >= 0) { + return false; + } + + if (operand1 < 0) + return operand1 < Integer.MIN_VALUE - operand2; + else + return Integer.MAX_VALUE - operand1 < operand2; + } +} Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-17 18:11:39 UTC (rev 60) @@ -75,7 +75,7 @@ public static ProcessSpace createProcessSpaceFromBinary(Loader loader) throws IOException { if (loader.isARM_ABI() || loader.isSysV_ABI()) { - report("Creating ARM Linux ABI [rocess space"); + report("Creating ARM Linux ABI Process space"); return new ARM_LinuxProcessSpace(); } else { report("Creating ARM image process space."); @@ -96,21 +96,21 @@ */ @Uninterruptible public int getCurrentInstructionAddress() { - return registers.read(ARM_Registers.PC); + return registers.get(ARM_Registers.PC); } /** * Sets the current instruction's address */ public void setCurrentInstructionAddress(int pc) { - registers.write(ARM_Registers.PC, pc); + registers.set(ARM_Registers.PC, pc); } /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { - return registers.read(14); + return registers.get(ARM_Registers.SP); } /** Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-17 18:11:39 UTC (rev 60) @@ -4,8 +4,8 @@ public final class ARM_Registers { - public final static int SP = 14; - + public final static int SP = 13; + public final static int LR = 14; public final static int PC = 15; /** @@ -77,23 +77,38 @@ public final static byte OPERATING_MODE_ABT = 0x17; public final static byte OPERATING_MODE_UND = 0x1A; + + /** Is the processor currently in thumb mode? */ + private boolean thumbMode = false; public ARM_Registers() { } - public int read(int reg) { + /** Returns the value of the specified register. */ + public int get(int reg) { if (VM.VerifyAssertions) VM._assert(reg < 16); return regs[reg]; } - public void write(int reg, int value) { + /** Sets the value of the specified register (<code>reg</code>) to <code>value</code>. */ + public void set(int reg, int value) { if (VM.VerifyAssertions) VM._assert(reg < 16); regs[reg] = value; } + + /** + * Restores the saved program status register of the current operating mode to the CPSR, + * thereby effectively switching to a different operating mode. + */ + public void restoreSPSR2CPSR() { + if (VM.VerifyAssertions) VM._assert(operatingMode != OPERATING_MODE_USR && operatingMode != OPERATING_MODE_SVC); + + setFlagsFromCPSR(getSPSR()); + } /** * Returns the content of ARM's Current Program Status Register. @@ -104,8 +119,13 @@ return (flagNegative ? 1 << 31 : 0) | (flagZero ? 1 << 30 : 0) | (flagCarry ? 1 << 29 : 0) | (flagOverflow ? 1 << 28 : 0) | (flagIRQsDisabled ? 1 << 7 : 0) | (flagFIQsDisabled ? 1 << 6 : 0) - | operatingMode; + | (thumbMode ? 1 << 5 : 0) | operatingMode; } + + /** Returns the content of the current mode's Saved Program Status register.*/ + public int getSPSR() { + throw new RuntimeException("Accessing the SPSR is not yet implemented"); + } /** * Restores the processor state to the state saved within the given CPSR. @@ -114,7 +134,69 @@ * ARM CPSR register content */ public void setFlagsFromCPSR(int cpsr) { - throw new RuntimeException("Not yet implemented."); + throw new RuntimeException("Interpreting a previous SPSR is not yet implemented."); } + + /** + * This function switches the processor to either ARM or Thumb mode. + * + * @param enable + * Set to true to enable execution of thumb code, false otherwise. + */ + public void setThumbMode(boolean enable) { + thumbMode = enable; + } + + /** + * Sets all flags at once. This operation is very common in the ARm architecture and therefore + * implemented explicitely. + * @param negative + * The value of the negative flag. + * @param zero + * The value of the zero flag. + * @param carry + * The value of the carry flag. + * @param overflow + * The value of the overflow flag. + */ + public void setFlags(boolean negative, boolean zero, boolean carry, boolean overflow) { + flagNegative = negative; + flagZero = zero; + flagCarry = carry; + flagOverflow = overflow; + } + + /** + * Sets all flags, except for the overflow flag, at once. This operation is very common in the ARm architecture and therefore + * implemented explicitely. + * @param negative + * The value of the negative flag. + * @param zero + * The value of the zero flag. + * @param carry + * The value of the carry flag. + */ + public void setFlags(boolean negative, boolean zero, boolean carry) { + flagNegative = negative; + flagZero = zero; + flagCarry = carry; + } + + /** + * Sets the negative and zero flags at once. + * @param negative + * The value of the negative flag. + * @param zero + * The value of the zero flag. + */ + public void setFlags(boolean negative, boolean zero) { + flagNegative = negative; + flagZero = zero; + } + + /** Returns true if the carry flag is set, false otherwise. */ + public boolean isCarrySet() { + return flagCarry; + } } Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-17 18:11:39 UTC (rev 60) @@ -29,7 +29,7 @@ @Override public void initialise(Loader loader, int pc, int brk) { - registers.write(ARM_Registers.PC, pc); + registers.set(ARM_Registers.PC, pc); } } Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-17 18:11:39 UTC (rev 60) @@ -47,7 +47,7 @@ @Override public void initialise(Loader loader, int pc, int brk) { - registers.write(ARM_Registers.PC, pc); + registers.set(ARM_Registers.PC, pc); this.brk = brk; // initialize the stack Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java 2007-04-17 18:11:39 UTC (rev 60) @@ -15,7 +15,7 @@ } public int nextInt() { - return ps.registers.read(currentArgument++); + return ps.registers.get(currentArgument++); } public long nextLong() { Modified: src/org/binarytranslator/generic/decoder/DisassembledInstruction.java =================================================================== --- src/org/binarytranslator/generic/decoder/DisassembledInstruction.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/generic/decoder/DisassembledInstruction.java 2007-04-17 18:11:39 UTC (rev 60) @@ -1,7 +1,8 @@ package org.binarytranslator.generic.decoder; /** - * Represents a disassembled instruction. + * Represents an instruction, after it has been decoded by a disassembler. + * The instruction should be printable in the format of the target system's assembly language. * * @author Michael Baer */ Added: src/org/binarytranslator/generic/decoder/Interpreter.java =================================================================== --- src/org/binarytranslator/generic/decoder/Interpreter.java (rev 0) +++ src/org/binarytranslator/generic/decoder/Interpreter.java 2007-04-17 18:11:39 UTC (rev 60) @@ -0,0 +1,12 @@ +package org.binarytranslator.generic.decoder; + +public interface Interpreter { + + public interface Instruction { + + void execute(); + int getSuccessor(int pc); + } + + Instruction decode(int pc); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-16 21:28:29
|
Revision: 59 http://svn.sourceforge.net/pearcolator/?rev=59&view=rev Author: captain5050 Date: 2007-04-16 14:28:29 -0700 (Mon, 16 Apr 2007) Log Message: ----------- Fix planting of bad instructions. Handle TLS ELF sections Modified Paths: -------------- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/vmInterface/DBT_Trace.java Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-16 21:25:39 UTC (rev 58) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-16 21:28:29 UTC (rev 59) @@ -12,6 +12,7 @@ import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.generic.decoder.InstructionDecoder; +import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; @@ -750,7 +751,7 @@ public int translate(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc) { TODO(); - return -1; + return 0xEBADC0DE; } /** @@ -763,9 +764,12 @@ */ public static int translateInstruction(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc) { + System.err.println("Translating "+pc); X86_InstructionDecoder decoder = getDecoder(ps, pc); if (DBT_Options.debugInstr) { + System.err.println("Disassembling "+pc); System.err.println(decoder.disassemble(ps, pc)); + System.err.println("After disassembling "+pc); } return decoder.translate(translationHelper, ps, lazy, pc); } @@ -796,6 +800,29 @@ * A decoder that faults with a bad instruction exception */ class X86_BadInstructionDecoder extends X86_InstructionDecoder { + /** + * Get the decoder with upto four or five(X86_64) prefix decoders but + * currently no opcode or operands + */ + protected X86_InstructionDecoder getDecoder(ProcessSpace ps, int pc, + int offset, X86_Group1PrefixDecoder prefix1, + X86_Group2PrefixDecoder prefix2, X86_Group3PrefixDecoder prefix3, + X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { + return this; + } + /** + * Translate a single instruction + * @param translationHelper the object containing the translation sequence + * @param ps the process space of the translation + * @param pc the address of the instruction to translate + * @return the address of the next instruction or -1 if this instruction has + * branched to the end of the trace + */ + public int translate(X862IR translationHelper, ProcessSpace ps, + X86_Laziness lazy, int pc) { + translationHelper.plantThrowBadInstruction(lazy, pc); + return -1; + } } /** Modified: src/org/binarytranslator/generic/decoder/DecoderUtils.java =================================================================== --- src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-16 21:25:39 UTC (rev 58) +++ src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-16 21:28:29 UTC (rev 59) @@ -117,9 +117,9 @@ BadInstructionException.class).asClass(); VM_MethodReference badInstrKlassInitMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(badInstrKlass.getTypeRef(), VM_Atom - .findOrCreateAsciiAtom("<init>"), VM_Atom - .findOrCreateAsciiAtom("(I" + psTref.getName() + ")V")); + .findOrCreate(badInstrKlass.getTypeRef(), + VM_Atom.findOrCreateAsciiAtom("<init>"), + VM_Atom.findOrCreateAsciiAtom("(ILorg/binarytranslator/generic/os/process/ProcessSpace;)V")); badInstrKlassInitMethod = badInstrKlassInitMethRef.resolveInvokeSpecial(); VM_MethodReference recordUncaughtBranchMethRef = (VM_MethodReference) VM_MemberReference @@ -1218,62 +1218,57 @@ * the program counter of the bad instruction */ public void plantThrowBadInstruction(Laziness lazy, int pc) { - // There's a bug with this, so for now I'm just commenting it out :-( -- IAR - setReturnValueResolveLazinessAndBranchToFinish(lazy, - new OPT_IntConstantOperand(0xEBADC0DE)); - if (false) { - // Need to make sure that the PPC_ProcessSpace registers have - // the correct values before call to doSysCall(). - resolveLaziness(lazy); - spillAllRegisters(); + // Need to make sure that the PPC_ProcessSpace registers have + // the correct values before call to doSysCall(). + resolveLaziness(lazy); + spillAllRegisters(); - OPT_Operator newOperator; - OPT_TypeOperand typeOperand = new OPT_TypeOperand(badInstrKlass); - VM_TypeReference eTref = badInstrKlass.getTypeRef(); + OPT_Operator newOperator; + OPT_TypeOperand typeOperand = new OPT_TypeOperand(badInstrKlass); + VM_TypeReference eTref = badInstrKlass.getTypeRef(); - if (badInstrKlass.isInitialized() || badInstrKlass.isInBootImage()) { - newOperator = NEW; - } else { - newOperator = NEW_UNRESOLVED; - } + if (badInstrKlass.isInitialized() || badInstrKlass.isInBootImage()) { + newOperator = NEW; + } else { + newOperator = NEW_UNRESOLVED; + } - OPT_RegisterOperand eRef = gc.temps.makeTemp(eTref); + OPT_RegisterOperand eRef = gc.temps.makeTemp(eTref); - OPT_Instruction n = New.create(newOperator, eRef, typeOperand); - n.position = gc.inlineSequence; - n.bcIndex = DBT_Trace.BAD_INSTRUCTION_NEW; + OPT_Instruction n = New.create(newOperator, eRef, typeOperand); + n.position = gc.inlineSequence; + n.bcIndex = DBT_Trace.BAD_INSTRUCTION_NEW; - OPT_Operand psRef = gc.makeLocal(1, psTref); + appendInstructionToCurrentBlock(n); - OPT_Instruction c = Call.create(CALL, null, null, null, null, 3); + OPT_Operand psRef = gc.makeLocal(1, psTref); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL( - badInstrKlassInitMethod.getMemberRef().asMethodReference(), - badInstrKlassInitMethod); - Call.setParam(c, 0, eRef.copy()); // 'this' pointer in - // BadInstructionException.init - Call.setParam(c, 1, new OPT_IntConstantOperand(pc)); - Call.setParam(c, 2, psRef); - Call.setGuard(c, new OPT_TrueGuardOperand()); - Call.setMethod(c, methOp); - Call.setAddress(c, new OPT_AddressConstantOperand(badInstrKlassInitMethod - .getOffset())); - c.position = gc.inlineSequence; - c.bcIndex = DBT_Trace.BAD_INSTRUCTION_INIT; + OPT_Instruction c = Call.create(CALL, null, null, null, null, 3); - OPT_Instruction t = Athrow.create(ATHROW, eRef.copyRO()); - t.position = gc.inlineSequence; - t.bcIndex = DBT_Trace.BAD_INSTRUCTION_THROW; + OPT_MethodOperand methOp = OPT_MethodOperand.SPECIAL( + badInstrKlassInitMethod.getMemberRef().asMethodReference(), + badInstrKlassInitMethod); + Call.setParam(c, 0, eRef.copy()); // 'this' pointer in + // BadInstructionException.init + Call.setParam(c, 1, new OPT_IntConstantOperand(pc)); + Call.setParam(c, 2, psRef); + Call.setGuard(c, new OPT_TrueGuardOperand()); + Call.setMethod(c, methOp); + Call.setAddress(c, new OPT_AddressConstantOperand(badInstrKlassInitMethod + .getOffset())); + c.position = gc.inlineSequence; + c.bcIndex = DBT_Trace.BAD_INSTRUCTION_INIT; - appendInstructionToCurrentBlock(n); + appendInstructionToCurrentBlock(c); - appendInstructionToCurrentBlock(c); + OPT_Instruction t = Athrow.create(ATHROW, eRef.copyRO()); + t.position = gc.inlineSequence; + t.bcIndex = DBT_Trace.BAD_INSTRUCTION_THROW; - appendInstructionToCurrentBlock(t); + appendInstructionToCurrentBlock(t); - setReturnValueResolveLazinessAndBranchToFinish(lazy, - new OPT_IntConstantOperand(0xEBADC0DE)); - } + setReturnValueResolveLazinessAndBranchToFinish(lazy, + new OPT_IntConstantOperand(0xEBADC0DE)); } // -oO Trace helping methods Oo- Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-04-16 21:25:39 UTC (rev 58) +++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-04-16 21:28:29 UTC (rev 59) @@ -8,6 +8,7 @@ */ package org.binarytranslator.generic.memory; +import org.binarytranslator.DBT; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_Trace; import org.binarytranslator.vmInterface.TranslationHelper; @@ -436,8 +437,9 @@ case DBT_Trace.MEMORY_LOAD32: return load32.getMemberRef().asMethodReference(); default: - throw new Error("Error linking method at " + callAddress - + " for memory model " + this.getClass()); + DBT.write(callAddress); + DBT.fail("Trying to dynamic link inside a DBT trace for an unknown dynamic link location"); + return null; } } } Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-16 21:25:39 UTC (rev 58) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-04-16 21:28:29 UTC (rev 59) @@ -44,7 +44,7 @@ * Debug information * @param s string of debug information */ - private static void report(String s){ + private static void report(String s) { if (DBT_Options.debugLoader) { System.out.print("ELF Loader:"); System.out.println(s); @@ -63,10 +63,12 @@ * Do we need to byte swap multi-byte values? */ private final boolean needsBswap; + /** * File to read from */ RandomAccessFile rFile; + /** * Constructor * @param rFile file to read from @@ -76,19 +78,23 @@ this.rFile = rFile; this.needsBswap = needsBswap; } + /** * Byte swap a 32-bit integer */ - private static int bswap (int x) { - return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | (x >>> 24); + private static int bswap(int x) { + return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) + | (x >>> 24); } + /** * Byte swap a 16-bit integer */ - private static short bswap (short x) { - short result = (short)(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); + private static short bswap(short x) { + short result = (short) (((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); return result; } + /** * Read a 32bit int value */ @@ -96,6 +102,7 @@ int result = rFile.readInt(); return needsBswap ? bswap(result) : result; } + /** * Read a 16bit short value */ @@ -103,6 +110,7 @@ short result = rFile.readShort(); return needsBswap ? bswap(result) : result; } + /** * Seek to location from beginning of file */ @@ -120,12 +128,11 @@ * @param filename the program file name * @return process space containing loaded binary */ - public ProcessSpace readBinary(String filename) throws IOException - { + public ProcessSpace readBinary(String filename) throws IOException { report("Opening File: " + filename); RandomAccessFile rFile = new RandomAccessFile(filename, "r"); - elfHeader = new ELF_Header(rFile); //NB also sets up reader + elfHeader = new ELF_Header(rFile); // NB also sets up reader report("ELF header read successfully"); ProcessSpace ps = ProcessSpace.createProcessSpaceFromBinary(this); @@ -135,52 +142,50 @@ segmentHeaders = readHeaders(); report("Creating program segments"); - for(int i=0; i < segmentHeaders.length; i++){ + for (int i = 0; i < segmentHeaders.length; i++) { report("Creating: " + segmentHeaders[i]); segmentHeaders[i].create(ps); } int brk; - if(segmentHeaders.length > 1) { + if (segmentHeaders.length > 1) { brk = segmentHeaders[1].getEnd(); } else { - brk = segmentHeaders[0].getEnd(); + brk = segmentHeaders[0].getEnd(); } - report("Initialising the process space: "+ - "entry = 0x" + Integer.toHexString(elfHeader.getEntryPoint()) + - " brk = 0x" + Integer.toHexString(brk) - ); + report("Initialising the process space: " + "entry = 0x" + + Integer.toHexString(elfHeader.getEntryPoint()) + " brk = 0x" + + Integer.toHexString(brk)); ps.initialise(this, elfHeader.getEntryPoint(), brk); return ps; } - + /** - * Determine if the id array corresponds with the initial part of an - * ELF binary + * Determine if the id array corresponds with the initial part of an ELF + * binary * @param filename Name of the file to check * @return whether this is an ELF binary */ public static boolean conforms(String filename) { - + RandomAccessFile rFile = null; report("Testing is file is ELF: " + filename); - + try { rFile = new RandomAccessFile(filename, "r"); byte[] id = new byte[4]; rFile.read(id); - - return (id[0] == 0x7f) && (id[1] == 'E') && (id[2] == 'L') && (id[3] == 'F'); - } - catch (Exception e) { + + return (id[0] == 0x7f) && (id[1] == 'E') && (id[2] == 'L') + && (id[3] == 'F'); + } catch (Exception e) { return false; - } - finally { + } finally { try { rFile.close(); + } catch (Exception e) { } - catch(Exception e) {} } } @@ -188,9 +193,10 @@ * Read and construct the program segment headers */ private ELF_ProgramSegmentHeader[] readHeaders() throws IOException { - ELF_ProgramSegmentHeader segmentHeaders[] = new ELF_ProgramSegmentHeader[elfHeader.getNumberOfProgramSegmentHeaders()]; + ELF_ProgramSegmentHeader segmentHeaders[] = new ELF_ProgramSegmentHeader[elfHeader + .getNumberOfProgramSegmentHeaders()]; reader.seek(elfHeader.getProgramSegmentHeaderOffset()); - for(int i=0; i < segmentHeaders.length; i++) { + for (int i = 0; i < segmentHeaders.length; i++) { segmentHeaders[i] = new ELF_ProgramSegmentHeader(); } return segmentHeaders; @@ -202,6 +208,7 @@ public String getABIString() { return elfHeader.getABIString(); } + /** * Return the architecture (ISA) supported by this file */ @@ -215,13 +222,14 @@ public boolean isX86_ISA() { return elfHeader.isX86_ISA(); } + /** * Is the ELF's machine field PowerPC */ public boolean isPPC_ISA() { return elfHeader.isPPC_ISA(); } - + /** * Is this binary for the ARM architecture? */ @@ -235,13 +243,14 @@ public boolean isSysV_ABI() { return elfHeader.isSysV_ABI(); } + /** * Does this file support the Linux ABI? */ public boolean isLinuxABI() { return elfHeader.isLinuxABI(); } - + /** * Does this file support the ARM ABI? * @return @@ -268,6 +277,7 @@ * Size of ELF identity structure */ private static final int EI_NIDENT = 16; + /** * Backing store for identity structure: * {0x7f,'E','L','F',class,data,version,padding..} @@ -277,24 +287,30 @@ /** * ELF Magic numbers locations in identity */ - private static final int EI_MAG0 = 0, EI_MAG1 = 1, EI_MAG2 = 2, EI_MAG3 = 3; + private static final int EI_MAG0 = 0, EI_MAG1 = 1, EI_MAG2 = 2, + EI_MAG3 = 3; + /** * ELF magic values indicating an ELF file */ - private static final byte ELFMAG0 = 0x7f, ELFMAG1 = 'E', ELFMAG2 = 'L', ELFMAG3 = 'F'; + private static final byte ELFMAG0 = 0x7f, ELFMAG1 = 'E', ELFMAG2 = 'L', + ELFMAG3 = 'F'; /** * Location of class data in identity structure */ private static final int EI_CLASS = 4; + /** * ELF file is invalid */ private static final byte ELFCLASSNONE = 0; + /** * ELF file contains 32bit data */ private static final byte ELFCLASS32 = 1; + /** * ELF file contains 64bit data */ @@ -304,30 +320,39 @@ * Location of data information in identity structure */ private static final int EI_DATA = 5; + /** * Invalid data encoding */ private static final byte ELFDATANONE = 0; + /** * LSB or little-endian encoding N.B. not the native Java format */ private static final byte ELFDATA2LSB = 1; + /** * MSB or big-endian encoding N.B. the native Java format */ private static final byte ELFDATA2MSB = 2; + /** * Is this ELF MSB encoded? */ boolean isMSB() throws IOException { switch (e_ident[EI_DATA]) { - case ELFDATA2LSB: return false; - case ELFDATA2MSB: return true; - default: throw new IOException("Unrecognized data encoding"); + case ELFDATA2LSB: + return false; + case ELFDATA2MSB: + return true; + default: + throw new IOException("Unrecognized data encoding"); } } + /** - * Location of version data - should be EV_CURRENT as defined by the ELF header + * Location of version data - should be EV_CURRENT as defined by the ELF + * header */ private static final int EI_VERSION = 6; @@ -335,104 +360,133 @@ * Location of OS ABI data */ private static final int EI_OSABI = 7; + /** * UNIX System V ABI. */ private static final byte ELFOSABI_SYSV = 0; + /** * HP-UX ABI */ private static final byte ELFOSABI_HPUX = 1; + /** * NetBSD ABI */ private static final byte ELFOSABI_NETBSD = 2; + /** * Linux ABI */ private static final byte ELFOSABI_LINUX = 3; + /** * Solaris ABI */ private static final byte ELFOSABI_SOLARIS = 6; + /** * AIX ABI */ private static final byte ELFOSABI_AIX = 7; + /** * IRIX ABI */ private static final byte ELFOSABI_IRIX = 8; + /** * FreeBSD ABI */ private static final byte ELFOSABI_FREEBSD = 9; + /** * TRU64 UNIX ABI */ private static final byte ELFOSABI_TRU64 = 10; + /** * Novell Modesto */ private static final byte ELFOSABI_MODESTO = 11; + /** * Open BSD */ private static final byte ELFOSABI_OPENBSD = 12; + /** * Open VMS */ private static final byte ELFOSABI_OPENVMS = 13; + /** * Hewlett-Packard Non-Stop Kernel */ private static final byte ELFOSABI_NSK = 14; - + /** - * ARM ABI, probably using the ARM AAPCS. + * ARM ABI, probably using the ARM AAPCS. */ private static final byte ELFOSABI_ARM = 97; - + /** * Return the application binary interface (ABI) supported by this file */ String getABIString() { - switch(e_ident[EI_OSABI]) { - case ELFOSABI_SYSV: return "SysV"; - case ELFOSABI_HPUX: return "HP-UX"; - case ELFOSABI_NETBSD: return "NetBSD"; - case ELFOSABI_LINUX: return "Linux"; - case ELFOSABI_SOLARIS: return "Solaris"; - case ELFOSABI_AIX: return "AIX"; - case ELFOSABI_IRIX: return "IRIX"; - case ELFOSABI_FREEBSD: return "FreeBSD"; - case ELFOSABI_TRU64: return "TRU64"; - case ELFOSABI_MODESTO: return "Novell Modesto"; - case ELFOSABI_OPENBSD: return "OpenBSD"; - case ELFOSABI_OPENVMS: return "OpenVMS"; - case ELFOSABI_NSK: return "Hewlett-Packard Non-Stop Kernel"; - case ELFOSABI_ARM: return "ARM ABI"; + switch (e_ident[EI_OSABI]) { + case ELFOSABI_SYSV: + return "SysV"; + case ELFOSABI_HPUX: + return "HP-UX"; + case ELFOSABI_NETBSD: + return "NetBSD"; + case ELFOSABI_LINUX: + return "Linux"; + case ELFOSABI_SOLARIS: + return "Solaris"; + case ELFOSABI_AIX: + return "AIX"; + case ELFOSABI_IRIX: + return "IRIX"; + case ELFOSABI_FREEBSD: + return "FreeBSD"; + case ELFOSABI_TRU64: + return "TRU64"; + case ELFOSABI_MODESTO: + return "Novell Modesto"; + case ELFOSABI_OPENBSD: + return "OpenBSD"; + case ELFOSABI_OPENVMS: + return "OpenVMS"; + case ELFOSABI_NSK: + return "Hewlett-Packard Non-Stop Kernel"; + case ELFOSABI_ARM: + return "ARM ABI"; default: return "Unknown ELF ABI: " + e_ident[EI_OSABI]; } } + /** * Does this file support the SysV ABI? */ boolean isSysV_ABI() { return e_ident[EI_OSABI] == ELFOSABI_SYSV; } + /** * Does this file support the Linux ABI? */ boolean isLinuxABI() { return e_ident[EI_OSABI] == ELFOSABI_LINUX; } - + boolean isARM_ABI() { return e_ident[EI_OSABI] == ELFOSABI_ARM; } - + /** * Location of OS ABI version data */ @@ -450,10 +504,8 @@ // Identification is in bytes and therefore is endian agnostic rFile.read(e_ident); // Check magic is correct - if ((ELFMAG0 != e_ident[EI_MAG0]) || - (ELFMAG1 != e_ident[EI_MAG1]) || - (ELFMAG2 != e_ident[EI_MAG2]) || - (ELFMAG3 != e_ident[EI_MAG3])) { + if ((ELFMAG0 != e_ident[EI_MAG0]) || (ELFMAG1 != e_ident[EI_MAG1]) + || (ELFMAG2 != e_ident[EI_MAG2]) || (ELFMAG3 != e_ident[EI_MAG3])) { throw new IOException("Bad ELF file magic: " + rFile); } } @@ -470,19 +522,21 @@ String getABIString() { return identity.getABIString(); } + /** * Does this file support the SysV ABI? */ boolean isSysV_ABI() { return identity.isSysV_ABI(); } + /** * Does this file support the Linux ABI? */ boolean isLinuxABI() { return identity.isLinuxABI(); } - + /** * Does this file support the ARM ABI? */ @@ -494,95 +548,117 @@ * Object file type */ private short e_type; + /** * No file type */ private static final short ET_NONE = 0; + /** * Relocatable file */ private static final short ET_REL = 1; + /** * Executable file */ private static final short ET_EXEC = 2; + /** * Shared object file */ private static final short ET_DYN = 3; + /** * Core file */ private static final short ET_CORE = 4; + /** * Number of defined types */ private static final short ET_NUM = 5; + /** * Start of OS reserved region */ - private static final short ET_LOOS = (short)0xfe00; + private static final short ET_LOOS = (short) 0xfe00; + /** * End of OS reserved region */ - private static final short ET_HIOS = (short)0xfeff; + private static final short ET_HIOS = (short) 0xfeff; + /** * Start of processor-specific reserved region */ - private static final short ET_LOPROC = (short)0xff00; + private static final short ET_LOPROC = (short) 0xff00; + /** * End of processor-specific reserved region */ - private static final short ET_HIPROC = (short)0xffff; + private static final short ET_HIPROC = (short) 0xffff; /** * The required architecture (machine) for the object file */ private short e_machine; + /** * No machine */ private static final short EM_NONE = 0; + /** * AT&T WE 32100 */ - private static final short EM_M32 = 1 ; + private static final short EM_M32 = 1; + /** * SPARC */ private static final short EM_SPARC = 2; + /** * Intel 80386 */ private static final short EM_386 = 3; + /** * Motoral 68000 */ private static final short EM_68K = 4; + /** * Motorola 88000 */ private static final short EM_88K = 5; - /** + + /** * Intel 80860 */ private static final short EM_860 = 7; - /** + + /** * MIPS RS3000 */ private static final short EM_MIPS = 8; + /** * PowerPC */ private static final short EM_PPC = 20; + /** * ARM */ private static final short EM_ARM = 40; + /** * Alpha */ private static final short EM_ALPHA = 41; + /** * Sparc V9 */ @@ -594,37 +670,50 @@ boolean isX86_ISA() { return e_machine == EM_386; } + /** * Is the ELF's machine field PowerPC */ boolean isPPC_ISA() { return e_machine == EM_PPC; } - + /** * Is the elf binary for an ARM architecture? */ boolean isARM_ISA() { return e_machine == EM_ARM; } - + /** * Return the architecture (ISA) supported by this file */ public String getArchitectureString() { - switch(e_machine) { - case EM_M32: return "AT&T WE 32100"; - case EM_SPARC: return "SPARC"; - case EM_386: return "Intel 80386"; - case EM_68K: return "Motorola 68000"; - case EM_88K: return "Motorola 88000"; - case EM_860: return "Intel 80860"; - case EM_MIPS: return "MIPS RS3000"; - case EM_PPC: return "PowerPC"; - case EM_ARM: return "ARM"; - case EM_ALPHA: return "Alpha"; - case EM_SPARCV9: return "SPARC V9"; - default: return "Unknown architecture " + e_machine; + switch (e_machine) { + case EM_M32: + return "AT&T WE 32100"; + case EM_SPARC: + return "SPARC"; + case EM_386: + return "Intel 80386"; + case EM_68K: + return "Motorola 68000"; + case EM_88K: + return "Motorola 88000"; + case EM_860: + return "Intel 80860"; + case EM_MIPS: + return "MIPS RS3000"; + case EM_PPC: + return "PowerPC"; + case EM_ARM: + return "ARM"; + case EM_ALPHA: + return "Alpha"; + case EM_SPARCV9: + return "SPARC V9"; + default: + return "Unknown architecture " + e_machine; } } @@ -632,20 +721,23 @@ * Object file version */ private int e_version; + /** * Invalid version */ private static final int EV_NONE = 0; + /** - * Current version + * Current version */ private static final int EV_CURRENT = 1; /** - * Entry point virtual address. The virtual address to which the - * system first transfers control, thus starting the process. + * Entry point virtual address. The virtual address to which the system + * first transfers control, thus starting the process. */ private int e_entry; + /** * Return the entry point of the binary */ @@ -657,6 +749,7 @@ * Program header table file offset */ private int e_phoff; + /** * What is the offset in the file of the program headers */ @@ -683,6 +776,7 @@ * Program header table entry size */ private short e_phentsize; + /** * What's the size of a program segment header? */ @@ -694,17 +788,19 @@ * Program header table entry count */ private short e_phnum; + /** * How many program segments are in this ELF binary? */ - int getNumberOfProgramSegmentHeaders(){ - return e_phnum; + int getNumberOfProgramSegmentHeaders() { + return e_phnum; } /** * Section header table entry size */ private short e_shentsize; + /** * Section header table entry count */ @@ -713,7 +809,7 @@ /** * Section header table index */ - private short e_shstrndx; + private short e_shstrndx; /** * Construct/read ELF header @@ -723,33 +819,31 @@ // Identification is in bytes and therefore is endian agnostic identity = new ELF_Identity(rFile); // Set up reader to handle endianness for the rest of the file - reader = new ELF_BinaryReader(rFile,!identity.isMSB()); + reader = new ELF_BinaryReader(rFile, !identity.isMSB()); // Read in rest of header - e_type = reader.readShort(); + e_type = reader.readShort(); e_machine = reader.readShort(); e_version = reader.readInt(); - e_entry = reader.readInt(); - e_phoff = reader.readInt(); - e_shoff = reader.readInt(); - e_flags = reader.readInt(); - e_ehsize = reader.readShort(); + e_entry = reader.readInt(); + e_phoff = reader.readInt(); + e_shoff = reader.readInt(); + e_flags = reader.readInt(); + e_ehsize = reader.readShort(); e_phentsize = reader.readShort(); - e_phnum = reader.readShort(); + e_phnum = reader.readShort(); e_shentsize = reader.readShort(); - e_shnum = reader.readShort(); - e_shstrndx = reader.readShort(); - } - catch(IOException e) { + e_shnum = reader.readShort(); + e_shstrndx = reader.readShort(); + } catch (IOException e) { throw new Error(e); } } } /** - * Header representing a segment in the process (e.g. stack, heap, - * code aka text) in the ELF file. These are known as program - * header's in the ELF literature, but they don't represent - * programs, rather separate segments. + * Header representing a segment in the process (e.g. stack, heap, code aka + * text) in the ELF file. These are known as program header's in the ELF + * literature, but they don't represent programs, rather separate segments. */ @SuppressWarnings("unused") class ELF_ProgramSegmentHeader { @@ -757,98 +851,120 @@ * Type of the segment */ private final int p_type; + /** * Null header, contains no data and can be ignored */ private static final int PT_NULL = 0; + /** * A loadable segment */ private static final int PT_LOAD = 1; + /** * Segment containing dynamic linking information */ private static final int PT_DYNAMIC = 2; + /** * A segment containing a string to invoke as interpreter for this file */ private static final int PT_INTERP = 3; + /** * A segment describing the location and size of auxiliary information */ private static final int PT_NOTE = 4; + /** * A reserved segment type with unspecified semantics */ private static final int PT_SHLIB = 5; + /** - * A segment describing the ELF's header, present once before any - * loadable segments + * A segment describing the ELF's header, present once before any loadable + * segments */ private static final int PT_PHDR = 6; + /** * Thread local storage (TLS) segment */ private static final int PT_TLS = 7; + /** * Number of defined types */ private static final int PT_NUM = 8; + /** * Start of OS reserved segment types */ private static final int PT_LOOS = 0x60000000; + /** * SUN unwind table segment */ private static final int PT_SUNW_UNWIND = 0x6464e550; + /** * GCC .eh_frame_hdr segment */ private static final int PT_GNU_EH_FRAME = 0x6474e550; + /** * Indicates stack executability */ private static final int PT_GNU_STACK = 0x6474e551; + /** * Read-only after relocation */ private static final int PT_GNU_RELRO = 0x6474e552; + /** * Start of SUN reserved segments */ private static final int PT_LOSUNW = 0x6ffffffa; + /** - * The array element has the same attributes as a PT_LOAD element - * and is used to describe a .SUNW_bss section. + * The array element has the same attributes as a PT_LOAD element and is + * used to describe a .SUNW_bss section. */ private static final int PT_SUNWBSS = 0x6ffffffa; + /** - * Describes a process stack. Only one PT_SUNWSTACK element can - * exist. Only access permissions, as defined in the p_flags - * field, are meaningful. + * Describes a process stack. Only one PT_SUNWSTACK element can exist. Only + * access permissions, as defined in the p_flags field, are meaningful. */ private static final int PT_SUNWSTACK = 0x6ffffffb; + /** * Reserved for internal use by dtrace */ private static final int PT_SUNWDTRACE = 0x6ffffffc; + /** * Specifies hardware capability requirements */ private static final int PT_SUNWCAP = 0x6ffffffd; + /** * End of SUN reserved segments */ private static final int PT_HISUNW = 0x6fffffff; + /** * End of OS reserved segment types */ private static final int PT_HIOS = 0x6fffffff; + /** * Start of processor reserved segment types */ private static final int PT_LOPROC = 0x70000000; + /** * End of processor reserved segment types */ @@ -865,7 +981,7 @@ private final int p_vaddr; /** - * Corresponding physical addressed used by some systems + * Corresponding physical addressed used by some systems */ private final int p_paddr; @@ -883,32 +999,37 @@ * Read/Write/Execute flags for segment in memory */ private final int p_flags; + /** * Executable flag */ private static final int PF_X = 0x1; + /** * Writable flag */ private static final int PF_W = 0x2; + /** * Readable flag */ private static final int PF_R = 0x4; + /** * OS specific reserved bits */ private static final int PF_MASKOS = 0x0ff00000; + /** * Processor specific reserved bits */ private static final int PF_MASKPROC = 0xf0000000; /** - * This member gives the value to which the segments are aligned in - * memory and in the file. Values 0 and 1 mean no alignment is - * required. Otherwise, p_align should be a positive, integral - * power of 2, and p_vaddr should equal p_offset, modulo p_align. + * This member gives the value to which the segments are aligned in memory + * and in the file. Values 0 and 1 mean no alignment is required. Otherwise, + * p_align should be a positive, integral power of 2, and p_vaddr should + * equal p_offset, modulo p_align. */ private final int p_align; @@ -927,65 +1048,59 @@ // Move file onto next program segment header offset reader.rFile.skipBytes(elfHeader.getProgramSegmentHeaderSize() - 32); } + /** * Load/create the program segment */ void create(ProcessSpace ps) { - switch(p_type) { + switch (p_type) { case PT_NULL: // Null header, contains no data and can be ignored break; case PT_LOAD: // A loadable segment try { - createSegment(ps.memory, - reader.rFile, - p_offset, p_vaddr, - p_filesz, p_memsz, - (p_flags & PF_R) != 0, (p_flags & PF_W) != 0, (p_flags & PF_X) != 0); - } - catch(MemoryMapException e) { + createSegment(ps.memory, reader.rFile, p_offset, p_vaddr, p_filesz, + p_memsz, (p_flags & PF_R) != 0, (p_flags & PF_W) != 0, + (p_flags & PF_X) != 0); + } catch (MemoryMapException e) { throw new Error("Error in creating: " + this, e); } break; - case PT_NOTE: // A segment describing the location and size of auxiliary information + case PT_NOTE: // A segment describing the location and size of auxiliary + // information // ignore break; case PT_GNU_STACK: // A segment describing the permissions for the stack // ignore break; - case PT_INTERP: // A segment containing a string to invoke as interpreter for this file + case PT_TLS: // A segment describing thread local storage + // ignore for now + break; + case PT_INTERP: // A segment containing a string to invoke as interpreter + // for this file case PT_DYNAMIC: // Segment containing dynamic linking information - case PT_SHLIB: // A reserved segment type with unspecified semantics - case PT_PHDR: // A segment describing the ELF's header; present once before any loadable segments + case PT_SHLIB: // A reserved segment type with unspecified semantics + case PT_PHDR: // A segment describing the ELF's header; present once + // before any loadable segments default: throw new Error("Segment type " + toString() + " not yet supported"); } } - + /** * Create a segment - * - * @param memory - * The memory into which the segment is to be mapped. - * @param file - * file to read segment data from if file size != 0 - * @param offset - * file offset - * @param address - * location of segment - * @param filesize - * size of segment in file - * @param memsize - * size of segment in memory - * @param read - * is segment readable - * @param write - * is segment writable - * @param exec - * is segment executable + * @param memory The memory into which the segment is to be mapped. + * @param file file to read segment data from if file size != 0 + * @param offset file offset + * @param address location of segment + * @param filesize size of segment in file + * @param memsize size of segment in memory + * @param read is segment readable + * @param write is segment writable + * @param exec is segment executable */ - public void createSegment(Memory memory, RandomAccessFile file, long offset, int address, - int filesize, int memsize, boolean read, boolean write, boolean exec) - throws MemoryMapException { + public void createSegment(Memory memory, RandomAccessFile file, + long offset, int address, int filesize, int memsize, boolean read, + boolean write, boolean exec) throws MemoryMapException { // Sanity check if (memsize < filesize) { throw new Error("Segment memory size (" + memsize @@ -1024,12 +1139,13 @@ } /** - * Round the give value up so that it is at the beginning of the - * next aligned region + * Round the give value up so that it is at the beginning of the next + * aligned region */ private int truncateToNextAlignment(int x) { return ((x + p_align - 1) / p_align) * p_align; } + /** * Get the end of the segment */ @@ -1041,20 +1157,23 @@ * String representation of header */ public String toString() { - switch(p_type) { + switch (p_type) { case PT_NULL: return "Null segment header (ignored)"; case PT_LOAD: - return - "Loadable segment (offset=0x" + Long.toHexString(p_offset) + - ", address=0x"+ Integer.toHexString(p_vaddr)+ - ", file size=" + p_filesz + - ", memory size=" + p_memsz + - ", permissions=" + - (((p_flags & PF_R) != 0) ? 'r' : '-') + - (((p_flags & PF_W) != 0) ? 'w' : '-') + - (((p_flags & PF_X) != 0) ? 'x' : '-') + - ")"; + return "Loadable segment (offset=0x" + Long.toHexString(p_offset) + + ", address=0x" + Integer.toHexString(p_vaddr) + ", file size=" + + p_filesz + ", memory size=" + p_memsz + ", permissions=" + + (((p_flags & PF_R) != 0) ? 'r' : '-') + + (((p_flags & PF_W) != 0) ? 'w' : '-') + + (((p_flags & PF_X) != 0) ? 'x' : '-') + ")"; + case PT_TLS: + return "TLS segment (offset=0x" + Long.toHexString(p_offset) + + ", address=0x" + Integer.toHexString(p_vaddr) + ", file size=" + + p_filesz + ", memory size=" + p_memsz + ", permissions=" + + (((p_flags & PF_R) != 0) ? 'r' : '-') + + (((p_flags & PF_W) != 0) ? 'w' : '-') + + (((p_flags & PF_X) != 0) ? 'x' : '-') + ")"; case PT_NOTE: return "Note: segment containing auxiliary information"; case PT_INTERP: @@ -1068,18 +1187,15 @@ case PT_GNU_STACK: return "GNU stack executability"; default: - if((p_type > PT_LOPROC) && (p_type <= PT_HIPROC)) { + if ((p_type > PT_LOPROC) && (p_type <= PT_HIPROC)) { return "Processor specific segment 0x" + Integer.toHexString(p_type); - } - else if ((p_type > PT_LOOS) && (p_type <= PT_HIOS)) { - if((p_type > PT_LOSUNW) && (p_type <= PT_HISUNW)){ - return "Sun OS specific segment 0x" + Integer.toHexString(p_type); + } else if ((p_type > PT_LOOS) && (p_type <= PT_HIOS)) { + if ((p_type > PT_LOSUNW) && (p_type <= PT_HISUNW)) { + return "Sun OS specific segment 0x" + Integer.toHexString(p_type); + } else { + return "OS specific segment 0x" + Integer.toHexString(p_type); } - else { - return "OS specific segment 0x" + Integer.toHexString(p_type); - } - } - else { + } else { return "Unknown segment: 0x" + Integer.toHexString(p_type); } } Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-16 21:25:39 UTC (rev 58) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-16 21:28:29 UTC (rev 59) @@ -235,7 +235,7 @@ break; case BAD_INSTRUCTION_INIT: dynamicLink.set(DecoderUtils.badInstrKlassInitMethod.getMemberRef() - .asMethodReference(), JBC_invokevirtual); + .asMethodReference(), JBC_invokespecial); break; case MEMORY_STORE8: case MEMORY_STORE16: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-16 21:25:37
|
Revision: 58 http://svn.sourceforge.net/pearcolator/?rev=58&view=rev Author: captain5050 Date: 2007-04-16 14:25:39 -0700 (Mon, 16 Apr 2007) Log Message: ----------- Changes to reflect recent changes in the RVM Modified Paths: -------------- ext/org/jikesrvm/classloader/VM_Member.java ext/org/jikesrvm/compilers/opt/ir/OPT_BC2IR.java Modified: ext/org/jikesrvm/classloader/VM_Member.java =================================================================== --- ext/org/jikesrvm/classloader/VM_Member.java 2007-04-14 14:51:26 UTC (rev 57) +++ ext/org/jikesrvm/classloader/VM_Member.java 2007-04-16 21:25:39 UTC (rev 58) @@ -14,17 +14,19 @@ /** * A field or method of a java class. - * + * * @author Bowen Alpern * @author Dave Grove * @author Derek Lieber */ -public abstract class VM_Member extends VM_AnnotatedElement implements - VM_Constants, VM_ClassLoaderConstants { +public abstract class VM_Member extends VM_AnnotatedElement implements VM_Constants, VM_ClassLoaderConstants { + /** Initial value for a field offset - indicates field not laid out. */ + private static final int NO_OFFSET = Short.MIN_VALUE+1; + /** - * The class that declared this member, avaliable by calling getDeclaringClass - * once the class is loaded. + * The class that declared this member, avaliable by calling + * getDeclaringClass once the class is loaded. */ private final VM_TypeReference declaringClass; @@ -39,53 +41,46 @@ public final short modifiers; /** - * The signature is a string representing the generic type for this field or - * method declaration, may be null + * The signature is a string representing the generic type for this + * field or method declaration, may be null */ private final VM_Atom signature; /** - * The member's jtoc/obj/tib offset in bytes. Set by - * {@link VM_Class#resolve()} + * The member's jtoc/obj/tib offset in bytes. + * Set by {@link VM_Class#resolve()} */ protected int offset; /** - * NOTE: Only {@link VM_Class} is allowed to create an instance of a - * VM_Member. + * NOTE: Only {@link VM_Class} is allowed to create an instance of a VM_Member. * - * @param declaringClass - * the VM_TypeReference object of the class that declared this member - * @param memRef - * the canonical memberReference for this member. - * @param modifiers - * modifiers associated with this member. - * @param signature - * generic type of this member - * @param annotations - * array of runtime visible annotations + * @param declaringClass the VM_TypeReference object of the class that declared this member + * @param memRef the canonical memberReference for this member. + * @param modifiers modifiers associated with this member. + * @param signature generic type of this member + * @param annotations array of runtime visible annotations */ - protected VM_Member(VM_TypeReference declaringClass, - VM_MemberReference memRef, short modifiers, VM_Atom signature, - VM_Annotation[] annotations) { + protected VM_Member(VM_TypeReference declaringClass, VM_MemberReference memRef, + short modifiers, VM_Atom signature, + VM_Annotation[] annotations) { super(annotations); this.declaringClass = declaringClass; this.memRef = memRef; this.modifiers = modifiers; this.signature = signature; - this.offset = Short.MIN_VALUE + 1; // invalid value. Set to valid value - // during VM_Class.resolve() + this.offset = NO_OFFSET; // invalid value. Set to valid value during VM_Class.resolve() } - // --------------------------------------------------------------------// - // Section 1. // - // The following are available after class loading. // - // --------------------------------------------------------------------// + //--------------------------------------------------------------------// + // Section 1. // + // The following are available after class loading. // + //--------------------------------------------------------------------// /** - * Class that declared this field or method. Not available before the class is - * loaded. - */ + * Class that declared this field or method. Not available before + * the class is loaded. + */ @Uninterruptible public final VM_Class getDeclaringClass() { return declaringClass.peekResolvedType().asClass(); @@ -93,26 +88,26 @@ /** * Canonical member reference for this member. - */ + */ @Uninterruptible - public final VM_MemberReference getMemberRef() { + public final VM_MemberReference getMemberRef() { return memRef; } /** * Name of this member. - */ + */ @Uninterruptible - public final VM_Atom getName() { + public final VM_Atom getName() { return memRef.getName(); } /** - * Descriptor for this member. something like "I" for a field or "(I)V" for a - * method. - */ + * Descriptor for this member. + * something like "I" for a field or "(I)V" for a method. + */ @Uninterruptible - public final VM_Atom getDescriptor() { + public final VM_Atom getDescriptor() { return memRef.getDescriptor(); } @@ -124,47 +119,47 @@ } /** - * Get a unique id for this member. The id is the id of the canonical - * VM_MemberReference for this member and thus may be used to find the member - * by first finding the member reference. + * Get a unique id for this member. + * The id is the id of the canonical VM_MemberReference for this member + * and thus may be used to find the member by first finding the member reference. */ @Uninterruptible - public final int getId() { + public final int getId() { return memRef.getId(); } /* - * Define hashcode in terms of VM_Atom.hashCode to enable consistent hash - * codes during bootImage writing and run-time. + * Define hashcode in terms of VM_Atom.hashCode to enable + * consistent hash codes during bootImage writing and run-time. */ - public int hashCode() { + public int hashCode() { return memRef.hashCode(); } public final String toString() { return declaringClass + "." + getName() + " " + getDescriptor(); } - + /** * Usable from classes outside its package? - */ + */ public final boolean isPublic() { - return (modifiers & ACC_PUBLIC) != 0; + return (modifiers & ACC_PUBLIC) != 0; } /** * Usable only from this class? - */ - public final boolean isPrivate() { - return (modifiers & ACC_PRIVATE) != 0; + */ + public final boolean isPrivate() { + return (modifiers & ACC_PRIVATE) != 0; } - + /** * Usable from subclasses? - */ - public final boolean isProtected() { - return (modifiers & ACC_PROTECTED) != 0; - } + */ + public final boolean isProtected() { + return (modifiers & ACC_PROTECTED) != 0; + } /** * Get the member's modifiers. @@ -172,35 +167,42 @@ public final int getModifiers() { return modifiers; } + + /** + * Has the field been laid out in the object yet ? + * + * @return + */ + public final boolean hasOffset() { + return !(offset == NO_OFFSET); + } - // ------------------------------------------------------------------// - // Section 2. // - // The following are available after the declaring class has been // - // "resolved". // - // ------------------------------------------------------------------// + //------------------------------------------------------------------// + // Section 2. // + // The following are available after the declaring class has been // + // "resolved". // + //------------------------------------------------------------------// /** * Offset of this field or method, in bytes. * <ul> - * <li> For a static field: offset of field from start of jtoc - * <li> For a static method: offset of code object reference from start of - * jtoc - * <li> For a non-static field: offset of field from start of object - * <li> For a non-static method: offset of code object reference from start of - * tib + * <li> For a static field: offset of field from start of jtoc + * <li> For a static method: offset of code object reference from start of jtoc + * <li> For a non-static field: offset of field from start of object + * <li> For a non-static method: offset of code object reference from start of tib * </ul> - */ + */ @Uninterruptible - public final Offset getOffset() { - if (VM.VerifyAssertions) - VM._assert(declaringClass.isResolved()); + public final Offset getOffset() { + if (VM.VerifyAssertions) VM._assert(declaringClass.isResolved()); + if (VM.VerifyAssertions) VM._assert(offset != NO_OFFSET); return Offset.fromIntSignExtend(offset); } /** - * Only meant to be used by VM_ObjectModel.layoutInstanceFields. TODO: - * refactor system so this functionality is in the classloader package and - * this method doesn't have to be final. + * Only meant to be used by VM_ObjectModel.layoutInstanceFields. + * TODO: refactor system so this functionality is in the classloader package + * and this method doesn't have to be final. */ public final void setOffset(Offset off) { offset = off.toInt(); Modified: ext/org/jikesrvm/compilers/opt/ir/OPT_BC2IR.java =================================================================== --- ext/org/jikesrvm/compilers/opt/ir/OPT_BC2IR.java 2007-04-14 14:51:26 UTC (rev 57) +++ ext/org/jikesrvm/compilers/opt/ir/OPT_BC2IR.java 2007-04-16 21:25:39 UTC (rev 58) @@ -2686,7 +2686,12 @@ s.markAsNonPEI(); } for (int i = params.length - 1; i >= 0; i--) { - Call.setParam(s, i + numHiddenParams, pop(params[i])); + try { + Call.setParam(s, i + numHiddenParams, pop(params[i])); + } catch (OPT_OptimizingCompilerException.IllegalUpcast e) { + throw new Error("Illegal upcast creating call to " + meth + + " from " + gc.method + " argument " + i, e); + } } if (numHiddenParams != 0) { OPT_Operand ref = pop(); @@ -3211,6 +3216,15 @@ // Can't assert the following due to approximations by // OPT_ClassLoaderProxy.findCommonSuperclass // if (VM.VerifyAssertions) assertIsType(r, type); + if (VM.VerifyAssertions) { + if ((type == VM_TypeReference.JavaLangObject) && + (r.getType().isMagicType()) && + (r.getType() != VM_TypeReference.ObjectReference) && + !gc.method.getDeclaringClass().isMagicType() + ) { + throw new OPT_OptimizingCompilerException.IllegalUpcast(r.getType()); + } + } if (type.isLongType() || type.isDoubleType()) popDummy(); return r; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-14 14:51:25
|
Revision: 57 http://svn.sourceforge.net/pearcolator/?rev=57&view=rev Author: michael_baer Date: 2007-04-14 07:51:26 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Moved interface ARM_InstructionFactory into a package-visible interface, managed by ARM_InstructionDecoder. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java Removed Paths: ------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-14 14:47:54 UTC (rev 56) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-14 14:51:26 UTC (rev 57) @@ -243,6 +243,32 @@ } /** + * An interface to a factory class, which will create the actual object representations of the + * instruction classes decoded by {@link ARM_InstructionDecoder}. + * + * @param <T> + * The type of the object representations, that shall be created when an ARM instruction is decoded. + */ + interface ARM_InstructionFactory<T> { + T createDataProcessing(int instr); + T createSingleDataTransfer(int instr); + T createBlockDataTransfer(int instr); + T createIntMultiply(int instr); + T createLongMultiply(int instr); + T createSwap(int instr); + T createSoftwareInterrupt(int instr); + T createBranch(int instr); + T createBranchExchange(int instr); + T createCoprocessorDataTransfer(int instr); + T createCoprocessorDataProcessing(int instr); + T createCoprocessorRegisterTransfer(int instr); + T createMoveFromStatusRegister(int instr); + T createMoveToStatusRegister(int instr); + T createCountLeadingZeros(int instr); + T createUndefinedInstruction(int instr); + } + + /** * A default implementation of the ARM instruction factory, which will create the * appropriate classes from the {@link ARM_Instructions} namespace. */ Deleted: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java 2007-04-14 14:47:54 UTC (rev 56) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java 2007-04-14 14:51:26 UTC (rev 57) @@ -1,20 +0,0 @@ -package org.binarytranslator.arch.arm.decoder; - -public interface ARM_InstructionFactory<T> { - T createDataProcessing(int instr); - T createSingleDataTransfer(int instr); - T createBlockDataTransfer(int instr); - T createIntMultiply(int instr); - T createLongMultiply(int instr); - T createSwap(int instr); - T createSoftwareInterrupt(int instr); - T createBranch(int instr); - T createBranchExchange(int instr); - T createCoprocessorDataTransfer(int instr); - T createCoprocessorDataProcessing(int instr); - T createCoprocessorRegisterTransfer(int instr); - T createMoveFromStatusRegister(int instr); - T createMoveToStatusRegister(int instr); - T createCountLeadingZeros(int instr); - T createUndefinedInstruction(int instr); -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-14 14:48:00
|
Revision: 56 http://svn.sourceforge.net/pearcolator/?rev=56&view=rev Author: michael_baer Date: 2007-04-14 07:47:54 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Added more JavaDoc, created a default implementation of ARM_InstructionFactory and renamed ARM_InstructionDecoders to ARM_Instructions. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java Removed Paths: ------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-14 13:55:41 UTC (rev 55) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-14 14:47:54 UTC (rev 56) @@ -1,23 +1,23 @@ package org.binarytranslator.arch.arm.decoder; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Instruction; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.BlockDataTransfer; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Branch; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.BranchExchange; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorDataProcessing; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorDataTransfer; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorRegisterTransfer; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CountLeadingZeros; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.DataProcessing; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.IntMultiply; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.LongMultiply; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.MoveFromStatusRegister; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.MoveToStatusRegister; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.OperandWrapper; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.SingleDataTransfer; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.SoftwareInterrupt; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Swap; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Instruction.Condition; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.BlockDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Branch; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.BranchExchange; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorDataProcessing; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorRegisterTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CountLeadingZeros; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.IntMultiply; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.LongMultiply; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.MoveFromStatusRegister; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.MoveToStatusRegister; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.SingleDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.SoftwareInterrupt; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Swap; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.generic.decoder.DisassembledInstruction; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -43,8 +43,11 @@ public final static DisassembledInstruction disassemble(int address, ProcessSpace ps) { - int instr = ps.memory.loadInstruction32(address); + int binaryInstruction = ps.memory.loadInstruction32(address); + Instruction decodedInstruction = ARM_InstructionDecoder.decode(binaryInstruction); + DisassemblingVisitor disassembler = new DisassemblingVisitor(address); + decodedInstruction.visit(disassembler); return disassembler.result; } @@ -59,7 +62,7 @@ * @return A human-readable version of the given instruction. */ final static DisassembledInstruction disassemble( - ARM_InstructionDecoders.Instruction instruction) { + ARM_Instructions.Instruction instruction) { DisassemblingVisitor disassembler = new DisassemblingVisitor(); instruction.visit(disassembler); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-14 13:55:41 UTC (rev 55) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-14 14:47:54 UTC (rev 56) @@ -1,6 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.DBT; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; /** * This class decodes an ARM instruction and uses a user-supplied ARM_InstructionFactory to create a class @@ -17,7 +18,48 @@ */ public class ARM_InstructionDecoder { + /** This static field caches the default {@link ARM_InstructionFactory} implementation, which is used by {@link #decode(int)}. + * It is being lazily initialized once it is used for the first time. */ + private static DefaultFactory _defaultFactory; + /** + * Decodes a given ARM instruction and returns an object representation of it. + * @param instruction + * A binary ARM instruction, that is to be decoded. + * @return + * A version of the instruction, which has been decoded into an instance of {@link Instruction}. + * Use the {@link Instruction#visit(ARM_InstructionVisitor)} method to further interact with the + * returned instance. + */ + public static Instruction decode(int instruction) { + if (_defaultFactory == null) + _defaultFactory = new DefaultFactory(); + + return decode(instruction, _defaultFactory); + } + + /** + * Decodes a binary ARM instruction. This method will use the supplied {@link ARM_InstructionFactory} + * to create an object representation of the decoded instruction. + * @param <T> + * The return type depends on whatever the {@link ARM_InstructionFactory} actually creates. + * @param instruction + * A binary representation of the instruction that is to be decoded. + * @param factory + * A factory, that will create object instances of the instruction. + * @return + * An object representation of the decoded instruction. + */ + static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { + if (getBit(instruction, 27)) { + return decode_1xx(instruction, factory); + } + else { + return decode_0xx(instruction, factory); + } + } + + /** * Checks if a bit is set within a word. * @param word * The word that is being examined. @@ -31,15 +73,6 @@ DBT._assert(bit >= 0 && bit <= 31); return (word & (1 << bit)) != 0; } - - public static <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 27)) { - return decode_1xx(instr, factory); - } - else { - return decode_0xx(instr, factory); - } - } private static <T> T decode_0xx(int instr, ARM_InstructionFactory<T> factory) { if ((instr & 0xF0000000) == 0xF0000000) { @@ -208,4 +241,76 @@ } } } + + /** + * A default implementation of the ARM instruction factory, which will create the + * appropriate classes from the {@link ARM_Instructions} namespace. + */ + static class DefaultFactory implements ARM_InstructionFactory<ARM_Instructions.Instruction> { + + public Instruction createBlockDataTransfer(int instr) { + return new BlockDataTransfer(instr); + } + + public Instruction createBranch(int instr) { + return new Branch(instr); + } + + public Instruction createBranchExchange(int instr) { + return new BranchExchange(instr); + } + + public Instruction createCoprocessorDataProcessing(int instr) { + return new CoprocessorDataProcessing(instr); + } + + public Instruction createCoprocessorDataTransfer(int instr) { + return new CoprocessorDataTransfer(instr); + } + + public Instruction createCoprocessorRegisterTransfer(int instr) { + return new CoprocessorRegisterTransfer(instr); + } + + public Instruction createCountLeadingZeros(int instr) { + return new CountLeadingZeros(instr); + } + + public Instruction createDataProcessing(int instr) { + return new DataProcessing(instr); + } + + public Instruction createIntMultiply(int instr) { + return new IntMultiply(instr); + } + + public Instruction createLongMultiply(int instr) { + return new LongMultiply(instr); + } + + public Instruction createMoveFromStatusRegister(int instr) { + return new MoveFromStatusRegister(instr); + } + + public Instruction createMoveToStatusRegister(int instr) { + return new MoveToStatusRegister(instr); + } + + public Instruction createSingleDataTransfer(int instr) { + return new SingleDataTransfer(instr); + } + + public Instruction createSoftwareInterrupt(int instr) { + return new SoftwareInterrupt(instr); + } + + public Instruction createSwap(int instr) { + return new Swap(instr); + } + + public Instruction createUndefinedInstruction(int instr) { + return null; + } + + } } Deleted: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-14 13:55:41 UTC (rev 55) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-14 14:47:54 UTC (rev 56) @@ -1,1195 +0,0 @@ -package org.binarytranslator.arch.arm.decoder; - -import org.binarytranslator.DBT; - -/** - * In the ARM decoder model, the decoding and usage (translating/interpreting/disassembling) of instructions - * is strictly separated. This class provides a namespace for all decoder classes. A decoder works like a - * mask than can be put upon a binary instruction to look at the different fields within that instruction. - * - * Application might derive from these decoders to implement instruction-specific functionality. - * Then, implement a version of the generic {@link ARM_InstructionFactory} interface, which returns - * your derived classes and pass it to the {@link ARM_InstructionDecoder} to let it create instances of - * your class from binary instructions. - * - * @author Michael Baer - * - */ -public class ARM_InstructionDecoders { - - /** - * Checks if a bit is set within a word. - * @param word - * The word that is being examined. - * @param bit - * The number of the bit that is to be checked, starting from zero. - * @return - * True, if the given bit is set within the word, false otherwise. - */ - private static final boolean getBit(int word, int bit) { - if (DBT.VerifyAssertions) - DBT._assert(bit >= 0 && bit <= 31); - return (word & (1 << bit)) != 0; - } - - /** - * Extracts a subsequence of bits from a word. - * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. - * @param word - * The word that is to be examined. - * @param from - * The first bit (starting from 0) that is to be extracted. - * @param to - * The last bit (starting from 0) that is to be extracted from the word. - * @return - * A zero-based version of the bit sequence. - */ - private static final int getBits(int word, int from, int to) { - if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to <= 31); - return (word & ((1 << (to + 1)) - 1)) >> from; - } - - /** - * Sign extends a given value. - * @param value - * The value to sign extends. - * @param bitsUsed - * The number bits used within this values. - * @return - * A sign extended value. - */ - public static int signExtend(int value, int bitsUsed) { - return (value << (32 - bitsUsed)) >> (32 - bitsUsed); - } - - /** A base class for all (conditional) ARM instructions. */ - public abstract static class Instruction { - - public enum Condition { - EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV - } - - /** @see #getCondition() */ - protected final Condition condition; - - private Instruction(int instr) { - condition = Condition.values()[(byte) getBits(instr, 28, 31)]; - } - - /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ - public final Condition getCondition() { - return condition; - } - - @Override - public String toString() { - return ARM_Disassembler.disassemble(this).asString(); - } - - /** All instruction classes are meant to implement the visitor pattern. This is the pattern's visit method. */ - public abstract void visit(ARM_InstructionVisitor visitor); - } - - /** Base class for most instructions that use two registers. */ - private abstract static class TwoRegistersTemplate extends Instruction { - - /** @see #getRn() */ - protected final byte Rn; - - /** @see #getRd() */ - protected final byte Rd; - - public TwoRegistersTemplate(int instr) { - super(instr); - - Rd = (byte) getBits(instr, 12, 15); - Rn = (byte) getBits(instr, 16, 19); - } - - /** Returns the number of the operation's destination register, starting from 0.*/ - public final byte getRd() { - return Rd; - } - - /** Returns the number of the operation's first operand register, starting from 0.*/ - public final byte getRn() { - return Rn; - } - } - - /** Base class for most instructions that use three registers. */ - private abstract static class ThreeRegistersTemplate extends - TwoRegistersTemplate { - - /** @see #getRm() */ - protected final byte Rm; - - public ThreeRegistersTemplate(int instr) { - super(instr); - - Rm = (byte) getBits(instr, 0, 3); - } - - /** Returns the number of the second operand register, starting from 0.*/ - public final byte getRm() { - return Rm; - } - } - - /** Base class for multiply operations. */ - protected abstract static class MultiplyTemplate - extends ThreeRegistersTemplate { - - /** @see #updateConditionCodes() */ - protected final boolean updateConditionCodes; - - /** @see #accumulate() */ - protected final boolean accumulate; - - /** @see #getRs() */ - protected final byte Rs; - - protected MultiplyTemplate(int instr) { - super(instr); - - updateConditionCodes = getBit(instr, 20); - accumulate = getBit(instr, 21); - Rs = (byte) getBits(instr, 8, 11); - } - - /** Returns true, if the condition codes shall be updated by the result of this operation. */ - public final boolean updateConditionCodes() { - return updateConditionCodes; - } - - /** Returns true, if this is the accumulate version of the instruction. */ - public final boolean accumulate() { - return accumulate; - } - - /** Returns the register number of the Rs operand register. */ - public final byte getRs() { - return Rs; - } - } - - /** Base class for coprocessor instructions. */ - protected static abstract class CoprocessorTemplate extends Instruction { - - /** This is a register id, which can either refer to the CPU or the coprocessor, depending on the instruction. */ - protected final byte Rd; - - /** This is a register id, which can either refer to the CPU or the coprocessor, depending on the instruction. */ - protected final byte Rn; - - /** @see #getCoprocessorNumber() */ - protected final byte cpNum; - - public CoprocessorTemplate(int instr) { - super(instr); - - cpNum = (byte) getBits(instr, 8, 11); - Rd = (byte) getBits(instr, 12, 15); - Rn = (byte) getBits(instr, 16, 19); - } - - /** Returns the coprocessor that shall process this instruction */ - public final byte getCoprocessorNumber() { - return cpNum; - } - } - - /** Represents an operand, which might either be an immediate value, a register (shifted by an immediate) or a register shifted by a register. */ - public abstract static class OperandWrapper { - - /** Describes the type of the operand. */ - public enum Type { - Immediate, - PcRelative, - Register, - ImmediateShiftedRegister, - RegisterShiftedRegister, - } - - /** Describes a type of shift, in case the operand is supposed to be shifted. */ - public enum ShiftType { - LSL, - LSR, - ASR, - ROR, - RRE - } - - /** Creates an operand wrapper around a 12 bit immediate value. */ - public static OperandWrapper createImmediate(int immediate) { - return new ImmediateOperand(immediate); - } - - /** Creates an operand wrapper that is a normal register value. */ - public static OperandWrapper createRegister(byte register) { - return new RegisterOperand(register); - } - - /** Creates an operand wrapper representing an offset to the pc.*/ - public static OperandWrapper createPcRelative(int offset) { - return new PcRelativeOperand(offset); - } - - /** Creates an operand wrapper, that represents a register shifted by an immediate or a register, depending on the instruction. */ - public static OperandWrapper decodeShiftedRegister(int instr) { - ShiftType shift = ShiftType.values()[getBits(instr, 5, 6)]; - byte shiftedRegister = (byte) (instr & 0xF); - - if (getBit(instr, 4)) { - //shift by a register - byte shiftingRegister = (byte)getBits(instr, 8, 11); - return new RegisterShiftRegisterOperand(shiftedRegister, shift, shiftingRegister); - } - else { - //shift by an immediate - byte immediate = (byte)getBits(instr, 7, 11); - - if (immediate == 0) { - //if we are shifting by zero, we might forget about the shift - if (shift == ShiftType.ROR) { - //However, if the shift type was RotateRight, then ARM meant do a RotateRightExtend by 1 - return new RegisterShiftImmediateOperand(shiftedRegister, shift, (byte)1); - } - else { - //Otherwise, really forget about the shifting - return new RegisterOperand(shiftedRegister); - } - } - else { - return new RegisterShiftImmediateOperand(shiftedRegister, shift, immediate); - } - } - } - - /** Returns the type of the operand that this class is actually representing. */ - public abstract Type getType(); - - /** Returns the immediate, which is the 2nd operand of this instruction. Make sure that hasImmediate is true before calling this. */ - public int getImmediate() { - throw new RuntimeException("Invalid call on an operand wrapper."); - } - - /** Returns an offset that is to be applied to a register. */ - public int getOffset() { - throw new RuntimeException("Invalid call on an operand wrapper."); - } - - /** Returns the number of the register, which forms the 2nd operand. Only applicable if {@link #hasImmediate()} is false.*/ - public byte getRegister() { - throw new RuntimeException("Invalid call on an operand wrapper."); - } - - /** Returns the number of the register which is performing the shift. */ - public byte getShiftingRegister() { - throw new RuntimeException("Invalid call on an operand wrapper."); - } - - /** Returns the amount by which a value is supposed to be shifted*/ - public byte getShiftAmount() { - throw new RuntimeException("Invalid call on an operand wrapper."); - } - - /** Returns the shift type, in case this Operand includes shifting. */ - public ShiftType getShiftType() { - throw new RuntimeException("Invalid call on an operand wrapper."); - } - - /** Represents an immediate value operand. */ - protected static class ImmediateOperand extends OperandWrapper { - - /** @see #getImmediate() */ - protected final int immediate; - - protected ImmediateOperand(int immediate) { - this.immediate = immediate; - } - - @Override - public int getImmediate() { - return immediate; - } - - @Override - public Type getType() { - return Type.Immediate; - } - } - - protected static class PcRelativeOperand extends OperandWrapper { - - protected final int offset; - - protected PcRelativeOperand(int offset) { - this.offset = offset; - } - - @Override - public byte getRegister() { - return 15; - } - - @Override - public int getOffset() { - return offset; - } - - @Override - public Type getType() { - return Type.PcRelative; - } - } - - /** Represents a register operand. */ - protected static class RegisterOperand extends OperandWrapper { - - /** @see #getRegister() */ - protected final byte register; - - protected RegisterOperand(byte register) { - this.register = register; - } - - @Override - public byte getRegister() { - return register; - } - - @Override - public Type getType() { - return Type.Register; - } - } - - /** Represents an operand, which is a register shifted by an immediate value. */ - protected static class RegisterShiftImmediateOperand extends RegisterOperand { - - /** @see #getShiftType() */ - protected final ShiftType shiftType; - - /** @see #getShiftAmount() */ - protected final byte shiftAmount; - - protected RegisterShiftImmediateOperand(byte register, ShiftType shift, byte shiftAmount) { - super(register); - this.shiftAmount = shiftAmount; - this.shiftType = shift; - } - - @Override - public Type getType() { - return Type.ImmediateShiftedRegister; - } - - @Override - public byte getShiftAmount() { - return shiftAmount; - } - - @Override - public ShiftType getShiftType() { - return shiftType; - } - } - - /** Returns an operand, which is a register shifted by a register. */ - protected static class RegisterShiftRegisterOperand extends RegisterOperand { - - /** @see #getShiftType() */ - protected final ShiftType shiftType; - - /** @see #getShiftingRegister() */ - protected final byte shiftingRegister; - - protected RegisterShiftRegisterOperand(byte shiftedRegister, ShiftType shift, byte shiftingRegister) { - super(shiftedRegister); - this.shiftType = shift; - this.shiftingRegister = shiftingRegister; - } - - @Override - public Type getType() { - return Type.RegisterShiftedRegister; - } - - @Override - public byte getShiftingRegister() { - return shiftingRegister; - } - - @Override - public ShiftType getShiftType() { - return shiftType; - } - } - } - - /** Represents a Data Processing instruction. */ - public static class DataProcessing extends - TwoRegistersTemplate { - - /** A list of possible DataProcessing operations. The list is orded in ascendingly, with the - * first opcode corresponding to opcode 0 (zero) in the opcode field of an ARM data processing - * instruction. */ - public enum Opcode { - AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN - } - - /** @see #hasSetConditionCodes() */ - protected final boolean updateConditionCodes; - - /** @see #getOpcode() */ - protected final Opcode opcode; - - /** @see #getOperand2() */ - protected final OperandWrapper operand2; - - public DataProcessing(int instr) { - super(instr); - - updateConditionCodes = getBit(instr, 20); - opcode = Opcode.values()[(byte) getBits(instr, 21, 24)]; - - if (getBit(instr, 25)) - operand2 = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); - else - operand2 = OperandWrapper.decodeShiftedRegister(instr); - } - - /** Returns the opcode, that specifies the data processing operation, which is to be performed. */ - public final Opcode getOpcode() { - return opcode; - } - - /** Returns true if the condition codes shall be set by this operation, false otherwise. */ - public final boolean updateConditionCodes() { - return updateConditionCodes; - } - - /** Returns the 2nd operand of this data processing instruction. */ - public final OperandWrapper getOperand2() { - return operand2; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a LDR/SDR instruction. */ - public static class SingleDataTransfer extends - TwoRegistersTemplate { - - public enum TransferSize { - Byte, - HalfWord, - Word - } - - /** @see #preIndexing() */ - protected final boolean preIndexing; - - /** @see #positiveOffset() */ - protected final boolean positiveOffset; - - /** @see #signExtend() */ - protected final boolean signExtend; - - /** @see #forceUserMode() */ - protected final boolean forceUserMode; - - /** @see #getSize() */ - protected final TransferSize size; - - /** @see #writeBack() */ - protected final boolean writeBack; - - /** @see #isLoad() */ - protected final boolean isLoad; - - /** @see #getOffset() */ - protected final OperandWrapper offset; - - public SingleDataTransfer(int instr) { - super(instr); - - preIndexing = getBit(instr, 24); - positiveOffset = getBit(instr, 23); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); - - if (getBit(instr, 26)) { - //this is an unsigned byte or word transfer - signExtend = false; - - forceUserMode = !preIndexing && writeBack; - - if (getBit(instr, 22)) - size = TransferSize.Byte; - else - size = TransferSize.Word; - - if (getBit(instr, 25)) - offset = OperandWrapper.createImmediate(instr & 0xFF); - else - offset = OperandWrapper.decodeShiftedRegister(instr); - } - else { - //this is a byte or half-word transfer - if (getBit(instr, 5)) - size = TransferSize.HalfWord; - else - size = TransferSize.Byte; - - signExtend = getBit(instr, 6); - forceUserMode = false; - - if (getBit(instr, 22)) { - //immediate offset - offset = OperandWrapper.createImmediate((getBits(instr, 8, 11) << 4) | (instr & 0xF)); - } - else { - //register offset - offset = OperandWrapper.createRegister((byte)(instr & 0xF)); - } - - //The decoder should make sure that we're never being called with this combination - if (DBT.VerifyAssertions) DBT._assert(!signExtend || isLoad); - } - } - - /** Returns true, if this memory access shall be treated as if it had been done in user mode. */ - public final boolean forceUserMode() { - return forceUserMode; - } - - /** Returns true, if the loaded/stored value shall be signed-extended.*/ - public final boolean signExtend() { - return signExtend; - } - - /** Returns the number of bytes that have to be transferred. */ - public final TransferSize getSize() { - return size; - } - - /** True if this is a LDM instruction, false if it is a STM instruction. */ - public final boolean isLoad() { - return isLoad; - } - - /** Returns true, if the offset from the base register (see {@link #getRn()} is positive, false if it is negative. */ - public final boolean positiveOffset() { - return positiveOffset; - } - - /** True if the base register shall be changed before the transfer, otherwise changed it after the transfer. */ - public final boolean preIndexing() { - return preIndexing; - } - - /** True if the incremented base register shall be persisted after this instruction. */ - public final boolean writeBack() { - return writeBack; - } - - /** Returns the offset operand for this data processing instruction. */ - public final OperandWrapper getOffset() { - return offset; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a normal (not long) multiply instruction. */ - public static class IntMultiply extends MultiplyTemplate { - - protected IntMultiply(int instr) { - super(instr); - - if (DBT.VerifyAssertions) DBT._assert(accumulate || Rn == 0); - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a long multiply instruction. */ - public static class LongMultiply extends MultiplyTemplate { - - /** @see #isUnsigned() */ - protected final boolean unsigned; - - public LongMultiply(int instr) { - super(instr); - - unsigned = getBit(instr, 22); - } - - /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ - public final byte getRdHigh() { - return Rd; - } - - /** Long multiplication stores its result in two registers. This function gets the register which receives the low int. */ - public final byte getRdLow() { - return Rn; - } - - /** Returns true, if this is an unsigned multiplication or false if it is a signed multiplication. */ - public final boolean isUnsigned() { - return unsigned; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a SWP/SWPB instruction. */ - public static class Swap extends ThreeRegistersTemplate { - - /** @see #swapByte() */ - protected final boolean swapByte; - - public Swap(int instr) { - super(instr); - swapByte = getBit(instr, 22); - } - - /** Returns true, if a byte shall be swapped or false, if an int (32 bit) shall be swapped. */ - public final boolean swapByte() { - return swapByte; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a LDM/STM instruction. */ - public static class BlockDataTransfer extends Instruction { - - /** @see #postIndexing() */ - protected final boolean postIndexing; - - /** @see #incrementBase() */ - protected final boolean incrementBase; - - /** @see #forceUser() */ - protected final boolean forceUser; - - /** @see #writeBack() */ - protected final boolean writeBack; - - /** @see #isLoad() */ - protected final boolean isLoad; - - /** @see #getBaseRegister() */ - protected final byte baseRegister; - - /** Contains a set bit at position N if rN should be transferred using this instruction.*/ - protected final int registerList; - - public BlockDataTransfer(int instr) { - super(instr); - - postIndexing = getBit(instr, 24); - incrementBase = getBit(instr, 23); - forceUser = getBit(instr, 22); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); - baseRegister = (byte) getBits(instr, 16, 19); - registerList = instr; - } - - /** @return True if register r should be transferred using this instruction. */ - public final boolean transferRegister(int r) { - if (DBT.VerifyAssertions) - DBT._assert(r >= 0 && r < 16); - - return getBit(registerList, r); - } - - /** True if the base register shall be changed after each single transfer, otherwise changed it before each transfer. */ - public final boolean postIndexing() { - return postIndexing; - } - - /** True if the base register shall be incremented, false if it should be decremented. */ - public final boolean incrementBase() { - return incrementBase; - } - - /** Force user mode during this instruction? */ - public final boolean forceUser() { - return forceUser; - } - - /** True if the incremented base register shall be persisted after this instruction. */ - public final boolean writeBack() { - return writeBack; - } - - /** True if this is a LDM instruction, false if it is a STM instruction. */ - public final boolean isLoad() { - return isLoad; - } - - /** The number of the register which will provides the base address for this LDM/STM instruction. */ - public final byte getBaseRegister() { - return baseRegister; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a SWI instruction*/ - public static class SoftwareInterrupt extends Instruction { - - /** @see #getInterruptNumber() */ - protected final int interruptNumber; - - public SoftwareInterrupt(int instr) { - super(instr); - interruptNumber = instr & 0xFFFFFF; - } - - /** Returns the interrupt that is being called. The value is taken from the instruction's comment field. */ - public final int getInterruptNumber() { - return interruptNumber; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a branch instruction. */ - public static class Branch extends Instruction { - - /** @see #link() */ - protected final boolean link; - - /** @see #getOffset() */ - protected final int offset; - - public Branch(int instr) { - super(instr); - link = getBit(instr, 24); - offset = instr & 0xFFF; - } - - /** Should the current PC be put into the lr? */ - public final boolean link() { - return link; - } - - /** The offset of the target address to the PC */ - public final int getOffset() { - return offset; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a BX instruction set */ - public static class BranchExchange extends Instruction { - - /** @see #target() */ - protected final OperandWrapper target; - - /** @see #link() */ - protected final boolean link; - - public BranchExchange(int instr) { - super(getBit(instr, 27) ? 0xE0000000 : instr); - - if (getBit(instr, 27)) { - //this is the immediate version of a BLX - link = true; - - //sign extend jump target - int jumpTarget = signExtend(instr & 0xFFF, 24) << 2; - - //are we addressing a half-byte? - if (getBit(instr, 24)) - jumpTarget += 2; - - target = OperandWrapper.createPcRelative(jumpTarget); - } - else { - link = getBit(instr, 5); - target = OperandWrapper.createRegister((byte) (instr & 0xF)); - } - } - - /** Returns, whether the return address for this jump shall be put into the lr. */ - public final boolean link() { - return link; - } - - /** Returns the address to which this instruction will branch. */ - public final OperandWrapper target() { - return target; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a LDC/STC instruction. */ - public static class CoprocessorDataTransfer extends CoprocessorTemplate { - - /** @see #getOffset() */ - protected final int offset; - - /** @see #preIndexing() */ - protected final boolean preIndexing; - - /** @see #largeTransfer() */ - protected final boolean largeTransfer; - - /** @see #writeBack() */ - protected final boolean writeBack; - - /** @see #isLoad() */ - protected final boolean isLoad; - - public CoprocessorDataTransfer(int instr) { - super(instr); - - preIndexing = getBit(instr, 24); - largeTransfer = getBit(instr, 22); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); - - if (!writeBack && !preIndexing) { - offset = instr & 0xFF; - } - else { - if (getBit(instr, 23)) - offset = (instr & 0xFF) << 2; - else - offset = - ((instr & 0xFF) << 2); - } - } - - /** Returns the number of the register, which contains the base address for this data transfer.*/ - public final byte getBaseRegister() { - return Rn; - } - - /** Returns the transfer register on the coprocessor. */ - public final byte getCoprocessorRd() { - return Rd; - } - - /** True if this is a LDC instruction, false if it is a STC instruction. */ - public final boolean isLoad() { - return isLoad; - } - - /** Returns the offset that should be added to the base register. Note that the offset may be negative. */ - public final int getOffset() { - return offset; - } - - /** In certain circumstances, the instruction might include an option to the coprocessor that is stored instead of the offset. */ - public final int getOption() { - if (DBT.VerifyAssertions) DBT._assert(!writeBack && !preIndexing); - - return offset; - } - - /** True if the changed base register shall be persisted after this instruction. */ - public final boolean writeBack() { - return writeBack; - } - - /** True if the base register shall be changed before the transfer, otherwise changed it after the transfer. */ - public final boolean preIndexing() { - return preIndexing; - } - - /** Returns true, if the flag which indicates a large transfer is set. The meaning of "large transfer" is dependend on the coprocessor.*/ - public final boolean largeTransfer() { - return largeTransfer; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a CDP instruction. */ - public static class CoprocessorDataProcessing extends CoprocessorTemplate { - - /** @see #getOpcode() */ - protected final byte opcode; - - /** @see #getCoprocessorRm() */ - protected final byte cpRm; - - /** @see #getCoprocessorInfo() */ - protected final byte cpInfo; - - public CoprocessorDataProcessing(int instr) { - super(instr); - - opcode = (byte) getBits(instr, 20, 23); - cpInfo = (byte) getBits(instr, 5, 7); - cpRm = (byte) (instr & 0xF); - } - - /** Returns the destination register of this operation. This register is a coprocessor register. */ - public final byte getCoprocessorRd() { - return Rd; - } - - /** Returns the first operand register of this operation. This register is a coprocessor register. */ - public final byte getCoprocessorRn() { - return Rn; - } - - /** Returns the second operand register of this operation. This register is a coprocessor register. */ - public final byte getCoprocessorRm() { - return cpRm; - } - - /** The instruction contains three bits that may be used to control the details of the operation. This info is only of significance to the coprocessor. */ - public final byte getCoprocessorInfo() { - return cpInfo; - } - - /** Returns the opcode, that identifies the operation that shall be performed on the coprocessor. This vlaue is only of significance to the coprocessor. */ - public final byte getOpcode() { - return opcode; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a MRC/MCR instruction. */ - public static class CoprocessorRegisterTransfer extends CoprocessorTemplate { - - /** @see #getOpcode() */ - protected final byte opcode; - - /** @see #getCoprocessorRm() */ - protected final byte cpRm; - - /** @see #getCoprocessorInfo() */ - protected final byte cpInfo; - - /** @see #isLoadFromCP() */ - protected final boolean isLoad; - - public CoprocessorRegisterTransfer(int instr) { - super(instr); - - opcode = (byte) getBits(instr, 21, 23); - cpInfo = (byte) getBits(instr, 5, 7); - cpRm = (byte) (instr & 0xF); - isLoad = getBit(instr, 20); - } - - /** Returns true if this operation is a load from a coprocessor or false if it is a store to coprocessor. */ - public final boolean isLoadFromCP() { - return isLoad; - } - - /** Returns the destination register of this operation.*/ - public final byte getRd() { - return Rd; - } - - /** Returns the first operand register of this operation. This register is a coprocessor register. */ - public final byte getCoprocessorRn() { - return Rn; - } - - /** Returns the second operand register of this operation. This register is a coprocessor register. */ - public final byte getCoprocessorRm() { - return cpRm; - } - - /** The instruction contains three bits that may be used to control the details of the operation. This info is only of significance to the coprocessor. */ - public final byte getCoprocessorInfo() { - return cpInfo; - } - - /** Returns the opcode, that identifies the operation that shall be performed on the coprocessor. This vlaue is only of significance to the coprocessor. */ - public final byte getOpcode() { - return opcode; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a MRS instruction. */ - public static class MoveFromStatusRegister extends Instruction { - - /** @see #getRd() */ - protected final byte Rd; - - /** @see #transferSavedPSR() */ - protected final boolean transferSavedPSR; - - public MoveFromStatusRegister(int instr) { - super(instr); - - Rd = (byte) getBits(instr, 12, 15); - transferSavedPSR = getBit(instr, 22); - } - - /** Returns the number of the destination register. */ - public final byte getRd() { - return Rd; - } - - /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ - public final boolean transferSavedPSR() { - return transferSavedPSR; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a MSR instruction. */ - public static class MoveToStatusRegister extends Instruction { - - /** @see #transferControlField() */ - protected final boolean transferControl; - - /** @see #transferExtensionField() */ - protected final boolean transferExtension; - - /** @see #transferStatusField() */ - protected final boolean transferStatus; - - /** @see #transferFlagField() */ - protected final boolean transferFlags; - - /** @see #transferSavedPSR() */ - protected final boolean transferSavedPSR; - - /** @see #getSource() */ - protected final OperandWrapper sourceOperand; - - public MoveToStatusRegister(int instr) { - super(instr); - - transferControl = getBit(instr, 16); - transferExtension = getBit(instr, 17); - transferStatus = getBit(instr, 18); - transferFlags = getBit(instr, 19); - - transferSavedPSR = getBit(instr, 22); - - if (getBit(instr, 25)) - sourceOperand = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); - else - sourceOperand = OperandWrapper.decodeShiftedRegister(instr); - } - - /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ - public final boolean transferSavedPSR() { - return transferSavedPSR; - } - - /** Returns true if the control field of the PSR shall be overwritten. */ - public final boolean transferControlField() { - return transferControl; - } - - /** Returns true if the extension field of the PSR shall be overwritten. */ - public final boolean transferExtensionField() { - return transferExtension; - } - - /** Returns true if the status field of the PSR shall be overwritten. */ - public final boolean transferStatusField() { - return transferStatus; - } - - /** Returns true if the flag field of the PSR shall be overwritten. */ - public final boolean transferFlagField() { - return transferFlags; - } - - /** Returns the operand, which is to be transfered into the status register. */ - public final OperandWrapper getSource() { - return sourceOperand; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } - - /** Represents a CLZ instruction. */ - public static class CountLeadingZeros extends Instruction { - - /** @see #getRm() */ - protected final byte Rm; - - /** @see #getRd() */ - protected final byte Rd; - - public CountLeadingZeros(int instr) { - super(instr); - - Rm = (byte) (instr & 0xF); - Rd = (byte) getBits(instr, 12, 15); - } - - /** Returns the source register for this operation. */ - public final byte getRm() { - return Rm; - } - - /** Returns the destination register for this operation. */ - public final byte getRd() { - return Rd; - } - - @Override - public void visit(ARM_InstructionVisitor visitor) { - visitor.visit(this); - } - } -} Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-14 13:55:41 UTC (rev 55) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-14 14:47:54 UTC (rev 56) @@ -1,6 +1,6 @@ package org.binarytranslator.arch.arm.decoder; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.*; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; /** An interface that supports iterating over ARM instructions using the visitor pattern. */ public interface ARM_InstructionVisitor { Copied: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java (from rev 55, src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java) =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-14 14:47:54 UTC (rev 56) @@ -0,0 +1,1195 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.DBT; + +/** + * In the ARM decoder model, the decoding and usage (translating/interpreting/disassembling) of instructions + * is strictly separated. This class provides a namespace for all decoder classes. A decoder works like a + * mask than can be put upon a binary instruction to look at the different fields within that instruction. + * + * Application might derive from these decoders to implement instruction-specific functionality. + * Then, implement a version of the generic {@link ARM_InstructionFactory} interface, which returns + * your derived classes and pass it to the {@link ARM_InstructionDecoder} to let it create instances of + * your class from binary instructions. + * + * @author Michael Baer + * + */ +public class ARM_Instructions { + + /** + * Checks if a bit is set within a word. + * @param word + * The word that is being examined. + * @param bit + * The number of the bit that is to be checked, starting from zero. + * @return + * True, if the given bit is set within the word, false otherwise. + */ + private static final boolean getBit(int word, int bit) { + if (DBT.VerifyAssertions) + DBT._assert(bit >= 0 && bit <= 31); + return (word & (1 << bit)) != 0; + } + + /** + * Extracts a subsequence of bits from a word. + * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. + * @param word + * The word that is to be examined. + * @param from + * The first bit (starting from 0) that is to be extracted. + * @param to + * The last bit (starting from 0) that is to be extracted from the word. + * @return + * A zero-based version of the bit sequence. + */ + private static final int getBits(int word, int from, int to) { + if (DBT.VerifyAssertions) + DBT._assert(from < to && from >= 0 && to <= 31); + return (word & ((1 << (to + 1)) - 1)) >> from; + } + + /** + * Sign extends a given value. + * @param value + * The value to sign extends. + * @param bitsUsed + * The number bits used within this values. + * @return + * A sign extended value. + */ + public static int signExtend(int value, int bitsUsed) { + return (value << (32 - bitsUsed)) >> (32 - bitsUsed); + } + + /** A base class for all (conditional) ARM instructions. */ + public abstract static class Instruction { + + public enum Condition { + EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV + } + + /** @see #getCondition() */ + protected final Condition condition; + + private Instruction(int instr) { + condition = Condition.values()[(byte) getBits(instr, 28, 31)]; + } + + /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ + public final Condition getCondition() { + return condition; + } + + @Override + public String toString() { + return ARM_Disassembler.disassemble(this).asString(); + } + + /** All instruction classes are meant to implement the visitor pattern. This is the pattern's visit method. */ + public abstract void visit(ARM_InstructionVisitor visitor); + } + + /** Base class for most instructions that use two registers. */ + private abstract static class TwoRegistersTemplate extends Instruction { + + /** @see #getRn() */ + protected final byte Rn; + + /** @see #getRd() */ + protected final byte Rd; + + public TwoRegistersTemplate(int instr) { + super(instr); + + Rd = (byte) getBits(instr, 12, 15); + Rn = (byte) getBits(instr, 16, 19); + } + + /** Returns the number of the operation's destination register, starting from 0.*/ + public final byte getRd() { + return Rd; + } + + /** Returns the number of the operation's first operand register, starting from 0.*/ + public final byte getRn() { + return Rn; + } + } + + /** Base class for most instructions that use three registers. */ + private abstract static class ThreeRegistersTemplate extends + TwoRegistersTemplate { + + /** @see #getRm() */ + protected final byte Rm; + + public ThreeRegistersTemplate(int instr) { + super(instr); + + Rm = (byte) getBits(instr, 0, 3); + } + + /** Returns the number of the second operand register, starting from 0.*/ + public final byte getRm() { + return Rm; + } + } + + /** Base class for multiply operations. */ + protected abstract static class MultiplyTemplate + extends ThreeRegistersTemplate { + + /** @see #updateConditionCodes() */ + protected final boolean updateConditionCodes; + + /** @see #accumulate() */ + protected final boolean accumulate; + + /** @see #getRs() */ + protected final byte Rs; + + protected MultiplyTemplate(int instr) { + super(instr); + + updateConditionCodes = getBit(instr, 20); + accumulate = getBit(instr, 21); + Rs = (byte) getBits(instr, 8, 11); + } + + /** Returns true, if the condition codes shall be updated by the result of this operation. */ + public final boolean updateConditionCodes() { + return updateConditionCodes; + } + + /** Returns true, if this is the accumulate version of the instruction. */ + public final boolean accumulate() { + return accumulate; + } + + /** Returns the register number of the Rs operand register. */ + public final byte getRs() { + return Rs; + } + } + + /** Base class for coprocessor instructions. */ + protected static abstract class CoprocessorTemplate extends Instruction { + + /** This is a register id, which can either refer to the CPU or the coprocessor, depending on the instruction. */ + protected final byte Rd; + + /** This is a register id, which can either refer to the CPU or the coprocessor, depending on the instruction. */ + protected final byte Rn; + + /** @see #getCoprocessorNumber() */ + protected final byte cpNum; + + public CoprocessorTemplate(int instr) { + super(instr); + + cpNum = (byte) getBits(instr, 8, 11); + Rd = (byte) getBits(instr, 12, 15); + Rn = (byte) getBits(instr, 16, 19); + } + + /** Returns the coprocessor that shall process this instruction */ + public final byte getCoprocessorNumber() { + return cpNum; + } + } + + /** Represents an operand, which might either be an immediate value, a register (shifted by an immediate) or a register shifted by a register. */ + public abstract static class OperandWrapper { + + /** Describes the type of the operand. */ + public enum Type { + Immediate, + PcRelative, + Register, + ImmediateShiftedRegister, + RegisterShiftedRegister, + } + + /** Describes a type of shift, in case the operand is supposed to be shifted. */ + public enum ShiftType { + LSL, + LSR, + ASR, + ROR, + RRE + } + + /** Creates an operand wrapper around a 12 bit immediate value. */ + public static OperandWrapper createImmediate(int immediate) { + return new ImmediateOperand(immediate); + } + + /** Creates an operand wrapper that is a normal register value. */ + public static OperandWrapper createRegister(byte register) { + return new RegisterOperand(register); + } + + /** Creates an operand wrapper representing an offset to the pc.*/ + public static OperandWrapper createPcRelative(int offset) { + return new PcRelativeOperand(offset); + } + + /** Creates an operand wrapper, that represents a register shifted by an immediate or a register, depending on the instruction. */ + public static OperandWrapper decodeShiftedRegister(int instr) { + ShiftType shift = ShiftType.values()[getBits(instr, 5, 6)]; + byte shiftedRegister = (byte) (instr & 0xF); + + if (getBit(instr, 4)) { + //shift by a register + byte shiftingRegister = (byte)getBits(instr, 8, 11); + return new RegisterShiftRegisterOperand(shiftedRegister, shift, shiftingRegister); + } + else { + //shift by an immediate + byte immediate = (byte)getBits(instr, 7, 11); + + if (immediate == 0) { + //if we are shifting by zero, we might forget about the shift + if (shift == ShiftType.ROR) { + //However, if the shift type was RotateRight, then ARM meant do a RotateRightExtend by 1 + return new RegisterShiftImmediateOperand(shiftedRegister, shift, (byte)1); + } + else { + //Otherwise, really forget about the shifting + return new RegisterOperand(shiftedRegister); + } + } + else { + return new RegisterShiftImmediateOperand(shiftedRegister, shift, immediate); + } + } + } + + /** Returns the type of the operand that this class is actually representing. */ + public abstract Type getType(); + + /** Returns the immediate, which is the 2nd operand of this instruction. Make sure that hasImmediate is true before calling this. */ + public int getImmediate() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + /** Returns an offset that is to be applied to a register. */ + public int getOffset() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + /** Returns the number of the register, which forms the 2nd operand. Only applicable if {@link #hasImmediate()} is false.*/ + public byte getRegister() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + /** Returns the number of the register which is performing the shift. */ + public byte getShiftingRegister() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + /** Returns the amount by which a value is supposed to be shifted*/ + public byte getShiftAmount() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + /** Returns the shift type, in case this Operand includes shifting. */ + public ShiftType getShiftType() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + + /** Represents an immediate value operand. */ + protected static class ImmediateOperand extends OperandWrapper { + + /** @see #getImmediate() */ + protected final int immediate; + + protected ImmediateOperand(int immediate) { + this.immediate = immediate; + } + + @Override + public int getImmediate() { + return immediate; + } + + @Override + public Type getType() { + return Type.Immediate; + } + } + + protected static class PcRelativeOperand extends OperandWrapper { + + protected final int offset; + + protected PcRelativeOperand(int offset) { + this.offset = offset; + } + + @Override + public byte getRegister() { + return 15; + } + + @Override + public int getOffset() { + return offset; + } + + @Override + public Type getType() { + return Type.PcRelative; + } + } + + /** Represents a register operand. */ + protected static class RegisterOperand extends OperandWrapper { + + /** @see #getRegister() */ + protected final byte register; + + protected RegisterOperand(byte register) { + this.register = register; + } + + @Override + public byte getRegister() { + return register; + } + + @Override + public Type getType() { + return Type.Register; + } + } + + /** Represents an operand, which is a register shifted by an immediate value. */ + protected static class RegisterShiftImmediateOperand extends RegisterOperand { + + /** @see #getShiftType() */ + protected final ShiftType shiftType; + + /** @see #getShiftAmount() */ + protected final byte shiftAmount; + + protected RegisterShiftImmediateOperand(byte register, ShiftType shift, byte shiftAmount) { + super(register); + this.shiftAmount = shiftAmount; + this.shiftType = shift; + } + + ... [truncated message content] |
From: <mic...@us...> - 2007-04-14 13:55:40
|
Revision: 55 http://svn.sourceforge.net/pearcolator/?rev=55&view=rev Author: michael_baer Date: 2007-04-14 06:55:41 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Initial version of an ARM disassembler. Fixed a few bugs in ARM_InstructionDecoders. Introduced named enumerations for ARM condition codes and data processing opcodes. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/generic/decoder/DisassembledInstruction.java Added: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-14 13:55:41 UTC (rev 55) @@ -0,0 +1,409 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Instruction; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.BlockDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Branch; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.BranchExchange; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorDataProcessing; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CoprocessorRegisterTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.CountLeadingZeros; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.DataProcessing; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.IntMultiply; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.LongMultiply; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.MoveFromStatusRegister; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.MoveToStatusRegister; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.OperandWrapper; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.SingleDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.SoftwareInterrupt; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Swap; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Instruction.Condition; +import org.binarytranslator.generic.decoder.DisassembledInstruction; +import org.binarytranslator.generic.os.process.ProcessSpace; + +/** + * This class transfers an ARM instruction into a human-readable assembly + * format. + * + * @author Michael Baer + * + */ +public final class ARM_Disassembler { + + /** + * Disassembles an ARM instruction by reading it from a ProcessSpace. + * + * @param pc + * The address of the ARM instruction within the process space's + * memory. + * @param ps + * The process space from which the instruction is read. + * @return A disassembled ARM instruction. + */ + public final static DisassembledInstruction disassemble(int address, + ProcessSpace ps) { + + int instr = ps.memory.loadInstruction32(address); + DisassemblingVisitor disassembler = new DisassemblingVisitor(address); + + return disassembler.result; + } + + /** + * Directly disassembles an ARM instruction. This method only has package + * visibility, because it is only used to provide the toString() functionality + * for the ARM instruction decoder. + * + * @param instruction + * The instruction that is to be decoded. + * @return A human-readable version of the given instruction. + */ + final static DisassembledInstruction disassemble( + ARM_InstructionDecoders.Instruction instruction) { + + DisassemblingVisitor disassembler = new DisassemblingVisitor(); + instruction.visit(disassembler); + + return disassembler.result; + } + + /** Represents a disassembled ARM instruction. */ + private final static class ARM_DisassembledInstruction implements + DisassembledInstruction { + + /** A readable version of the diassembled instruction. */ + private final String instruction; + + public ARM_DisassembledInstruction(String instruction) { + this.instruction = instruction; + } + + /** @see DisassembledInstruction#asString() */ + public String asString() { + return instruction; + } + + /** @see DisassembledInstruction#getSuccessor(int) */ + public int getSuccessor(int pc) { + return pc + 4; + } + } + + /** + * As this class has only static methods, there is no need to ever instantiate + * it. + */ + private ARM_Disassembler() { + } + + /** + * This class decodes an ARM instruction into an ARM_DisassembledInstruction. + * It used a visitor pattern to decode the proper instructions and should only + * be used by calling {@link Instruction#visit(ARM_InstructionVisitor)} method. The + * disassembled instruction is saved within the {@link #result} member. + * + * As this class is private (i.e. can only ever be instantiated by its + * superclass), it should only be accessed using the methods provided by the + * superclass. + * + * @author Michael Baer + */ + private static final class DisassemblingVisitor implements + ARM_InstructionVisitor { + + /** This field receives the disassembled instruction. */ + private ARM_DisassembledInstruction result; + + /** The address of the instruction which is currently decoded or -1, if that address is not known. */ + private int address; + + private DisassemblingVisitor() { + this.address = -1; + } + + private DisassemblingVisitor(int address) { + this.address = address; + } + + /** Wraps a decoded assembly statement within an {@link ARM_DisassembledInstruction} object and + * stores it as the result of this operation. */ + private void setResult(String assembly) { + result = new ARM_DisassembledInstruction(assembly); + } + + /** + * Extracts the condition field from an instruction and provides a + * human-readable assembly form of the condition. + * + * @param instr + * The instruction, whose condition field shall be read. + * @return A human readable form of this instructions condition. + */ + private String cond(Instruction instr) { + return instr.getCondition().name(); + } + + /** + * Decodes an operand stored within a {@link OperandWrapper} object and + * provides an human-readable, ARM assembly version of it. + * + * @param op + * The operand that is to be decoded. + * @return A readable version of the operand. + */ + private final String operand(OperandWrapper op) { + switch (op.getType()) { + case Immediate: + return String.format("#%x", op.getImmediate()); + + case ImmediateShiftedRegister: + return String.format("r%d %s #%d", op.getRegister(), op.getShiftType(), + op.getShiftAmount()); + + case PcRelative: + return String.format("#%x", op.getOffset() + address + 8); + + case Register: + return "r" + op.getRegister(); + + case RegisterShiftedRegister: + return String.format("r%d %s r%s", op.getRegister(), op.getShiftType(), + op.getShiftingRegister()); + + default: + throw new RuntimeException("Unexpected operand wrapper type: " + + op.getType()); + } + } + + public void visit(DataProcessing instr) { + String mnemonic = instr.getOpcode().name(); + mnemonic += cond(instr); + + if (instr.updateConditionCodes()) + mnemonic += 'S'; + + String optionalParam; + + // Filter instructions that only take one parameter + if (instr.getOpcode() != DataProcessing.Opcode.MOV + && instr.getOpcode() != DataProcessing.Opcode.MVN) { + + optionalParam = ", " + operand(instr.getOperand2()); + } else + optionalParam = ""; + + setResult(String.format("%s r%d, r%d %s", mnemonic, instr.getRd(), instr + .getRn(), optionalParam)); + } + + public void visit(SingleDataTransfer instr) { + String mnemonic = instr.isLoad() ? "LDR" : "STR"; + String address = "[r" + instr.getRn(); + + if (instr.preIndexing()) { + address += ", " + operand(instr.getOffset()) + "]"; + + if (instr.writeBack()) + address += '!'; + } else { + address += "], " + operand(instr.getOffset()); + } + mnemonic += cond(instr); + + switch (instr.getSize()) { + case Byte: + mnemonic += 'B'; + break; + + case HalfWord: + mnemonic += 'H'; + break; + + case Word: + break; + + default: + throw new RuntimeException( + "Unexpected transfer size for single data transfer: " + + instr.getSize()); + } + + if (instr.forceUserMode()) + mnemonic += 'T'; + + setResult(String.format("%s r%d, %s", mnemonic, instr.getRd(), address)); + } + + public void visit(IntMultiply instr) { + + String mnemonic; + String accumParam; + + if (instr.accumulate) { + mnemonic = "MLA"; + accumParam = ", r" + instr.getRn(); + } else { + mnemonic = "MUL"; + accumParam = ""; + } + + mnemonic += cond(instr); + + if (instr.updateConditionCodes()) + mnemonic += "S"; + + setResult(String.format("%s r%d, r%d, r%d%s", mnemonic, instr.getRd(), + instr.getRm(), instr.getRs(), accumParam)); + } + + public void visit(LongMultiply instr) { + String mnemonic = instr.isUnsigned() ? "U" : "S"; + + mnemonic += instr.accumulate() ? "MLAL" : "MULL"; + mnemonic += cond(instr); + + if (instr.updateConditionCodes()) + mnemonic += "S"; + + setResult(String.format("%s %s, %s, %s, %s", mnemonic, instr.getRdLow(), + instr.getRdHigh(), instr.getRm(), instr.getRs())); + } + + public void visit(Swap instr) { + + String mnemonic = instr.swapByte() ? "B" : ""; + setResult(String.format("SWP%s%s r%d, r%d, r%d", mnemonic, cond(instr), + instr.getRd(), instr.getRm(), instr.getRn())); + } + + public void visit(BlockDataTransfer instr) { + String mnemonic = instr.isLoad() ? "LDM" : "STM"; + String baseRegister = "r" + instr.getBaseRegister(); + + mnemonic += cond(instr); + mnemonic += instr.incrementBase() ? "I" : "D"; + mnemonic += instr.postIndexing() ? "A" : "B"; + + if (instr.writeBack()) + baseRegister += "!"; + + String registers = ""; + + for (int i = 0; i < 15; i++) + if (instr.transferRegister(i)) + registers += ", r" + i; + + registers = registers.substring(2); + + setResult(String.format("%s %s, {%s}%s", mnemonic, baseRegister, + registers, instr.forceUser() ? "^" : "")); + } + + public void visit(SoftwareInterrupt instr) { + + setResult(String.format("SWI%s #%x", cond(instr), instr + .getInterruptNumber())); + } + + public void visit(Branch instr) { + + String mnemonic = instr.link() ? "BL" : "B"; + setResult(String.format("%s%s #%x", mnemonic, cond(instr), instr + .getOffset() + + address)); + } + + public void visit(BranchExchange instr) { + + String mnemonic = instr.link ? "BLX" : "BX"; + setResult(String.format("%s%s #%x", mnemonic, cond(instr), operand(instr + .target()))); + } + + public void visit(CoprocessorDataTransfer instr) { + + String mnemonic = instr.isLoad() ? "LDC" : "STC"; + String cond = instr.getCondition() == Condition.NV ? "2" : cond(instr); + String largeTransfer = instr.largeTransfer() ? "L" : ""; + String address = "[r" + instr.getBaseRegister(); + + if (!instr.preIndexing() && !instr.writeBack()) { + // this is a special instruction form, where the offset is actually a + // coprocessor option + address += "], " + instr.getOption(); + } else { + + String offset = "#" + instr.getOffset(); + + if (!instr.preIndexing()) { + address += "], " + offset; + } else { + address += ", " + offset + "]"; + + if (instr.writeBack()) + address += "!"; + } + } + + setResult(String.format("%s%s%s p%d, cp_r%d, %s", mnemonic, cond, + largeTransfer, instr.getCoprocessorNumber(), + instr.getCoprocessorRd(), address)); + } + + public void visit(CoprocessorDataProcessing instr) { + + String mnemonic = instr.getCondition() == Condition.NV ? "CDP2" : "CDP" + + cond(instr); + setResult(String.format("%s p%d, %d, cp_r%d, cp_r%d, cp_r%d, %d", + mnemonic, instr.getCoprocessorNumber(), instr.getOpcode(), instr + .getCoprocessorRd(), instr.getCoprocessorRn(), instr + .getCoprocessorRm(), instr.getCoprocessorInfo())); + } + + public void visit(CoprocessorRegisterTransfer instr) { + String mnemonic = instr.isLoadFromCP() ? "MRC" : "MCR"; + String condition = instr.getCondition() == Condition.NV ? "2" : cond(instr); + String opcode2 = instr.getCoprocessorInfo() != 0 ? ", " + + instr.getCoprocessorInfo() : ""; + + setResult(String.format("%s%s p%d, %d, r%d, cp_r%d, cp_r%d%s", mnemonic, + condition, instr.getCoprocessorNumber(), instr.getOpcode(), instr + .getRd(), instr.getCoprocessorRn(), instr.getCoprocessorRm(), + opcode2)); + } + + public void visit(MoveFromStatusRegister instr) { + + String field = instr.transferSavedPSR() ? "SPSR" : "CPSR"; + setResult(String.format("MRS%s r%d, %s", cond(instr), instr.getRd(), + field)); + } + + public void visit(MoveToStatusRegister instr) { + + String fields = instr.transferSavedPSR() ? "SPSR_" : "CPSR_"; + + if (instr.transferControlField()) + fields += 'c'; + + if (instr.transferExtensionField()) + fields += 'x'; + + if (instr.transferStatusField()) + fields += 's'; + + if (instr.transferFlagField()) + fields += 'f'; + + setResult(String.format("MSR%s %s, %s", cond(instr), fields, + operand(instr.getSource()))); + } + + public void visit(CountLeadingZeros instr) { + + setResult(String.format("CLZ%s r%s r%s ", cond(instr), instr.getRd(), + instr.getRm())); + } + } +} Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-14 12:04:52 UTC (rev 54) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-14 13:55:41 UTC (rev 55) @@ -64,25 +64,35 @@ } /** A base class for all (conditional) ARM instructions. */ - private abstract static class Basic { + public abstract static class Instruction { + + public enum Condition { + EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV + } + /** @see #getCondition() */ - protected final byte condition; + protected final Condition condition; - public Basic(int instr) { - condition = (byte) getBits(instr, 28, 31); + private Instruction(int instr) { + condition = Condition.values()[(byte) getBits(instr, 28, 31)]; } /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ - public final byte getCondition() { + public final Condition getCondition() { return condition; } + @Override + public String toString() { + return ARM_Disassembler.disassemble(this).asString(); + } + /** All instruction classes are meant to implement the visitor pattern. This is the pattern's visit method. */ public abstract void visit(ARM_InstructionVisitor visitor); } /** Base class for most instructions that use two registers. */ - private abstract static class TwoRegistersTemplate extends Basic { + private abstract static class TwoRegistersTemplate extends Instruction { /** @see #getRn() */ protected final byte Rn; @@ -165,7 +175,7 @@ } /** Base class for coprocessor instructions. */ - protected static abstract class CoprocessorTemplate extends Basic { + protected static abstract class CoprocessorTemplate extends Instruction { /** This is a register id, which can either refer to the CPU or the coprocessor, depending on the instruction. */ protected final byte Rd; @@ -196,6 +206,7 @@ /** Describes the type of the operand. */ public enum Type { Immediate, + PcRelative, Register, ImmediateShiftedRegister, RegisterShiftedRegister, @@ -203,11 +214,11 @@ /** Describes a type of shift, in case the operand is supposed to be shifted. */ public enum ShiftType { - LogicalLeft, - LogicalRight, - ArithmeticRight, - RotateRight, - RotateRightExtend + LSL, + LSR, + ASR, + ROR, + RRE } /** Creates an operand wrapper around a 12 bit immediate value. */ @@ -215,11 +226,16 @@ return new ImmediateOperand(immediate); } - /** Creates an operand wrapper that is a nromal register value. */ + /** Creates an operand wrapper that is a normal register value. */ public static OperandWrapper createRegister(byte register) { return new RegisterOperand(register); } + /** Creates an operand wrapper representing an offset to the pc.*/ + public static OperandWrapper createPcRelative(int offset) { + return new PcRelativeOperand(offset); + } + /** Creates an operand wrapper, that represents a register shifted by an immediate or a register, depending on the instruction. */ public static OperandWrapper decodeShiftedRegister(int instr) { ShiftType shift = ShiftType.values()[getBits(instr, 5, 6)]; @@ -236,7 +252,7 @@ if (immediate == 0) { //if we are shifting by zero, we might forget about the shift - if (shift == ShiftType.RotateRight) { + if (shift == ShiftType.ROR) { //However, if the shift type was RotateRight, then ARM meant do a RotateRightExtend by 1 return new RegisterShiftImmediateOperand(shiftedRegister, shift, (byte)1); } @@ -259,6 +275,11 @@ throw new RuntimeException("Invalid call on an operand wrapper."); } + /** Returns an offset that is to be applied to a register. */ + public int getOffset() { + throw new RuntimeException("Invalid call on an operand wrapper."); + } + /** Returns the number of the register, which forms the 2nd operand. Only applicable if {@link #hasImmediate()} is false.*/ public byte getRegister() { throw new RuntimeException("Invalid call on an operand wrapper."); @@ -300,6 +321,30 @@ } } + protected static class PcRelativeOperand extends OperandWrapper { + + protected final int offset; + + protected PcRelativeOperand(int offset) { + this.offset = offset; + } + + @Override + public byte getRegister() { + return 15; + } + + @Override + public int getOffset() { + return offset; + } + + @Override + public Type getType() { + return Type.PcRelative; + } + } + /** Represents a register operand. */ protected static class RegisterOperand extends OperandWrapper { @@ -387,12 +432,19 @@ /** Represents a Data Processing instruction. */ public static class DataProcessing extends TwoRegistersTemplate { + + /** A list of possible DataProcessing operations. The list is orded in ascendingly, with the + * first opcode corresponding to opcode 0 (zero) in the opcode field of an ARM data processing + * instruction. */ + public enum Opcode { + AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN + } /** @see #hasSetConditionCodes() */ protected final boolean updateConditionCodes; /** @see #getOpcode() */ - protected final byte opcode; + protected final Opcode opcode; /** @see #getOperand2() */ protected final OperandWrapper operand2; @@ -401,7 +453,7 @@ super(instr); updateConditionCodes = getBit(instr, 20); - opcode = (byte) getBits(instr, 21, 24); + opcode = Opcode.values()[(byte) getBits(instr, 21, 24)]; if (getBit(instr, 25)) operand2 = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); @@ -410,7 +462,7 @@ } /** Returns the opcode, that specifies the data processing operation, which is to be performed. */ - public final byte getOpcode() { + public final Opcode getOpcode() { return opcode; } @@ -448,6 +500,9 @@ /** @see #signExtend() */ protected final boolean signExtend; + + /** @see #forceUserMode() */ + protected final boolean forceUserMode; /** @see #getSize() */ protected final TransferSize size; @@ -473,6 +528,8 @@ //this is an unsigned byte or word transfer signExtend = false; + forceUserMode = !preIndexing && writeBack; + if (getBit(instr, 22)) size = TransferSize.Byte; else @@ -491,6 +548,7 @@ size = TransferSize.Byte; signExtend = getBit(instr, 6); + forceUserMode = false; if (getBit(instr, 22)) { //immediate offset @@ -506,6 +564,11 @@ } } + /** Returns true, if this memory access shall be treated as if it had been done in user mode. */ + public final boolean forceUserMode() { + return forceUserMode; + } + /** Returns true, if the loaded/stored value shall be signed-extended.*/ public final boolean signExtend() { return signExtend; @@ -552,6 +615,8 @@ protected IntMultiply(int instr) { super(instr); + + if (DBT.VerifyAssertions) DBT._assert(accumulate || Rn == 0); } @Override @@ -616,10 +681,10 @@ } /** Represents a LDM/STM instruction. */ - public static class BlockDataTransfer extends Basic { + public static class BlockDataTransfer extends Instruction { - /** @see #preIndexing() */ - protected final boolean preIndexing; + /** @see #postIndexing() */ + protected final boolean postIndexing; /** @see #incrementBase() */ protected final boolean incrementBase; @@ -642,7 +707,7 @@ public BlockDataTransfer(int instr) { super(instr); - preIndexing = getBit(instr, 24); + postIndexing = getBit(instr, 24); incrementBase = getBit(instr, 23); forceUser = getBit(instr, 22); writeBack = getBit(instr, 21); @@ -659,9 +724,9 @@ return getBit(registerList, r); } - /** True if the base register shall be changed before each single transfer, otherwise changed it after each transfer. */ - public final boolean preIndexing() { - return preIndexing; + /** True if the base register shall be changed after each single transfer, otherwise changed it before each transfer. */ + public final boolean postIndexing() { + return postIndexing; } /** True if the base register shall be incremented, false if it should be decremented. */ @@ -696,7 +761,7 @@ } /** Represents a SWI instruction*/ - public static class SoftwareInterrupt extends Basic { + public static class SoftwareInterrupt extends Instruction { /** @see #getInterruptNumber() */ protected final int interruptNumber; @@ -718,9 +783,9 @@ } /** Represents a branch instruction. */ - public static class Branch extends Basic { + public static class Branch extends Instruction { - /** @see #isBranchAndLink() */ + /** @see #link() */ protected final boolean link; /** @see #getOffset() */ @@ -733,7 +798,7 @@ } /** Should the current PC be put into the lr? */ - public final boolean isBranchAndLink() { + public final boolean link() { return link; } @@ -749,9 +814,9 @@ } /** Represents a BX instruction set */ - public static class BranchExchange extends Basic { + public static class BranchExchange extends Instruction { - /** @see #getRn() */ + /** @see #target() */ protected final OperandWrapper target; /** @see #link() */ @@ -765,13 +830,13 @@ link = true; //sign extend jump target - int jumpTarget = signExtend(instr & 0xFFF, 24); + int jumpTarget = signExtend(instr & 0xFFF, 24) << 2; //are we addressing a half-byte? if (getBit(instr, 24)) jumpTarget += 2; - target = OperandWrapper.createImmediate(jumpTarget); + target = OperandWrapper.createPcRelative(jumpTarget); } else { link = getBit(instr, 5); @@ -783,6 +848,11 @@ public final boolean link() { return link; } + + /** Returns the address to which this instruction will branch. */ + public final OperandWrapper target() { + return target; + } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -816,10 +886,15 @@ writeBack = getBit(instr, 21); isLoad = getBit(instr, 20); - if (getBit(instr, 23)) - offset = (instr & 0xFF) << 2; - else - offset = - ((instr & 0xFF) << 2); + if (!writeBack && !preIndexing) { + offset = instr & 0xFF; + } + else { + if (getBit(instr, 23)) + offset = (instr & 0xFF) << 2; + else + offset = - ((instr & 0xFF) << 2); + } } /** Returns the number of the register, which contains the base address for this data transfer.*/ @@ -828,7 +903,7 @@ } /** Returns the transfer register on the coprocessor. */ - public final byte getCoprocessorRegister() { + public final byte getCoprocessorRd() { return Rd; } @@ -842,6 +917,13 @@ return offset; } + /** In certain circumstances, the instruction might include an option to the coprocessor that is stored instead of the offset. */ + public final int getOption() { + if (DBT.VerifyAssertions) DBT._assert(!writeBack && !preIndexing); + + return offset; + } + /** True if the changed base register shall be persisted after this instruction. */ public final boolean writeBack() { return writeBack; @@ -975,7 +1057,7 @@ } /** Represents a MRS instruction. */ - public static class MoveFromStatusRegister extends Basic { + public static class MoveFromStatusRegister extends Instruction { /** @see #getRd() */ protected final byte Rd; @@ -1007,7 +1089,7 @@ } /** Represents a MSR instruction. */ - public static class MoveToStatusRegister extends Basic { + public static class MoveToStatusRegister extends Instruction { /** @see #transferControlField() */ protected final boolean transferControl; @@ -1024,7 +1106,7 @@ /** @see #transferSavedPSR() */ protected final boolean transferSavedPSR; - /** @see #getSourceOperand() */ + /** @see #getSource() */ protected final OperandWrapper sourceOperand; public MoveToStatusRegister(int instr) { @@ -1069,7 +1151,7 @@ } /** Returns the operand, which is to be transfered into the status register. */ - public final OperandWrapper getSourceOperand() { + public final OperandWrapper getSource() { return sourceOperand; } @@ -1080,7 +1162,7 @@ } /** Represents a CLZ instruction. */ - public static class CountLeadingZeros extends Basic { + public static class CountLeadingZeros extends Instruction { /** @see #getRm() */ protected final byte Rm; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-14 12:04:52 UTC (rev 54) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-14 13:55:41 UTC (rev 55) @@ -5,19 +5,19 @@ /** An interface that supports iterating over ARM instructions using the visitor pattern. */ public interface ARM_InstructionVisitor { - void visit(DataProcessing processing); - void visit(SingleDataTransfer transfer); - void visit(IntMultiply multiply); - void visit(LongMultiply multiply); - void visit(Swap swap); - void visit(BlockDataTransfer transfer); - void visit(SoftwareInterrupt interrupt); - void visit(Branch branch); - void visit(BranchExchange exchange); - void visit(CoprocessorDataTransfer transfer); - void visit(CoprocessorDataProcessing processing); - void visit(CoprocessorRegisterTransfer transfer); - void visit(MoveFromStatusRegister register); - void visit(MoveToStatusRegister register); - void visit(CountLeadingZeros zeros); + void visit(DataProcessing instr); + void visit(SingleDataTransfer instr); + void visit(IntMultiply instr); + void visit(LongMultiply instr); + void visit(Swap instr); + void visit(BlockDataTransfer instr); + void visit(SoftwareInterrupt instr); + void visit(Branch instr); + void visit(BranchExchange instr); + void visit(CoprocessorDataTransfer instr); + void visit(CoprocessorDataProcessing instr); + void visit(CoprocessorRegisterTransfer instr); + void visit(MoveFromStatusRegister instr); + void visit(MoveToStatusRegister instr); + void visit(CountLeadingZeros instr); } Added: src/org/binarytranslator/generic/decoder/DisassembledInstruction.java =================================================================== --- src/org/binarytranslator/generic/decoder/DisassembledInstruction.java (rev 0) +++ src/org/binarytranslator/generic/decoder/DisassembledInstruction.java 2007-04-14 13:55:41 UTC (rev 55) @@ -0,0 +1,33 @@ +package org.binarytranslator.generic.decoder; + +/** + * Represents a disassembled instruction. + * + * @author Michael Baer + */ +public interface DisassembledInstruction { + /** + * Shall return the address of the instruction following this one in <i>code order</i>, given that + * the current instruction has been decoded from address <code>pc</code>. + * @param pc + * The address from which this instruction has been decoded. + * @return + * The address of the instruction following this one in code order. + */ + int getSuccessor(int pc); + + /** + * Shall return a string representation of the disassembled instruction. + * We might have used toString() here, but I wanted it to be obvious if a dedicated implementation + * of this method is missing. + * + * @return + * A string representation of the disassembled instruction. + * For example: + * <code> + * ADD r0, r1, #15 + * </code> + * for an ARM ADD instruction. + */ + public String asString(); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cap...@us...> - 2007-04-14 12:04:53
|
Revision: 54 http://svn.sourceforge.net/pearcolator/?rev=54&view=rev Author: captain5050 Date: 2007-04-14 05:04:52 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Modify code format Modified Paths: -------------- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-14 11:35:53 UTC (rev 53) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-04-14 12:04:52 UTC (rev 54) @@ -4,7 +4,7 @@ * A copy of the license is included in the distribution, and is also * available at http://www.opensource.org/licenses/cpl1.0.php * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + * (C) Copyright Ian Rogers, The University of Manchester 2003-2007 */ package org.binarytranslator.arch.x86.decoder; @@ -82,52 +82,52 @@ private static final X86_InstructionDecoder[] primaryOpcodes = { /* OPCD Decoder */ /* 0x00 */new X86_Add_OpcodeDecoder(8, true, 0, true), // 8bit, has - // ModRM, no imm, - // rm is dest + // ModRM, no imm, + // rm is dest /* 0x01 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest + // ModRM, + // no + // imm, + // rm + // is + // dest /* 0x02 */new X86_Add_OpcodeDecoder(8, true, 0, false),// 8bit, has - // ModRM, no imm, - // rm is src + // ModRM, no imm, + // rm is src /* 0x03 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src + // ModRM, + // no + // imm, + // rm + // is + // src /* 0x04 */new X86_Add_OpcodeDecoder(8, false, 8, false),// 8bit, no ModRM, - // 8bit imm + // 8bit imm /* 0x05 */new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 : 32, false),// 16/32bit, no ModRM, 16/32bit imm /* 0x06 */null, /* 0x07 */null, /* 0x08 */new X86_Or_OpcodeDecoder(8, true, 0, true), // 8bit, has ModRM, - // no imm, rm is - // dest + // no imm, rm is + // dest /* 0x09 */new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest + // ModRM, + // no + // imm, + // rm + // is + // dest /* 0x0A */new X86_Or_OpcodeDecoder(8, true, 0, false),// 8bit, has ModRM, - // no imm, rm is src + // no imm, rm is src /* 0x0B */new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src + // ModRM, + // no + // imm, + // rm + // is + // src /* 0x0C */new X86_Or_OpcodeDecoder(8, false, 8, false),// 8bit, no ModRM, - // 8bit imm + // 8bit imm /* 0x0D */new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 : 32, false),// 16/32bit, no ModRM, 16/32bit imm /* 0x0E */null, @@ -151,106 +151,106 @@ /* 0x1F */null, /* 0x20 */new X86_And_OpcodeDecoder(8, true, 0, true), // 8bit, has - // ModRM, no imm, - // rm is dest + // ModRM, no imm, + // rm is dest /* 0x21 */new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest + // ModRM, + // no + // imm, + // rm + // is + // dest /* 0x22 */new X86_And_OpcodeDecoder(8, true, 0, false),// 8bit, has - // ModRM, no imm, - // rm is src + // ModRM, no imm, + // rm is src /* 0x23 */new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src + // ModRM, + // no + // imm, + // rm + // is + // src /* 0x24 */new X86_And_OpcodeDecoder(8, false, 8, false),// 8bit, no ModRM, - // 8bit imm + // 8bit imm /* 0x25 */new X86_And_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 : 32, false),// 16/32bit, no ModRM, 16/32bit imm /* 0x26 */new X86_ES_SegmentOverride_PrefixDecoder(), /* 0x27 */null, /* 0x28 */new X86_Sub_OpcodeDecoder(8, true, 0, true), // 8bit, has - // ModRM, no imm, - // rm is dest + // ModRM, no imm, + // rm is dest /* 0x29 */new X86_Sub_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest + // ModRM, + // no + // imm, + // rm + // is + // dest /* 0x2A */new X86_Sub_OpcodeDecoder(8, true, 0, false),// 8bit, has - // ModRM, no imm, - // rm is src + // ModRM, no imm, + // rm is src /* 0x2B */new X86_Sub_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src + // ModRM, + // no + // imm, + // rm + // is + // src /* 0x2C */new X86_Sub_OpcodeDecoder(8, false, 8, false),// 8bit, no ModRM, - // 8bit imm + // 8bit imm /* 0x2D */new X86_Sub_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 : 32, false),// 16/32bit, no ModRM, 16/32bit imm /* 0x2E */new X86_CS_SegmentOverride_PrefixDecoder(), /* 0x2F */null, /* 0x30 */new X86_Xor_OpcodeDecoder(8, true, 0, true), // 8bit, has - // ModRM, no imm, - // rm is dest + // ModRM, no imm, + // rm is dest /* 0x31 */new X86_Xor_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest + // ModRM, + // no + // imm, + // rm + // is + // dest /* 0x32 */new X86_Xor_OpcodeDecoder(8, true, 0, false),// 8bit, has - // ModRM, no imm, - // rm is src + // ModRM, no imm, + // rm is src /* 0x33 */new X86_Xor_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src + // ModRM, + // no + // imm, + // rm + // is + // src /* 0x34 */new X86_Xor_OpcodeDecoder(8, false, 8, false),// 8bit, no ModRM, - // 8bit imm + // 8bit imm /* 0x35 */new X86_Xor_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 : 32, false),// 16/32bit, no ModRM, 16/32bit imm /* 0x36 */new X86_SS_SegmentOverride_PrefixDecoder(), /* 0x37 */null, /* 0x38 */new X86_Cmp_OpcodeDecoder(8, true, 0, true), // 8bit, has - // ModRM, no imm, - // rm is dest + // ModRM, no imm, + // rm is dest /* 0x39 */new X86_Cmp_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest + // ModRM, + // no + // imm, + // rm + // is + // dest /* 0x3A */new X86_Cmp_OpcodeDecoder(8, true, 0, false),// 8bit, has - // ModRM, no imm, - // rm is src + // ModRM, no imm, + // rm is src /* 0x3B */new X86_Cmp_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src + // ModRM, + // no + // imm, + // rm + // is + // src /* 0x3C */new X86_Cmp_OpcodeDecoder(8, false, 8, false),// 8bit, no ModRM, - // 8bit imm + // 8bit imm /* 0x3D */new X86_Cmp_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 : 32, false),// 16/32bit, no ModRM, 16/32bit imm /* 0x3E */new X86_DS_SegmentOverride_PrefixDecoder(), @@ -316,7 +316,7 @@ /* 0x66 */new X86_OperandSizeOverride_PrefixDecoder(), /* 0x67 */new X86_AddressSizeOverride_PrefixDecoder(), /* 0x68 */new X86_Push_OpcodeDecoder(_16BIT ? -16 : -32), // Push 16/32bit - // immediate + // immediate /* 0x69 */null, /* 0x6A */new X86_Push_OpcodeDecoder(-8), // Push 8bit immediate /* 0x6B */null, @@ -343,13 +343,13 @@ /* 0x7F */new X86_Jcc_OpcodeDecoder(GREATER, 8), /* 0x80 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 8bit, - // ModRM, - // 8bit - // imm, - // rm - // is - // dest - new X86_Add_OpcodeDecoder(8, true, 8, true),// 0 + // ModRM, + // 8bit + // imm, + // rm + // is + // dest + new X86_Add_OpcodeDecoder(8, true, 8, true),// 0 new X86_Or_OpcodeDecoder(8, true, 8, true),// 1 new X86_Adc_OpcodeDecoder(8, true, 8, true),// 2 new X86_Sbb_OpcodeDecoder(8, true, 8, true),// 3 @@ -359,12 +359,12 @@ new X86_Cmp_OpcodeDecoder(8, true, 8, true) // 7 }), /* 0x81 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 16/32bit, - // ModRM, - // 16/32bit - // imm, - // rm - // is - // dest + // ModRM, + // 16/32bit + // imm, + // rm + // is + // dest new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 : 32, true),// 0 new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, @@ -384,13 +384,13 @@ }), /* 0x82 */null, /* 0x83 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 16/32bit, - // ModRM, - // 8bit - // imm, - // rm - // is - // dest - new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 0 + // ModRM, + // 8bit + // imm, + // rm + // is + // dest + new X86_Add_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 0 new X86_Or_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 1 new X86_Adc_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 2 new X86_Sbb_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 3 @@ -400,33 +400,33 @@ new X86_Cmp_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true) // 7 }), /* 0x84 */new X86_Test_OpcodeDecoder(8, true, 0), // 8bit, has ModRM, no - // imm + // imm /* 0x85 */new X86_Test_OpcodeDecoder(_16BIT ? 16 : 32, true, 0), // 16/32bit,has - // ModRM, - // no - // imm + // ModRM, + // no + // imm /* 0x86 */null, /* 0x87 */null, /* 0x88 */new X86_Mov_OpcodeDecoder(8, true, 0, true), // 8bit, has - // ModRM, no imm, - // rm is dest + // ModRM, no imm, + // rm is dest /* 0x89 */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // dest + // ModRM, + // no + // imm, + // rm + // is + // dest /* 0x8A */new X86_Mov_OpcodeDecoder(8, true, 0, false),// 8bit, has - // ModRM, no imm, - // rm is src + // ModRM, no imm, + // rm is src /* 0x8B */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false),// 16/32bit,has - // ModRM, - // no - // imm, - // rm - // is - // src + // ModRM, + // no + // imm, + // rm + // is + // src /* 0x8C */null, /* 0x8D */new X86_Lea_OpcodeDecoder(), /* 0x8E */null, @@ -460,12 +460,12 @@ /* 0xA0 */new X86_Mov_OpcodeDecoder(8, true), // mov al, [disp8] /* 0xA1 */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, false),// mov - // [e]ax, - // [disp(16|32)] + // [e]ax, + // [disp(16|32)] /* 0xA2 */new X86_Mov_OpcodeDecoder(8, false), // mov [disp8], al /* 0xA3 */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, true), // mov - // [disp(16|32)], - // eax + // [disp(16|32)], + // eax /* 0xA4 */null, /* 0xA5 */null, /* 0xA6 */null, @@ -488,21 +488,21 @@ /* 0xB6 */new X86_Mov_OpcodeDecoder(6, 8), // reg, 8bit immediate /* 0xB7 */new X86_Mov_OpcodeDecoder(7, 8), // reg, 8bit immediate /* 0xB8 */new X86_Mov_OpcodeDecoder(0, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate + // immediate /* 0xB9 */new X86_Mov_OpcodeDecoder(1, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate + // immediate /* 0xBA */new X86_Mov_OpcodeDecoder(2, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate + // immediate /* 0xBB */new X86_Mov_OpcodeDecoder(3, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate + // immediate /* 0xBC */new X86_Mov_OpcodeDecoder(4, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate + // immediate /* 0xBD */new X86_Mov_OpcodeDecoder(5, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate + // immediate /* 0xBE */new X86_Mov_OpcodeDecoder(6, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate + // immediate /* 0xBF */new X86_Mov_OpcodeDecoder(7, _16BIT ? 16 : 32), // reg, 16/32bit - // immediate + // immediate /* 0xC0 */null, /* 0xC1 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] { @@ -511,43 +511,43 @@ null, // 2 null, // 3 new X86_Shl_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true), // 4 - - // 16/32bit, - // has - // ModRM, - // 8bit - // imm, rm - // is dest + // 16/32bit, + // has + // ModRM, + // 8bit + // imm, rm + // is dest new X86_Ushr_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true),// 5 - - // 16/32bit, - // has - // ModRM, - // 8bit - // imm, rm - // is dest + // 16/32bit, + // has + // ModRM, + // 8bit + // imm, rm + // is dest null, // 6 new X86_Shr_OpcodeDecoder(_16BIT ? 16 : 32, true, 8, true) // 7 - - // 16/32bit, - // has - // ModRM, - // 8bit - // imm, rm - // is dest + // 16/32bit, + // has + // ModRM, + // 8bit + // imm, rm + // is dest }), /* 0xC2 */new X86_Ret_OpcodeDecoder(false, 16), // near return, 16bit - // immediate + // immediate /* 0xC3 */new X86_Ret_OpcodeDecoder(false, 0), // near return, no - // immediate + // immediate /* 0xC4 */null, /* 0xC5 */null, /* 0xC6 */new X86_Mov_OpcodeDecoder(8, true, 8, true), // 8bit, has - // ModRM, 8bit - // imm, rm is dest + // ModRM, 8bit + // imm, rm is dest /* 0xC7 */new X86_Mov_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 : 32, true), // 16/32bit, has ModRM, 16/32bit imm, rm is dest /* 0xC8 */null, /* 0xC9 */new X86_Leave_OpcodeDecoder(), /* 0xCA */new X86_Ret_OpcodeDecoder(true, 16), // far return, 16bit - // immediate + // immediate /* 0xCB */new X86_Ret_OpcodeDecoder(true, 0), // far return, no immediate /* 0xCC */null, /* 0xCD */new X86_Int_OpcodeDecoder(), @@ -563,27 +563,27 @@ null, // 2 null, // 3 new X86_Shl_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true), // 4 - - // 16/32bit, - // has - // ModRM, - // no imm, - // rm is - // dest + // 16/32bit, + // has + // ModRM, + // no imm, + // rm is + // dest new X86_Ushr_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true),// 5 - - // 16/32bit, - // has - // ModRM, - // no imm, - // rm is - // dest + // 16/32bit, + // has + // ModRM, + // no imm, + // rm is + // dest null, // 6 new X86_Shr_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, true) // 7 - - // 16/32bit, - // has - // ModRM, - // no imm, - // rm is - // dest + // 16/32bit, + // has + // ModRM, + // no imm, + // rm is + // dest }), /* 0xD4 */null, /* 0xD5 */null, @@ -618,12 +618,12 @@ /* 0xE8 */new X86_Call_OpcodeDecoder(_16BIT ? 16 : 32, false, _16BIT ? 16 : 32, false), // 16/32bit, no ModRM, 16/32bit imm /* 0xE9 */new X86_Jmp_OpcodeDecoder(false, _16BIT ? 16 : 32), // relative - // jump + - // 16/32bit - // immediate + // jump + + // 16/32bit + // immediate /* 0xEA */null, /* 0xEB */new X86_Jmp_OpcodeDecoder(false, 8), // relative jump + 8bit - // immediate + // immediate /* 0xEC */null, /* 0xED */null, /* 0xEE */null, @@ -636,13 +636,13 @@ /* 0xF4 */null, /* 0xF5 */null, /* 0xF6 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 8bit, - // ModRM, - // 8bit - // imm, - // rm - // is - // dest - new X86_Test_OpcodeDecoder(8, true, 8), // 0 + // ModRM, + // 8bit + // imm, + // rm + // is + // dest + new X86_Test_OpcodeDecoder(8, true, 8), // 0 null, // 1 new X86_Not_OpcodeDecoder(8), // 2 - 8bit new X86_Neg_OpcodeDecoder(8), // 3 - 8bit @@ -652,13 +652,14 @@ null // 7 }), /* 0xF7 */new X86_OpcodeInModRMReg_Decoder(new X86_OpcodeDecoder[] {// 16/32bit, - // ModRM, - // 16/32bit - // imm, - // rm - // is - // dest - new X86_Test_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 : 32),// 0 + // ModRM, + // 16/32bit + // imm, + // rm + // is + // dest + new X86_Test_OpcodeDecoder(_16BIT ? 16 : 32, true, _16BIT ? 16 + : 32),// 0 null, // 1 new X86_Not_OpcodeDecoder(_16BIT ? 16 : 32), // 2 - 16/32bit new X86_Neg_OpcodeDecoder(_16BIT ? 16 : 32), // 3 - 16/32bit @@ -678,10 +679,10 @@ new X86_Inc_OpcodeDecoder(-1), // 0 - Inc of memory operand null, // 1 new X86_Call_OpcodeDecoder(_16BIT ? 16 : 32, true, 0, false), // 2 - - // 16/32bit, - // ModRM, - // no - // imm + // 16/32bit, + // ModRM, + // no + // imm null, // 3 new X86_Jmp_OpcodeDecoder(true, 0), // 4 - near absolute jump to ModRM null, // 5 @@ -730,11 +731,8 @@ /** * Disassemble a single instruction - * - * @param ps - * the process space of the translation - * @param pc - * the address of the instruction to translate + * @param ps the process space of the translation + * @param pc the address of the instruction to translate * @return the string for this instruction */ public String disassemble(ProcessSpace ps, int pc) { @@ -743,13 +741,9 @@ /** * Translate a single instruction - * - * @param translationHelper - * the object containing the translation sequence - * @param ps - * the process space of the translation - * @param pc - * the address of the instruction to translate + * @param translationHelper the object containing the translation sequence + * @param ps the process space of the translation + * @param pc the address of the instruction to translate * @return the address of the next instruction or -1 if this instruction has * branched to the end of the trace */ @@ -761,13 +755,9 @@ /** * Translate a single instruction which doesn't already have a decoder - * - * @param translationHelper - * the object containing the translation sequence - * @param ps - * the process space of the translation - * @param pc - * the address of the instruction to translate + * @param translationHelper the object containing the translation sequence + * @param ps the process space of the translation + * @param pc the address of the instruction to translate * @return the address of the next instruction or -1 if this instruction has * branched to the end of the trace */ @@ -782,9 +772,7 @@ /** * Interpret a single instruction - * - * @param ps - * the process space of the interpretation, contains the fetched + * @param ps the process space of the interpretation, contains the fetched * instruction and instruction address * @return the next instruction interpreter */ @@ -899,13 +887,9 @@ /** * Translate a single instruction - * - * @param translationHelper - * the object containing the translation sequence - * @param ps - * the process space of the translation - * @param pc - * the address of the instruction to translate + * @param translationHelper the object containing the translation sequence + * @param ps the process space of the translation + * @param pc the address of the instruction to translate * @return the address of the next instruction or -1 if this instruction has * branched to the end of the trace */ @@ -926,11 +910,8 @@ /** * Disassemble a single instruction - * - * @param ps - * the process space of the translation - * @param pc - * the address of the instruction to translate + * @param ps the process space of the translation + * @param pc the address of the instruction to translate * @return the string for this instruction */ public String disassemble(ProcessSpace ps, int pc) { @@ -1350,18 +1331,15 @@ /** * Constructor - * - * @param operandSize - * size of register/mem/immediate operands - * @param hasModRM - * does a ModRM byte follow the opcode possibly giving more + * @param operandSize size of register/mem/immediate operands + * @param hasModRM does a ModRM byte follow the opcode possibly giving more * information on the opcode as well as defining register and memory * operands? - * @param immediateSize - * the size in bits of any immediate or 0 if no immediate value - * @param isMemoryOperandDestination - * is the destination/result of this instruction a memory or register - * in the case that there's a ModRM byte + * @param immediateSize the size in bits of any immediate or 0 if no immediate + * value + * @param isMemoryOperandDestination is the destination/result of this + * instruction a memory or register in the case that there's a ModRM + * byte */ X86_OpcodeDecoder(int operandSize, boolean hasModRM, int immediateSize, boolean isMemoryOperandDestination) { @@ -1377,28 +1355,24 @@ /** * Constructor - * - * @param operandSize - * size of register/mem/immediate operands - * @param hasModRM - * does a ModRM byte follow the opcode possibly giving more + * @param operandSize size of register/mem/immediate operands + * @param hasModRM does a ModRM byte follow the opcode possibly giving more * information on the opcode as well as defining register and memory * operands? - * @param immediateSize - * the size in bits of any immediate or 0 if no immediate value - * @param isMemoryOperandDestination - * is the destination/result of this instruction a memory or register - * in the case that there's a ModRM byte - * @param register - * override EAX as the implicit register for an instruction not - * specifying modrm + * @param immediateSize the size in bits of any immediate or 0 if no immediate + * value + * @param isMemoryOperandDestination is the destination/result of this + * instruction a memory or register in the case that there's a ModRM + * byte + * @param register override EAX as the implicit register for an instruction + * not specifying modrm */ X86_OpcodeDecoder(int operandSize, boolean hasModRM, int immediateSize, boolean isMemoryOperandDestination, int register) { this.operandSize = operandSize; this.hasModRM = hasModRM; this.modRMhasOpcode = true; // override the register to show that the reg of - // the modrm is invalid + // the modrm is invalid this.immediateSize = immediateSize; this.isMemoryOperandDestination = isMemoryOperandDestination; this.register = register; @@ -1408,21 +1382,17 @@ /** * Constructor - * - * @param operandSize - * size of register/mem/immediate operands - * @param hasModRM - * does a ModRM byte follow the opcode possibly giving more + * @param operandSize size of register/mem/immediate operands + * @param hasModRM does a ModRM byte follow the opcode possibly giving more * information on the opcode as well as defining register and memory * operands? - * @param immediateSize - * the size in bits of any immediate or 0 if no immediate value - * @param isMemoryOperandDestination - * is the destination/result of this instruction a memory or register - * in the case that there's a ModRM byte - * @param discardResult - * should the result of the operation be written to the destination - * or just the flags modified? + * @param immediateSize the size in bits of any immediate or 0 if no immediate + * value + * @param isMemoryOperandDestination is the destination/result of this + * instruction a memory or register in the case that there's a ModRM + * byte + * @param discardResult should the result of the operation be written to the + * destination or just the flags modified? */ X86_OpcodeDecoder(int operandSize, boolean hasModRM, int immediateSize, boolean isMemoryOperandDestination, boolean discardResult) { @@ -1438,14 +1408,12 @@ /** * Constructor - * - * @param operandSize - * size of register/mem/immediate operands - * @param isMemoryOperandDestination - * is the destination/result of this instruction a memory or register - * in the case that there's a ModRM byte - * @param displacementSize - * a size for a displacement always present regardless of modrm + * @param operandSize size of register/mem/immediate operands + * @param isMemoryOperandDestination is the destination/result of this + * instruction a memory or register in the case that there's a ModRM + * byte + * @param displacementSize a size for a displacement always present regardless + * of modrm */ X86_OpcodeDecoder(int operandSize, boolean isMemoryOperandDestination, int displacementSize) { @@ -1627,32 +1595,20 @@ /** * Perform the actual translation - * * @param translationHelper * @param ps * @param lazy - * @param pc - * the address of the instruction being translated - * @param modrm - * the decoder for any modrm part of the instruction - * @param sib - * the sib decoder for any sib part of the instruction - * @param displacement - * any displacement to be added to the modrm - * @param immediateSize - * what size is the immediate value - * @param immediate - * if immediateSize > 0 then this is the immediate value - * @param length - * the length of the instruction - * @param prefix2 - * a group2 prefix decoder or null - * @param prefix3 - * a group3 prefix decoder or null - * @param prefix4 - * a group4 prefix decoder or null - * @param prefix5 - * a group5 prefix decoder or null + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null */ protected int translate(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, @@ -1808,30 +1764,18 @@ /** * Disassemble the opcode - * * @param ps - * @param pc - * the address of the instruction being translated - * @param modrm - * the decoder for any modrm part of the instruction - * @param sib - * the sib decoder for any sib part of the instruction - * @param displacement - * any displacement to be added to the modrm - * @param immediateSize - * what size is the immediate value - * @param immediate - * if immediateSize > 0 then this is the immediate value - * @param length - * the length of the instruction - * @param prefix2 - * a group2 prefix decoder or null - * @param prefix3 - * a group3 prefix decoder or null - * @param prefix4 - * a group4 prefix decoder or null - * @param prefix5 - * a group5 prefix decoder or null + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null */ protected String disassemble(ProcessSpace ps, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, int displacement, @@ -2111,7 +2055,7 @@ /* 0xB4 */null, /* 0xB5 */null, /* 0xB6 */new X86_MovZX_OpcodeDecoder(_16BIT ? 16 : 32, 8), // dest 16/32bit, - // src 8bit + // src 8bit /* 0xB7 */new X86_MovZX_OpcodeDecoder(32, 16), // dest 32bit, src 16bit /* 0xB8 */null, /* 0xB9 */null, @@ -2120,8 +2064,8 @@ /* 0xBC */null, /* 0xBD */null, /* 0xBE */new X86_MovSX_OpcodeDecoder(_16BIT ? 16 : 32, 8), // dest - // 16/32bit, - // src 8bit + // 16/32bit, + // src 8bit /* 0xBF */new X86_MovSX_OpcodeDecoder(32, 16), // dest 32bit, src 16bit /* 0xC0 */null, @@ -2195,10 +2139,11 @@ /** * Utility to get a decoder for a particular opcode */ - protected static X86_OpcodeDecoder secondaryOpcodeLookup(int opcode) { + protected static X86_InstructionDecoder secondaryOpcodeLookup(int opcode) { if (secondaryOpcodes[opcode] == null) { - throw new Error("Secondary Opcode 0x" + Integer.toHexString(opcode) + System.out.println("Secondary Opcode 0x" + Integer.toHexString(opcode) + " not found"); + return badInstructionDecoder; } else { return secondaryOpcodes[opcode]; } @@ -2764,9 +2709,7 @@ class X86_Pop_OpcodeDecoder extends X86_OpcodeDecoder { /** * Constructor, {@see X86_OpcodeDecoder} - * - * @param reg - * the register to pop into or -1 to show that the destination is a + * @param reg the register to pop into or -1 to show that the destination is a * memory operand */ X86_Pop_OpcodeDecoder(int reg) { @@ -2780,32 +2723,20 @@ /** * Perform the actual translation - * * @param translationHelper * @param ps * @param lazy - * @param pc - * the address of the instruction being translated - * @param modrm - * the decoder for any modrm part of the instruction - * @param sib - * the sib decoder for any sib part of the instruction - * @param displacement - * any displacement to be added to the modrm - * @param immediateSize - * what size is the immediate value - * @param immediate - * if immediateSize > 0 then this is the immediate value - * @param length - * the length of the instruction - * @param prefix2 - * a group2 prefix decoder or null - * @param prefix3 - * a group3 prefix decoder or null - * @param prefix4 - * a group4 prefix decoder or null - * @param prefix5 - * a group5 prefix decoder or null + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null */ protected int translate(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, @@ -2853,30 +2784,18 @@ /** * Disassemble the opcode - * * @param ps - * @param pc - * the address of the instruction being translated - * @param modrm - * the decoder for any modrm part of the instruction - * @param sib - * the sib decoder for any sib part of the instruction - * @param displacement - * any displacement to be added to the modrm - * @param immediateSize - * what size is the immediate value - * @param immedate - * if immediateSize > 0 then this is the immediate value - * @param length - * the length of the instruction - * @param prefix2 - * a group2 prefix decoder or null - * @param prefix3 - * a group3 prefix decoder or null - * @param prefix4 - * a group4 prefix decoder or null - * @param prefix5 - * a group5 prefix decoder or null + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immedate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null */ protected String disassemble(ProcessSpace ps, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, int displacement, @@ -2913,10 +2832,8 @@ class X86_Push_OpcodeDecoder extends X86_OpcodeDecoder { /** * Constructor, {@see X86_OpcodeDecoder} - * - * @param reg - * the register to push into, or -1 to show that the destination is a - * memory operand, or -8/-16/-32 to show that this is an immediate + * @param reg the register to push into, or -1 to show that the destination is + * a memory operand, or -8/-16/-32 to show that this is an immediate * push of the appropriate size */ X86_Push_OpcodeDecoder(int reg) { @@ -2930,32 +2847,20 @@ /** * Perform the actual translation - * * @param translationHelper * @param ps * @param lazy - * @param pc - * the address of the instruction being translated - * @param modrm - * the decoder for any modrm part of the instruction - * @param sib - * the sib decoder for any sib part of the instruction - * @param displacement - * any displacement to be added to the modrm - * @param immediateSize - * what size is the immediate value - * @param immediate - * if immediateSize > 0 then this is the immediate value - * @param length - * the length of the instruction - * @param prefix2 - * a group2 prefix decoder or null - * @param prefix3 - * a group3 prefix decoder or null - * @param prefix4 - * a group4 prefix decoder or null - * @param prefix5 - * a group5 prefix decoder or null + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null */ protected int translate(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, @@ -3007,30 +2912,18 @@ /** * Disassemble the opcode - * * @param ps - * @param pc - * the address of the instruction being translated - * @param modrm - * the decoder for any modrm part of the instruction - * @param sib - * the sib decoder for any sib part of the instruction - * @param displacement - * any displacement to be added to the modrm - * @param immediateSize - * what size is the immediate value - * @param immedate - * if immediateSize > 0 then this is the immediate value - * @param length - * the length of the instruction - * @param prefix2 - * a group2 prefix decoder or null - * @param prefix3 - * a group3 prefix decoder or null - * @param prefix4 - * a group4 prefix decoder or null - * @param prefix5 - * a group5 prefix decoder or null + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immedate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null */ protected String disassemble(ProcessSpace ps, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, int displacement, @@ -3085,32 +2978,20 @@ /** * Perform the actual translation - * * @param translationHelper * @param ps * @param lazy - * @param pc - * the address of the instruction being translated - * @param modrm - * the decoder for any modrm part of the instruction - * @param sib - * the sib decoder for any sib part of the instruction - * @param displacement - * any displacement to be added to the modrm - * @param immediateSize - * what size is the immediate value - * @param immediate - * if immediateSize > 0 then this is the immediate value - * @param length - * the length of the instruction - * @param prefix2 - * a group2 prefix decoder or null - * @param prefix3 - * a group3 prefix decoder or null - * @param prefix4 - * a group4 prefix decoder or null - * @param prefix5 - * a group5 prefix decoder or null + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null */ protected int translate(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, @@ -3148,30 +3029,18 @@ /** * Disassemble the opcode - * * @param ps - * @param pc - * the address of the instruction being translated - * @param modrm - * the decoder for any modrm part of the instruction - * @param sib - * the sib decoder for any sib part of the instruction - * @param displacement - * any displacement to be added to the modrm - * @param immediateSize - * what size is the immediate value - * @param immedate - * if immediateSize > 0 then this is the immediate value - * @param length - * the length of the instruction - * @param prefix2 - * a group2 prefix decoder or null - * @param prefix3 - * a group3 prefix decoder or null - * @param prefix4 - * a group4 prefix decoder or null - * @param prefix5 - * a group5 prefix decoder or null + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immedate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null */ protected String disassemble(ProcessSpace ps, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, int displacement, @@ -3196,32 +3065,20 @@ /** * Perform the actual translation - * * @param translationHelper * @param ps * @param lazy - * @param pc - * the address of the instruction being translated - * @param modrm - * the decoder for any modrm part of the instruction - * @param sib - * the sib decoder for any sib part of the instruction - * @param displacement - * any displacement to be added to the modrm - * @param immediateSize - * what size is the immediate value - * @param immediate - * if immediateSize > 0 then this is the immediate value - * @param length - * the length of the instruction - * @param prefix2 - * a group2 prefix decoder or null - * @param prefix3 - * a group3 prefix decoder or null - * @param prefix4 - * a group4 prefix decoder or null - * @param prefix5 - * a group5 prefix decoder or null + * @param pc the address of the instruction being translated + * @param modrm the decoder for any modrm part of the instruction + * @param sib the sib decoder for any sib part of the instruction + * @param displacement any displacement to be added to the modrm + * @param immediateSize what size is the immediate value + * @param immediate if immediateSize > 0 then this is the immediate value + * @param length the length of the instruction + * @param prefix2 a group2 prefix decoder or null + * @param prefix3 a group3 prefix decoder or null + * @param prefix4 a group4 prefix decoder or null + * @param prefix5 a group5 prefix decoder or null */ protected int translate(X862IR translationHelper, ProcessSpace ps, X86_Laziness lazy, int pc, X86_ModRM_Decoder modrm, X86_SIB_Decoder sib, @@ -3282,30 +3139,18 @@ /** * Disassemble the opcode - * * @param ps - * @param pc - * the address of the instruction being translated - * @param modrm - * the decoder for any modrm part of the instruction - * @param sib - * the sib decoder for any sib part of the instruction - * @param displacement - * any displacement to be added to the modrm - * @param immediateSize - * what size is the immediate value - * @param immediate - * if immediateSize > 0 then this is the immediate value - * @param length - * the length of the instruction - * @param prefix2 - * a group2 prefix decoder or null - * @param prefix3 - * a group3 prefix decoder or null - * @param prefix4 - * ... [truncated message content] |
From: <cap...@us...> - 2007-04-14 11:35:55
|
Revision: 53 http://svn.sourceforge.net/pearcolator/?rev=53&view=rev Author: captain5050 Date: 2007-04-14 04:35:53 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Clear up compiler warnings running current test code Modified Paths: -------------- src/org/binarytranslator/DBT.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/vmInterface/DBT_Trace.java Modified: src/org/binarytranslator/DBT.java =================================================================== --- src/org/binarytranslator/DBT.java 2007-04-14 10:17:47 UTC (rev 52) +++ src/org/binarytranslator/DBT.java 2007-04-14 11:35:53 UTC (rev 53) @@ -1,33 +1,60 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright The University of Manchester 2003-2007 + */ package org.binarytranslator; import org.jikesrvm.VM; +import org.vmmagic.pragma.Uninterruptible; +/** + * Common utility routines for the running DBT. Generally this class is dressing + * up methods from org.jikesrvm.VM. + */ public final class DBT { - public static final boolean VerifyAssertions = true; - + /** Should the following assertion be checked? */ + public static final boolean VerifyAssertions = VM.VerifyAssertions; + + /** + * Assert the following condition is true, if false then fail with stack trace + * @param cond the condition that should be true + */ public static void _assert(boolean cond) { - - if (!VerifyAssertions) - return; - - if (VM.VerifyAssertions) + if (!VerifyAssertions) { + // Checking an assertion in a production build is a bad idea + fail("Assertion checked when assertions should be disabled.\n" + + "Please guard the assertion with DBT.VerifyAssertions"); + } else { VM._assert(cond); - else - { - if (!cond) { - //assertion failed, see if we can get some info on where the assertion occurred - StackTraceElement[] trace = Thread.currentThread().getStackTrace(); - - if (trace.length > 0) { - StackTraceElement source = trace[trace.length-1]; - System.err.println("Assertion failed in: " + source.getFileName() + "(" + source.getLineNumber() + ")"); - } - else { - System.err.println("Assertion failed. No stack trace on assertion source available."); - } - - System.exit(-1); - } } } + + /** + * Exit and print stack trace + * @param message failure message + */ + @Uninterruptible + public static void fail(String message) { + VM.sysFail(message); + } + + /** + * Write the given message + */ + @Uninterruptible + public static void write(String message) { + VM.write(message); + } + + /** + * Write the given int + */ + @Uninterruptible + public static void write(int message) { + VM.write(message); + } } Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-04-14 10:17:47 UTC (rev 52) +++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-04-14 11:35:53 UTC (rev 53) @@ -18,6 +18,7 @@ import org.jikesrvm.classloader.VM_MethodReference; import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.ir.*; +import org.vmmagic.pragma.Uninterruptible; /** * CallBasedMemory abstraction: @@ -415,6 +416,7 @@ * @param callAddress * the address associated with this call */ + @Uninterruptible public VM_MethodReference getMethodRef(int callAddress) { switch (callAddress) { case DBT_Trace.MEMORY_STORE8: Modified: src/org/binarytranslator/generic/memory/Memory.java =================================================================== --- src/org/binarytranslator/generic/memory/Memory.java 2007-04-14 10:17:47 UTC (rev 52) +++ src/org/binarytranslator/generic/memory/Memory.java 2007-04-14 11:35:53 UTC (rev 53) @@ -12,6 +12,7 @@ import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; import org.jikesrvm.classloader.VM_MethodReference; import org.binarytranslator.vmInterface.TranslationHelper; +import org.vmmagic.pragma.Uninterruptible; import java.io.RandomAccessFile; /** @@ -291,6 +292,7 @@ * @param callAddress * the address associated with this call */ + @Uninterruptible public VM_MethodReference getMethodRef(int callAddress) { throw new Error("Error linking method at " + callAddress + " for memory model " + this.getClass()); Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-14 10:17:47 UTC (rev 52) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-04-14 11:35:53 UTC (rev 53) @@ -11,6 +11,7 @@ import org.binarytranslator.generic.decoder.DecoderUtils; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DummyDynamicCodeRunner; +import org.binarytranslator.DBT; import org.jikesrvm.compilers.common.VM_CompiledMethod; import org.jikesrvm.compilers.common.VM_CompiledMethods; import org.jikesrvm.classloader.VM_NormalMethod; @@ -230,7 +231,8 @@ .asMethodReference(), JBC_invokevirtual); break; case BAD_INSTRUCTION_NEW: - throw new Error("Todo: dynamic linking for new bad instruction exception"); + DBT.fail("Todo: dynamic linking for new bad instruction exception"); + break; case BAD_INSTRUCTION_INIT: dynamicLink.set(DecoderUtils.badInstrKlassInitMethod.getMemberRef() .asMethodReference(), JBC_invokevirtual); @@ -246,9 +248,8 @@ dynamicLink.set(ps.memory.getMethodRef(bcIndex), JBC_invokevirtual); break; default: - throw new Error( - "Trying to dynamic link inside a DBT trace for an unknown dynamic link location: 0x" - + Integer.toHexString(bcIndex)); + DBT.write(bcIndex); + DBT.fail("Trying to dynamic link inside a DBT trace for an unknown dynamic link location"); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-14 10:17:47
|
Revision: 52 http://svn.sourceforge.net/pearcolator/?rev=52&view=rev Author: michael_baer Date: 2007-04-14 03:17:47 -0700 (Sat, 14 Apr 2007) Log Message: ----------- PPC_InstructionDecoder does not actually implement InstructionDecoder and therefore shouldn't pretend it did. Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-14 09:58:24 UTC (rev 51) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-14 10:17:47 UTC (rev 52) @@ -12,7 +12,6 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; import org.binarytranslator.generic.branch.BranchLogic; -import org.binarytranslator.generic.decoder.InstructionDecoder; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.Binary; @@ -40,7 +39,7 @@ * This class is the super class of all instruction translators, it implements * default methods that just throw errors */ -public class PPC_InstructionDecoder extends InstructionDecoder implements +public class PPC_InstructionDecoder implements OPT_Operators { /* Different instruction formats */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-14 09:58:33
|
Revision: 51 http://svn.sourceforge.net/pearcolator/?rev=51&view=rev Author: michael_baer Date: 2007-04-14 02:58:24 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Protected DecoderUtils.numberOfInstructions Introduced usage of generic ArrayList in PPC2IR Modified Paths: -------------- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/generic/decoder/DecoderUtils.java Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-04-14 09:55:45 UTC (rev 50) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-04-14 09:58:24 UTC (rev 51) @@ -962,7 +962,7 @@ * Return an array of unused registers */ protected OPT_Register[] getUnusedRegisters() { - ArrayList unusedRegisterList = new ArrayList(); + ArrayList<OPT_Register> unusedRegisterList = new ArrayList<OPT_Register>(); for (int i = 0; i < 32; i++) { if (intRegInUseMap[i] == false) { unusedRegisterList.add(intRegMap[i]); Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-14 09:55:45 UTC (rev 50) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-04-14 09:58:24 UTC (rev 51) @@ -268,7 +268,7 @@ if (DBT_Options.debugInstr) { System.out.println(lazy.makeKey(pc) + PPC_Disassembler.disasm(instr, pc) - + " " + ppc2ir.getCurrentBlock() + " " + ppc2ir.numberOfInstructions); + + " " + ppc2ir.getCurrentBlock() + " " + ppc2ir.getNumInstructions()); } int primaryOpcode = bits(instr, 0, 5); Modified: src/org/binarytranslator/generic/decoder/DecoderUtils.java =================================================================== --- src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-14 09:55:45 UTC (rev 50) +++ src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-04-14 09:58:24 UTC (rev 51) @@ -29,7 +29,30 @@ import org.jikesrvm.classloader.VM_MethodReference; import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.OPT_Constants; -import org.jikesrvm.compilers.opt.ir.*; +import org.jikesrvm.compilers.opt.ir.Athrow; +import org.jikesrvm.compilers.opt.ir.BBend; +import org.jikesrvm.compilers.opt.ir.Call; +import org.jikesrvm.compilers.opt.ir.Goto; +import org.jikesrvm.compilers.opt.ir.IfCmp; +import org.jikesrvm.compilers.opt.ir.LookupSwitch; +import org.jikesrvm.compilers.opt.ir.Move; +import org.jikesrvm.compilers.opt.ir.New; +import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_BasicBlock; +import org.jikesrvm.compilers.opt.ir.OPT_BranchOperand; +import org.jikesrvm.compilers.opt.ir.OPT_BranchProfileOperand; +import org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand; +import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; +import org.jikesrvm.compilers.opt.ir.OPT_Instruction; +import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_MethodOperand; +import org.jikesrvm.compilers.opt.ir.OPT_Operand; +import org.jikesrvm.compilers.opt.ir.OPT_Operator; +import org.jikesrvm.compilers.opt.ir.OPT_Operators; +import org.jikesrvm.compilers.opt.ir.OPT_Register; +import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TrueGuardOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TypeOperand; /** * A collection of common tools used by decoders. The public entry point for the @@ -107,12 +130,10 @@ .resolveInvokeSpecial(); } - // -oO Global IR Oo- - /** * Number of translated instructions */ - public int numberOfInstructions; + private int numberOfInstructions; /** * The process space object used by the running PPC binary. @@ -237,8 +258,6 @@ */ protected abstract void report(String str); - // -oO Important entry points Oo- - /** * Constructor * @@ -284,6 +303,11 @@ unresolvedLookupSwitchForSwitches_Laziness = new ArrayList<Laziness>(); unresolvedLookupSwitchForSwitches_WasCall = new ArrayList<Boolean>(); } + + /** Returns the number of previously translated instructions within this trace. */ + public int getNumInstructions() { + return numberOfInstructions; + } /** * This is the main loop to generate the HIR. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-14 09:55:47
|
Revision: 50 http://svn.sourceforge.net/pearcolator/?rev=50&view=rev Author: michael_baer Date: 2007-04-14 02:55:45 -0700 (Sat, 14 Apr 2007) Log Message: ----------- Removed unused DBT_ConvertBinaryToHIR Removed Paths: ------------- src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java Deleted: src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java 2007-04-14 09:35:23 UTC (rev 49) +++ src/org/binarytranslator/vmInterface/DBT_ConvertBinaryToHIR.java 2007-04-14 09:55:45 UTC (rev 50) @@ -1,135 +0,0 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.vmInterface; - - -import org.jikesrvm.VM_Configuration; -import org.jikesrvm.compilers.opt.*; -import org.jikesrvm.compilers.opt.ir.*; -import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*; - -/** - * The OPT_CompilerPhase which translates from PowerPC machine code into HIR. It - * is used in PPC_OptimizationPlanner (in place of OPT_ConvertBCtoHIR and - * OPT_OptimizationPlanner). - * - * @author Richard Matley, Ian Rogers - * - */ -public abstract class DBT_ConvertBinaryToHIR extends OPT_CompilerPhase { - - public DBT_ConvertBinaryToHIR() { - } - - /** - * Return a String describing this compiler phase. - */ - public final String getName() { - return "Generate HIR from machine code"; - } - - /** - * Generate HIR from a block of machine code. - */ - public final void perform(OPT_IR ir) { - OPT_GenerationContext gc = new OPT_GenerationContext(ir.method, - ir.compiledMethod, ir.options, ir.inlinePlan); - // MC2IR.generateHIR(gc); - generateHIR(gc); - - ir.gc = gc; - ir.cfg = gc.cfg; - ir.regpool = gc.temps; - - if (gc.allocFrame) { - ir.stackManager.forceFrameAllocation(); - } - - // ir now contains well formed HIR, we hope. - ir.IRStage = OPT_IR.HIR; - ir.HIRInfo = new OPT_HIRInfo(ir); - if (OPT_IR.SANITY_CHECK) { - ir.verify("Initial HIR", true); - } - - if (VM_Configuration.BuildForPowerPC) { - eliminateConditionalMoves(ir); - } - } - - protected abstract void generateHIR(OPT_GenerationContext gc); - - /** - * Remove conditional moves - */ - public static void eliminateConditionalMoves(OPT_IR ir) { - OPT_BasicBlock curBB = ir.gc.prologue; - while (curBB != null) { - OPT_Instruction curInstr = curBB.firstInstruction(); - loop_over_instructions: while (BBend.conforms(curInstr) == false) { - if (CondMove.conforms(curInstr) - && (curInstr.operator() == INT_COND_MOVE)) { - OPT_BasicBlock compareBlock; // block containing compare instruction - OPT_BasicBlock trueBlock; // block containing true payload - OPT_BasicBlock falseBlock; // block containing false payload - OPT_BasicBlock restOfBlock; // the rest of the block - - // Set up blocks - compareBlock = curBB; - trueBlock = new OPT_BasicBlock(0, ir.gc.inlineSequence, ir.gc.cfg); - falseBlock = new OPT_BasicBlock(0, ir.gc.inlineSequence, ir.gc.cfg); - restOfBlock = compareBlock.splitNodeAt(curInstr, ir); - ir.gc.cfg.linkInCodeOrder(compareBlock, falseBlock); - ir.gc.cfg.linkInCodeOrder(falseBlock, trueBlock); - ir.gc.cfg.linkInCodeOrder(trueBlock, restOfBlock); - - // Set up values - OPT_RegisterOperand result = CondMove.getResult(curInstr); - OPT_Operand val1 = CondMove.getVal1(curInstr); - OPT_Operand val2 = CondMove.getVal2(curInstr); - OPT_ConditionOperand cond = CondMove.getCond(curInstr); - OPT_Operand trueValue = CondMove.getTrueValue(curInstr); - OPT_Operand falseValue = CondMove.getFalseValue(curInstr); - - // Create comparison - OPT_Operator cmpType; - if (val1.isInt()) { - cmpType = INT_IFCMP; - } else if (val1.isDouble()) { - cmpType = DOUBLE_IFCMP; - } else { - throw new Error("Unexpected type of val1: " + val1); - } - IfCmp.mutate(curInstr, cmpType, null, val1, val2, cond, trueBlock - .makeJumpTarget(), OPT_BranchProfileOperand.likely()); - compareBlock.deleteNormalOut(); - compareBlock.insertOut(trueBlock); - compareBlock.insertOut(falseBlock); - - // Create false code - falseBlock.appendInstruction(Move - .create(INT_MOVE, result, falseValue)); - falseBlock.appendInstruction(Goto.create(GOTO, restOfBlock - .makeJumpTarget())); - falseBlock.insertOut(restOfBlock); - - // Create true code - trueBlock.appendInstruction(Move.create(INT_MOVE, result, trueValue)); - trueBlock.insertOut(restOfBlock); - - // Move along - curBB = restOfBlock; - curInstr = curBB.firstInstruction(); - } - curInstr = curInstr.nextInstructionInCodeOrder(); - } - curBB = curBB.nextBasicBlockInCodeOrder(); - } - } -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |