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. |