From: <mic...@us...> - 2007-04-12 17:32:11
|
Revision: 30 http://svn.sourceforge.net/pearcolator/?rev=30&view=rev Author: michael_baer Date: 2007-04-12 10:31:57 -0700 (Thu, 12 Apr 2007) Log Message: ----------- - Changed ARM instruction decoders to allow traversal using the visitor pattern. - Added Interface ARM_InstructionVisitor, which is to be implemented by visitors Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java Removed Paths: ------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java Deleted: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-12 17:11:46 UTC (rev 29) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-12 17:31:57 UTC (rev 30) @@ -1,163 +0,0 @@ -package org.binarytranslator.arch.arm.decoder; - -import org.binarytranslator.DBT; -import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; -import org.binarytranslator.generic.decoder.InstructionDecoder; -import org.jikesrvm.compilers.opt.ir.*; - -public class ARM_InstructionDecoder extends InstructionDecoder { - - abstract static class BasicDecoder implements OPT_Operators { - /** Return the value of a single bit. Note that the bit is 0-based.*/ - public static final boolean getBit(int word, int bit) { - if (DBT.VerifyAssertions) DBT._assert(bit >= 0 && bit <= 31); - return (word & (1 << bit)) != 0; - } - - /** Transfer a subsequence of bits within (word) into an integer. Note that all bits are 0-based. */ - public 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; - } - - protected abstract int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr); - } - - /** Translates LDR and STR instructions */ - static class LDR_STR_Decoder extends BasicDecoder { - - @Override - protected int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { - boolean immediateOperand = getBit(instr, 25); - boolean preIndex = getBit(instr, 24); - boolean positiveOffset = getBit(instr, 23); - boolean transferByte = getBit(instr, 22); - boolean writeBack = getBit(instr, 21); - boolean loadOperation = getBit(instr, 20); - int offset = getBits(instr, 0, 11); - - int baseRegister = getBits(instr, 16, 19); - int destRegister = getBits(instr, 12, 15); - - System.out.println("Decoding LDR/STR with: "); - System.out.println("Imm: " + immediateOperand); - System.out.println("Pre Index: " + preIndex); - System.out.println("Offset: " + (positiveOffset ? "+" : "-") + offset); - System.out.println("Base: " + baseRegister); - System.out.println("Dest: " + destRegister); - System.out.println("Load Operation: " + loadOperation); - System.out.println("Write back: " + writeBack); - - //we are only handling a limitied subset of this instruction - if (DBT.VerifyAssertions) DBT._assert(immediateOperand == false && transferByte == false && writeBack == false && preIndex == true); - - //resolve correspoding memory address for this operation - OPT_Operand memoryAddr; - - //take the ARM pipeline into account when storing relative to the pc - if (baseRegister == 15) { - if (positiveOffset) - memoryAddr = new OPT_IntConstantOperand(pc + 8 + offset); - else - memoryAddr = new OPT_IntConstantOperand(pc + 8 - offset); - } - else { - OPT_Operand Rs = arm2ir.getRegister(baseRegister); - memoryAddr = arm2ir.getTempInt(0); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, (OPT_RegisterOperand)memoryAddr, Rs, new OPT_IntConstantOperand(offset))); - } - - //resolve dest register - OPT_RegisterOperand Rd = arm2ir.getRegister(destRegister); - - if (loadOperation) { - //load a word - ps.memory.translateLoad32(memoryAddr, Rd); - } - else { - //store a word - ps.memory.translateStore32(memoryAddr, Rd); - } - - return pc+4; - } - } - - abstract static class DataProcessingOperation_Decoder extends BasicDecoder { - - protected int Rd; - protected int Rs; - protected boolean setConditionCodes; - - protected boolean hasImmediate; - protected int immediate; - - @Override - protected final int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { - hasImmediate = getBit(instr, 25); - setConditionCodes = getBit(instr, 20); - Rd = getBits(instr, 12, 15); - Rs = getBits(instr, 16, 19); - - //we're only handling a subset of the possible instruction options - if (DBT.VerifyAssertions) DBT._assert(Rd != 15 && Rs != 15 && hasImmediate == true); - - if (hasImmediate) - immediate = getBits(instr, 0, 7) << getBits(instr, 8, 11); - - System.out.println("Decoding Data Processing Instruction with: "); - System.out.println("Rs: " + Rs); - System.out.println("Rd: " + Rd); - System.out.println("Op Code: " + getBits(instr, 21, 24)); - System.out.println("Set Condition Codes: " + setConditionCodes); - - if (hasImmediate) - System.out.println("Immediate: " + immediate); - - translateActualOpcode(arm2ir, ps, lazy, pc, instr); - - if (setConditionCodes && Rd != 15) { - throw new UnsupportedOperationException("Setting conditions codes is not yet supported"); - } - - return pc+4; - } - - protected abstract void translateActualOpcode(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr); - } - - static class ADD_Decoder extends DataProcessingOperation_Decoder { - - @Override - protected void translateActualOpcode(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { - - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, arm2ir.getRegister(Rd), arm2ir.getRegister(Rs), new OPT_IntConstantOperand(immediate))); - } - } - - static class BranchDecoder extends BasicDecoder { - - @Override - protected int translate(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc, int instr) { - boolean branchAndLink = getBit(instr, 24); - int offset = getBits(instr, 0, 23); - - if (DBT.VerifyAssertions) DBT._assert(branchAndLink == false); - - return pc + 8 + offset; - } - } - - public static int translateInstruction(ARM2IR arm2ir, ARM_ProcessSpace ps, ARM_Laziness lazy, int pc) { - int instr = ps.memory.loadInstruction32(pc); - - System.out.println("Translating Instruction:" + instr); - BasicDecoder decoder = null; - - if (BasicDecoder.getBits(instr, 26, 27) == 1) { - decoder = new LDR_STR_Decoder(); - } - - return decoder.translate(arm2ir, ps, lazy, pc, instr); - } -} Added: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-12 17:31:57 UTC (rev 30) @@ -0,0 +1,37 @@ +package org.binarytranslator.arch.arm.decoder; + +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.LongMultiply; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Multiply; +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.TransferFromStatusRegister; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.TransferToStatusRegister; + +/** 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(Multiply 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(TransferFromStatusRegister register); + void visit(TransferToStatusRegister register); + void visit(CountLeadingZeros zeros); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-13 15:01:40
|
Revision: 38 http://svn.sourceforge.net/pearcolator/?rev=38&view=rev Author: michael_baer Date: 2007-04-13 08:01:40 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Added Support for half-word and signed data transfers. Added initial version of an ARM instruction decoder. 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_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java Added: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-13 15:01:40 UTC (rev 38) @@ -0,0 +1,211 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.DBT; + +/** + * 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. + * + * @author Michael Baer + * + */ +public class ARM_InstructionDecoder { + + /** + * 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; + } + + 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) { + return factory.createUndefinedInstruction(instr); + } + + if (getBit(instr, 26)) { + //opcode: 01 + if (getBit(instr, 25) && getBit(instr, 4)) + return factory.createUndefinedInstruction(instr); + 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 (getBit(instr, 26)) { + //opcode: 11 + return decode_11x( instr, factory); + } + else { + //opcode: 10 + return decode_10x(instr, factory); + } + } + + private static <T> T decode_00x(int instr, ARM_InstructionFactory<T> factory) { + if (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)) { + //opcode: 101 + if ((instr & 0xF0000000) == 0xF0000000) + return factory.createBranchExchange(instr); + else + return factory.createBranch(instr); + } + else { + //opcode: 100 + if ((instr & 0xF0000000) == 0xF0000000) + return factory.createUndefinedInstruction(instr); + else + return factory.createBlockDataTransfer(instr); + } + } + + private static <T> T decode_000(int instr, ARM_InstructionFactory<T> factory) { + //opcode: 000 + if (getBit(instr, 24) && !getBit(instr, 23) && !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) + return factory.createDataProcessing(instr); + + return decode_multiplies_extra_load_stores(instr, factory); + } + } + + private static <T> T decode_001(int instr, ARM_InstructionFactory<T> factory) { + //opcode: 001 + if (!getBit(instr, 24) || getBit(instr, 23) || getBit(instr, 20)) { + return factory.createDataProcessing(instr); + } + + if (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 (getBit(instr, 25) == false) { + //opcode: 110 + return factory.createCoprocessorDataTransfer(instr); + } + + //opcode: 111 + if (getBit(instr, 24)) { + //opcode: 1111 + if ((instr & 0xF0000000) == 0xF0000000) + return factory.createUndefinedInstruction(instr); + else + return factory.createSoftwareInterrupt(instr); + } + else { + //opcode: 1110 + if (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 (getBit(instr, 6) || 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 (getBit(instr, 4)) { + if (getBit(instr, 22)) + return factory.createCountLeadingZeros(instr); + else + return factory.createBranchExchange(instr); + } + else { + if (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 (getBit(instr, 6)) { + //load/store signed half-word or two words + if (getBit(instr, 20)) + return factory.createSingleDataTransfer(instr); + else + return factory.createUndefinedInstruction(instr); //two words immediate offset + } + else { + if (getBit(instr, 5)) { + //load/store half-word + return factory.createSingleDataTransfer(instr); + } + else { + //Multiply, multiply long or Swap + if (getBit(instr, 24)) { + return factory.createSwap(instr); + } + else { + if (getBit(instr, 23)) + return factory.createLongMultiply(instr); + else + return factory.createIntMultiply(instr); + } + } + } + } +} Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-13 11:16:14 UTC (rev 37) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoders.java 2007-04-13 15:01:40 UTC (rev 38) @@ -2,6 +2,19 @@ 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 { /** @@ -13,7 +26,7 @@ * @return * True, if the given bit is set within the word, false otherwise. */ - public static final boolean getBit(int word, int bit) { + private static final boolean getBit(int word, int bit) { if (DBT.VerifyAssertions) DBT._assert(bit >= 0 && bit <= 31); return (word & (1 << bit)) != 0; @@ -31,7 +44,7 @@ * @return * A zero-based version of the bit sequence. */ - public static final int getBits(int word, int from, int to) { + 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; @@ -136,17 +149,17 @@ } /** Returns true, if the condition codes shall be updated by the result of this operation. */ - public boolean updateConditionCodes() { + public final boolean updateConditionCodes() { return updateConditionCodes; } /** Returns true, if this is the accumulate version of the instruction. */ - public boolean accumulate() { + public final boolean accumulate() { return accumulate; } /** Returns the register number of the Rs operand register. */ - public byte getRs() { + public final byte getRs() { return Rs; } } @@ -172,7 +185,7 @@ } /** Returns the coprocessor that shall process this instruction */ - public byte getCoprocessorNumber() { + public final byte getCoprocessorNumber() { return cpNum; } } @@ -180,6 +193,7 @@ /** 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, Register, @@ -187,6 +201,7 @@ RegisterShiftedRegister, } + /** Describes a type of shift, in case the operand is supposed to be shifted. */ public enum ShiftType { LogicalLeft, LogicalRight, @@ -236,6 +251,7 @@ } } + /** 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. */ @@ -263,8 +279,10 @@ 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) { @@ -282,8 +300,10 @@ } } + /** Represents a register operand. */ protected static class RegisterOperand extends OperandWrapper { + /** @see #getRegister() */ protected final byte register; protected RegisterOperand(byte register) { @@ -301,9 +321,13 @@ } } + /** 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) { @@ -321,11 +345,20 @@ 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) { @@ -343,11 +376,16 @@ public byte getShiftingRegister() { return shiftingRegister; } + + @Override + public ShiftType getShiftType() { + return shiftType; + } } } /** Represents a Data Processing instruction. */ - public final static class DataProcessing extends + public static class DataProcessing extends TwoRegistersTemplate { /** @see #hasSetConditionCodes() */ @@ -372,25 +410,20 @@ } /** Returns the opcode, that specifies the data processing operation, which is to be performed. */ - public byte getOpcode() { + public final byte getOpcode() { return opcode; } /** Returns true if the condition codes shall be set by this operation, false otherwise. */ - public boolean updateConditionCodes() { + public final boolean updateConditionCodes() { return updateConditionCodes; } /** Returns the 2nd operand of this data processing instruction. */ - public OperandWrapper getOperand2() { + public final OperandWrapper getOperand2() { return operand2; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 26, 27) == 0; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -398,17 +431,26 @@ } /** Represents a LDR/SDR instruction. */ - public final static class SingleDataTransfer extends + 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 #byteTransfer() */ - protected final boolean byteTransfer; + /** @see #getSize() */ + protected final TransferSize size; /** @see #writeBack() */ protected final boolean writeBack; @@ -416,58 +458,88 @@ /** @see #isLoad() */ protected final boolean isLoad; - /** @see #getOperand2() */ - protected final OperandWrapper operand2; + /** @see #getOffset() */ + protected final OperandWrapper offset; public SingleDataTransfer(int instr) { super(instr); preIndexing = getBit(instr, 24); positiveOffset = getBit(instr, 23); - byteTransfer = getBit(instr, 22); writeBack = getBit(instr, 21); isLoad = getBit(instr, 20); - if (getBit(instr, 25)) - operand2 = OperandWrapper.createImmediate(instr & 0xFF); - else - operand2 = OperandWrapper.decodeShiftedRegister(instr); + if (getBit(instr, 26)) { + //this is an unsigned byte or word transfer + signExtend = false; + + 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); + + 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 the loaded/stored value shall be signed-extended.*/ + public final boolean signExtend() { + return signExtend; + } - /** Returns true, if a single byte is to be transfered or false if an int shall be transfered. */ - public boolean isByteTransfer() { - return byteTransfer; + /** 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 boolean isLoad() { + 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 boolean positiveOffset() { + public final boolean positiveOffset() { return positiveOffset; } /** True if the base register shall be changed before the transfer, otherwise changed it after the transfer. */ - public boolean preIndexing() { + public final boolean preIndexing() { return preIndexing; } /** True if the incremented base register shall be persisted after this instruction. */ - public boolean writeBack() { + public final boolean writeBack() { return writeBack; } - /** Returns the 2nd operand of this data processing instruction. */ - public OperandWrapper getOperand2() { - return operand2; + /** Returns the offset operand for this data processing instruction. */ + public final OperandWrapper getOffset() { + return offset; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 26, 27) == 1; - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -476,17 +548,12 @@ } /** Represents a normal (not long) multiply instruction. */ - public final static class Multiply extends MultiplyTemplate { + public static class IntMultiply extends MultiplyTemplate { - protected Multiply(int instr) { + protected IntMultiply(int instr) { super(instr); } - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 22, 27) == 0 && getBits(instr, 4, 7) == 9; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -494,7 +561,7 @@ } /** Represents a long multiply instruction. */ - public final static class LongMultiply extends MultiplyTemplate { + public static class LongMultiply extends MultiplyTemplate { /** @see #isUnsigned() */ protected final boolean unsigned; @@ -506,25 +573,20 @@ } /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ - public byte getRdHigh() { + 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 byte getRdLow() { + public final byte getRdLow() { return Rn; } /** Returns true, if this is an unsigned multiplication or false if it is a signed multiplication. */ - public boolean isUnsigned() { + public final boolean isUnsigned() { return unsigned; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 23, 27) == 1 && getBits(instr, 4, 7) == 9; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -532,7 +594,7 @@ } /** Represents a SWP/SWPB instruction. */ - public final static class Swap extends ThreeRegistersTemplate { + public static class Swap extends ThreeRegistersTemplate { /** @see #swapByte() */ protected final boolean swapByte; @@ -543,16 +605,10 @@ } /** Returns true, if a byte shall be swapped or false, if an int (32 bit) shall be swapped. */ - public boolean swapByte() { + public final boolean swapByte() { return swapByte; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 23, 27) == 2 && getBits(instr, 20, 21) == 0 - && getBits(instr, 4, 11) == 9; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -560,7 +616,7 @@ } /** Represents a LDM/STM instruction. */ - public final static class BlockDataTransfer extends Basic { + public static class BlockDataTransfer extends Basic { /** @see #preIndexing() */ protected final boolean preIndexing; @@ -595,13 +651,8 @@ registerList = instr; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 25, 27) == 4; - } - /** @return True if register r should be transferred using this instruction. */ - public boolean transferRegister(int r) { + public final boolean transferRegister(int r) { if (DBT.VerifyAssertions) DBT._assert(r >= 0 && r < 16); @@ -609,32 +660,32 @@ } /** True if the base register shall be changed before each single transfer, otherwise changed it after each transfer. */ - public boolean preIndexing() { + public final boolean preIndexing() { return preIndexing; } /** True if the base register shall be incremented, false if it should be decremented. */ - public boolean incrementBase() { + public final boolean incrementBase() { return incrementBase; } /** Force user mode during this instruction? */ - public boolean forceUser() { + public final boolean forceUser() { return forceUser; } /** True if the incremented base register shall be persisted after this instruction. */ - public boolean writeBack() { + public final boolean writeBack() { return writeBack; } /** True if this is a LDM instruction, false if it is a STM instruction. */ - public boolean isLoad() { + public final boolean isLoad() { return isLoad; } /** The number of the register which will provides the base address for this LDM/STM instruction. */ - public byte getBaseRegister() { + public final byte getBaseRegister() { return baseRegister; } @@ -645,7 +696,7 @@ } /** Represents a SWI instruction*/ - public final static class SoftwareInterrupt extends Basic { + public static class SoftwareInterrupt extends Basic { /** @see #getInterruptNumber() */ protected final int interruptNumber; @@ -656,15 +707,10 @@ } /** Returns the interrupt that is being called. The value is taken from the instruction's comment field. */ - public int getInterruptNumber() { + public final int getInterruptNumber() { return interruptNumber; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 24, 27) == 15; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -672,7 +718,7 @@ } /** Represents a branch instruction. */ - public final static class Branch extends Basic { + public static class Branch extends Basic { /** @see #isBranchAndLink() */ protected final boolean link; @@ -687,20 +733,15 @@ } /** Should the current PC be put into the lr? */ - public boolean isBranchAndLink() { + public final boolean isBranchAndLink() { return link; } /** The offset of the target address to the PC */ - public int getOffset() { + public final int getOffset() { return offset; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 25, 27) == 5; - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -708,7 +749,7 @@ } /** Represents a BX instruction set */ - public final static class BranchExchange extends Basic { + public static class BranchExchange extends Basic { /** @see #getRn() */ protected final OperandWrapper target; @@ -739,16 +780,10 @@ } /** Returns, whether the return address for this jump shall be put into the lr. */ - public boolean link() { + public final boolean link() { return link; } - /** Checks if <code>instr</code> is a valid bit representation of this instruction. */ - public static boolean conforms(int instr) { - return getBits(instr, 25, 31) == 0x7D // BLX(1) - || (getBits(instr, 20, 27) == 0x12 && getBits(instr, 6, 7) == 0); //BLX(2) && BX - } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); @@ -756,7 +791,7 @@ } /** Represents a LDC/STC instruction. */ - public static final class CoprocessorDataTransfer extends CoprocessorTemplate { + public static class CoprocessorDataTransfer extends CoprocessorTemplate { /** @see #getOffset() */ protected final int offset; @@ -788,44 +823,39 @@ } /** Returns the number of the register, which contains the base address for this data transfer.*/ - public byte getBaseRegister() { + public final byte getBaseRegister() { return Rn; } /** Returns the transfer register on the coprocessor. */ - public byte getCoprocessorRegister() { + public final byte getCoprocessorRegister() { return Rd; } /** True if this is a LDC instruction, false if it is a STC instruction. */ - public boolean isLoad() { + 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 int getOffset() { + public final int getOffset() { return offset; } /** True if the changed base register shall be persisted after this instruction. */ - public boolean writeBack() { + public final boolean writeBack() { return writeBack; } /** True if the base register shall be changed before the transfer, otherwise changed it after the transfer. */ - public boolean preIndexing() { + 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 boolean largeTransfer() { + public final boolean largeTransfer() { return largeTransfer; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 25, 27) == 6; - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -834,7 +864,7 @@ } /** Represents a CDP instruction. */ - public final static class CoprocessorDataProcessing extends CoprocessorTemplate { + public static class CoprocessorDataProcessing extends CoprocessorTemplate { /** @see #getOpcode() */ protected final byte opcode; @@ -854,34 +884,29 @@ } /** Returns the destination register of this operation. This register is a coprocessor register. */ - public byte getCoprocessorRd() { + public final byte getCoprocessorRd() { return Rd; } /** Returns the first operand register of this operation. This register is a coprocessor register. */ - public byte getCoprocessorRn() { + public final byte getCoprocessorRn() { return Rn; } /** Returns the second operand register of this operation. This register is a coprocessor register. */ - public byte getCoprocessorRm() { + 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 byte getCoprocessorInfo() { + 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 byte getOpcode() { + public final byte getOpcode() { return opcode; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 24, 27) == 14 && !getBit(instr, 4); - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -890,7 +915,7 @@ } /** Represents a MRC/MCR instruction. */ - public final static class CoprocessorRegisterTransfer extends CoprocessorTemplate { + public static class CoprocessorRegisterTransfer extends CoprocessorTemplate { /** @see #getOpcode() */ protected final byte opcode; @@ -914,39 +939,34 @@ } /** Returns true if this operation is a load from a coprocessor or false if it is a store to coprocessor. */ - public boolean isLoadFromCP() { + public final boolean isLoadFromCP() { return isLoad; } /** Returns the destination register of this operation.*/ - public byte getRd() { + public final byte getRd() { return Rd; } /** Returns the first operand register of this operation. This register is a coprocessor register. */ - public byte getCoprocessorRn() { + public final byte getCoprocessorRn() { return Rn; } /** Returns the second operand register of this operation. This register is a coprocessor register. */ - public byte getCoprocessorRm() { + 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 byte getCoprocessorInfo() { + 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 byte getOpcode() { + public final byte getOpcode() { return opcode; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 24, 27) == 14 && getBit(instr, 4); - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -955,7 +975,7 @@ } /** Represents a MRS instruction. */ - public final static class TransferFromStatusRegister extends Basic { + public static class MoveFromStatusRegister extends Basic { /** @see #getRd() */ protected final byte Rd; @@ -963,7 +983,7 @@ /** @see #transferSavedPSR() */ protected final boolean transferSavedPSR; - public TransferFromStatusRegister(int instr) { + public MoveFromStatusRegister(int instr) { super(instr); Rd = (byte) getBits(instr, 12, 15); @@ -971,19 +991,14 @@ } /** Returns the number of the destination register. */ - public byte getRd() { + public final byte getRd() { return Rd; } /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ - public boolean transferSavedPSR() { + public final boolean transferSavedPSR() { return transferSavedPSR; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 23, 27) == 2 && getBits(instr, 16, 21) == 0 && (instr & 0xFFF) == 0; - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -992,7 +1007,7 @@ } /** Represents a MSR instruction. */ - public final static class TransferToStatusRegister extends Basic { + public static class MoveToStatusRegister extends Basic { /** @see #transferControlField() */ protected final boolean transferControl; @@ -1012,7 +1027,7 @@ /** @see #getSourceOperand() */ protected final OperandWrapper sourceOperand; - public TransferToStatusRegister(int instr) { + public MoveToStatusRegister(int instr) { super(instr); transferControl = getBit(instr, 16); @@ -1029,39 +1044,34 @@ } /** Identifies the PSR that is to be transferred: true for the SPSR, false for the CPSR. */ - public boolean transferSavedPSR() { + public final boolean transferSavedPSR() { return transferSavedPSR; } /** Returns true if the control field of the PSR shall be overwritten. */ - public boolean transferControlField() { + public final boolean transferControlField() { return transferControl; } /** Returns true if the extension field of the PSR shall be overwritten. */ - public boolean transferExtensionField() { + public final boolean transferExtensionField() { return transferExtension; } /** Returns true if the status field of the PSR shall be overwritten. */ - public boolean transferStatusField() { + public final boolean transferStatusField() { return transferStatus; } /** Returns true if the flag field of the PSR shall be overwritten. */ - public boolean transferFlagField() { + public final boolean transferFlagField() { return transferFlags; } /** Returns the operand, which is to be transfered into the status register. */ - public OperandWrapper getSourceOperand() { + public final OperandWrapper getSourceOperand() { return sourceOperand; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 26, 27) == 0 && getBits(instr, 23, 24) == 2 && getBits(instr, 12, 15) == 0; - } @Override public void visit(ARM_InstructionVisitor visitor) { @@ -1070,7 +1080,7 @@ } /** Represents a CLZ instruction. */ - public final static class CountLeadingZeros extends Basic { + public static class CountLeadingZeros extends Basic { /** @see #getRm() */ protected final byte Rm; @@ -1086,19 +1096,14 @@ } /** Returns the source register for this operation. */ - public byte getRm() { + public final byte getRm() { return Rm; } /** Returns the destination register for this operation. */ - public byte getRd() { + public final byte getRd() { return Rd; } - - /** Checks if <code>instr</code> is a valid bit representation of this instruction type. */ - public static boolean conforms(int instr) { - return getBits(instr, 16, 27) == 0x16F && getBits(instr, 4, 11) == 0xF1; - } @Override public void visit(ARM_InstructionVisitor visitor) { Added: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionFactory.java 2007-04-13 15:01:40 UTC (rev 38) @@ -0,0 +1,20 @@ +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); +} Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-13 11:16:14 UTC (rev 37) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-13 15:01:40 UTC (rev 38) @@ -1,27 +1,13 @@ package org.binarytranslator.arch.arm.decoder; -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.LongMultiply; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.Multiply; -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.TransferFromStatusRegister; -import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.TransferToStatusRegister; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoders.*; /** 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(Multiply multiply); + void visit(IntMultiply multiply); void visit(LongMultiply multiply); void visit(Swap swap); void visit(BlockDataTransfer transfer); @@ -31,7 +17,7 @@ void visit(CoprocessorDataTransfer transfer); void visit(CoprocessorDataProcessing processing); void visit(CoprocessorRegisterTransfer transfer); - void visit(TransferFromStatusRegister register); - void visit(TransferToStatusRegister register); + void visit(MoveFromStatusRegister register); + void visit(MoveToStatusRegister register); void visit(CountLeadingZeros zeros); } 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 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-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-23 21:57:27
|
Revision: 88 http://svn.sourceforge.net/pearcolator/?rev=88&view=rev Author: michael_baer Date: 2007-04-23 14:57:27 -0700 (Mon, 23 Apr 2007) Log Message: ----------- Fixed a bug with flag handling after subtractions on ARM Modified Paths: -------------- 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_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-23 17:10:21 UTC (rev 87) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-23 21:57:27 UTC (rev 88) @@ -540,14 +540,21 @@ preIndexing = Utils.getBit(instr, 24); positiveOffset = Utils.getBit(instr, 23); - writeBack = Utils.getBit(instr, 21); isLoad = Utils.getBit(instr, 20); if (Utils.getBit(instr, 26)) { //this is an unsigned byte or word transfer signExtend = false; - forceUserMode = !preIndexing && writeBack; + //if post-indexing implies writeBack, so set the writeback flag when postindexing is used + if (!preIndexing) { + writeBack = true; + forceUserMode = Utils.getBit(instr, 21); + } + else { + writeBack = Utils.getBit(instr, 21); + forceUserMode = false; + } if (Utils.getBit(instr, 22)) size = TransferSize.Byte; @@ -567,6 +574,7 @@ size = TransferSize.Byte; signExtend = Utils.getBit(instr, 6); + writeBack = Utils.getBit(instr, 21); forceUserMode = false; if (Utils.getBit(instr, 22)) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-23 17:10:21 UTC (rev 87) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-23 21:57:27 UTC (rev 88) @@ -340,7 +340,23 @@ } } } + + /** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/ + protected final void setFlagsForSub(int lhs, int rhs) { + if (updateConditionCodes) { + if (Rd != 15) { + int result = lhs - rhs; + boolean carry = !(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; @@ -380,7 +396,7 @@ } /** Add. <code>Rd = op1 + op2 </code>.*/ - private class DataProcessing_Add extends DataProcessing { + private final class DataProcessing_Add extends DataProcessing { public DataProcessing_Add(int instr) { super(instr); @@ -397,127 +413,125 @@ } /** Subtract. <code>Rd = op1 - op2 </code>.*/ - private final class DataProcessing_Sub extends DataProcessing_Add { + private final class DataProcessing_Sub extends DataProcessing { public DataProcessing_Sub(int instr) { super(instr); } + + @Override + public void execute() { + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); + int result = operand1 - operand2; - @Override - protected int resolveOperand2() { - return -super.resolveOperand2(); + regs.set(Rd, result); + setFlagsForSub(operand1, operand2); } } - /** Reverse subtract. <code>Rd = - op1 + op2</code>.*/ - private final class DataProcessing_Rsb extends DataProcessing_Add { + /** Reverse subtract. <code>Rd = op2 - op1</code>.*/ + private final class DataProcessing_Rsb extends DataProcessing { protected DataProcessing_Rsb(int instr) { super(instr); } @Override - protected int resolveOperand1() { - return -super.resolveOperand1(); + public void execute() { + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); + int result = operand2 - operand1; + + regs.set(Rd, result); + setFlagsForSub(operand2, operand1); } } /** 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 { + * not cause an overflow). Then, the normal add-routine is being invoked. */ + private final class DataProcessing_Adc extends DataProcessing { - /** 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) { super(instr); } @Override - protected final int resolveOperand1() { - return cachedOperand1; - } - - @Override - 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; + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); if (regs.isCarrySet()) { - if (cachedOperand1 != Integer.MAX_VALUE) { - cachedOperand1++; - } else if (cachedOperand2 != Integer.MAX_VALUE) { - cachedOperand2++; + if (operand1 != Integer.MAX_VALUE) { + operand1++; + } else if (operand2 != Integer.MAX_VALUE) { + operand2++; } else { - regs.setFlags(cachedOperand1 > 0, cachedOperand1 != 0, true, true); + regs.setFlags(operand1 > 0, operand1 != 0, true, true); return; } } - super.execute(); + int result = operand1 + operand2; + + regs.set(Rd, result); + setFlagsForAdd(operand1, operand2); } } /** Subtract with carry. <code>Rd = op1 - op2 + CARRY</code>.*/ - private class DataProcessing_Sbc extends DataProcessing_Adc { + private class DataProcessing_Sbc extends DataProcessing { protected DataProcessing_Sbc(int instr) { super(instr); } + + public void execute() { + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); - @Override - protected boolean negateOperand2() { - return true; + if (!regs.isCarrySet()) { + if (operand1 != Integer.MIN_VALUE) { + operand1--; + } else if (operand2 != Integer.MIN_VALUE) { + operand2--; + } else { + //TODO: Remove this exception, when the correct behavior has been verified. + throw new RuntimeException("I'm interested in finding a case where this occurs, so this exception is sooner or later going to 'notify' me.."); + //regs.setFlags(operand1 > 0, operand1 != 0, true, true); + //return; + } + } + + int result = operand1 - operand2; + + regs.set(Rd, result); + setFlagsForSub(operand1, operand2); } } /** Reserve subtract with carry. <code>Rd = -op1 + op2 + CARRY</code>.*/ - private class DataProcessing_Rsc extends DataProcessing_Adc { + private final class DataProcessing_Rsc extends DataProcessing_Sbc { protected DataProcessing_Rsc(int instr) { super(instr); } - + @Override - protected boolean negateOperand1() { - return true; + protected int resolveOperand1() { + return super.resolveOperand2(); } + + @Override + protected int resolveOperand2() { + return super.resolveOperand1(); + } } /** Set the flags according to the logical-and of two values. * <code>Flags = op1 & op2</code>*/ - private class DataProcessing_Tst extends DataProcessing { + private final class DataProcessing_Tst extends DataProcessing { protected DataProcessing_Tst(int instr) { super(instr); @@ -531,7 +545,7 @@ /** Sets the flags according to the exclusive-or of two values. * <code>Flags = op1 ^ op2</code> */ - private class DataProcessing_Teq extends DataProcessing { + private final class DataProcessing_Teq extends DataProcessing { protected DataProcessing_Teq(int instr) { super(instr); @@ -545,7 +559,7 @@ /** Set the flags according to the comparison of two values. * <code>Flags = op1 - op2</code> */ - private class DataProcessing_Cmp extends DataProcessing { + private final class DataProcessing_Cmp extends DataProcessing { protected DataProcessing_Cmp(int instr) { super(instr); @@ -553,13 +567,13 @@ @Override public void execute() { - setFlagsForAdd(resolveOperand1(), -resolveOperand2()); + setFlagsForSub(resolveOperand1(), resolveOperand2()); } } /** 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 { + private final class DataProcessing_Cmn extends DataProcessing { protected DataProcessing_Cmn(int instr) { super(instr); @@ -572,7 +586,7 @@ } /** Binary or. <code>Rd = op1 | op2</code>. */ - private class DataProcessing_Orr extends DataProcessing { + private final class DataProcessing_Orr extends DataProcessing { protected DataProcessing_Orr(int instr) { super(instr); @@ -586,7 +600,7 @@ } } - private class DataProcessing_Mov extends DataProcessing { + private final class DataProcessing_Mov extends DataProcessing { protected DataProcessing_Mov(int instr) { super(instr); @@ -603,7 +617,7 @@ /** 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 { + private final class DataProcessing_Bic extends DataProcessing { protected DataProcessing_Bic(int instr) { super(instr); @@ -620,7 +634,7 @@ /** Move and negate. Moves an integer between two registers, negating it on the way. * <code>Rd = -op2</code>.*/ - private class DataProcessing_Mvn extends DataProcessing { + private final class DataProcessing_Mvn extends DataProcessing { protected DataProcessing_Mvn(int instr) { super(instr); @@ -636,7 +650,7 @@ /** Count the number of leading zeros in an integer. * <code>Rd = Number_Of_Leading_Zeroes(op2) </code> */ - private class DataProcessing_Clz extends DataProcessing { + private final class DataProcessing_Clz extends DataProcessing { protected DataProcessing_Clz(int instr) { super(instr); @@ -652,7 +666,7 @@ /** 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 + private final class Swap extends ARM_Instructions.Swap implements ARM_Instruction { public Swap(int instr) { @@ -677,7 +691,7 @@ } /** Transfer multiple registers at once between the register bank and the memory. */ - private class BlockDataTransfer extends ARM_Instructions.MultipleDataTransfer + private final class BlockDataTransfer extends ARM_Instructions.MultipleDataTransfer implements ARM_Instruction { /** the lowest address that we're reading a register from / writing a register to */ @@ -799,7 +813,7 @@ } /** Branch to another instruction address. */ - private class Branch extends ARM_Instructions.Branch implements + private final class Branch extends ARM_Instructions.Branch implements ARM_Instruction { public Branch(int instr) { @@ -821,7 +835,7 @@ } /** Branch to another instruction address and switch between ARM32 and Thumb code on the way.*/ - private class BranchExchange extends ARM_Instructions.BranchExchange + private final class BranchExchange extends ARM_Instructions.BranchExchange implements ARM_Instruction { public BranchExchange(int instr) { @@ -876,7 +890,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 + private final class IntMultiply extends ARM_Instructions.IntMultiply implements ARM_Instruction { protected IntMultiply(int instr) { @@ -923,7 +937,7 @@ } /** Move the value of the program status register into a register. */ - private class MoveFromStatusRegister extends + private final class MoveFromStatusRegister extends ARM_Instructions.MoveFromStatusRegister implements ARM_Instruction { @@ -949,7 +963,7 @@ } /** Invoke a software interrupt. */ - private class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt + private final class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt implements ARM_Instruction { public SoftwareInterrupt(int instr) { @@ -968,27 +982,16 @@ /** 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 + private final class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer implements ARM_Instruction { public SingleDataTransfer(int instr) { super(instr); } - - /** Resolves the address of the memory slot, that is involved in the transfer. */ - 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; - + + /** Resolves the offset, which is (when post-indexing is not used) to be added to the + * base address to create the final address. */ + private int resolveOffset() { int addrOffset; switch (offset.getType()) { @@ -1005,7 +1008,7 @@ case ImmediateShiftedRegister: addrOffset = regs.get(offset.getRegister()); - + if (offset.getRegister() == 15) addrOffset += 8; @@ -1047,11 +1050,28 @@ } if (positiveOffset) - return base + addrOffset; + return addrOffset; else - return base - addrOffset; + return -1 * addrOffset; } + /** Resolves the address of the memory slot, that is involved in the transfer. */ + 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; + + return base + resolveOffset(); + } + public void execute() { //should we simulate a user-mode memory access? if (forceUserMode) { @@ -1114,15 +1134,15 @@ } } - //should the memory address, which we accessed, be written back into a register? This is used for continuos - //memory accesses + //should the memory address, which we accessed, be written back into a register? + //This is used for continuous memory accesses if (writeBack) { - if (preIndexing) + if (preIndexing) { regs.set(Rn, address); + } else { - //TODO: calculate the post-indexed address - //and set it to Rn - throw new RuntimeException("Not yet implemented."); + //add the offset to the base address and write the result back into Rn + regs.set(Rn, address + resolveOffset()); } } } @@ -1138,7 +1158,7 @@ /** Represents an undefined instruction, will throw a runtime error when this instruction * is executed. */ - private class UndefinedInstruction implements ARM_Instruction { + private final class UndefinedInstruction implements ARM_Instruction { private final int instruction; @@ -1159,7 +1179,7 @@ } } - private class DebugNopInstruction implements ARM_Instruction { + private final class DebugNopInstruction implements ARM_Instruction { public Condition getCondition() { return Condition.AL; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-19 17:34:24
|
Revision: 137 http://svn.sourceforge.net/pearcolator/?rev=137&view=rev Author: michael_baer Date: 2007-06-19 10:34:26 -0700 (Tue, 19 Jun 2007) Log Message: ----------- First translator that runs libc "Hello World" from Thumb code. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-19 17:33:45 UTC (rev 136) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-19 17:34:26 UTC (rev 137) @@ -489,32 +489,18 @@ T createDataProcessing(short instr); - T createSwap(short instr); - T createSingleDataTransfer(short instr); T createBlockDataTransfer(short instr); T createIntMultiply(short instr); - - T createLongMultiply(short instr); - + T createSoftwareInterrupt(short instr); T createBranch(short instr); T createBranchExchange(short instr); - T createCoprocessorDataTransfer(short instr); - - T createCoprocessorDataProcessing(short instr); - - T createCoprocessorRegisterTransfer(short instr); - - T createMoveFromStatusRegister(short instr); - - T createMoveToStatusRegister(short instr); - T createUndefinedInstruction(short instr); } @@ -597,34 +583,10 @@ return new BranchExchange(instr); } - public Instruction createCoprocessorDataProcessing(short instr) { - throw new RuntimeException("Thumb does not support coprocessor instructions."); - } - - public Instruction createCoprocessorDataTransfer(short instr) { - throw new RuntimeException("Thumb does not support coprocessor instructions."); - } - - public Instruction createCoprocessorRegisterTransfer(short instr) { - throw new RuntimeException("Thumb does not support coprocessor instructions."); - } - public Instruction createDataProcessing(short instr) { return new DataProcessing(instr); } - public Instruction createLongMultiply(short instr) { - throw new RuntimeException("Thumb does not support long multiplications."); - } - - public Instruction createMoveFromStatusRegister(short instr) { - throw new RuntimeException("Thumb does not support status register transfers."); - } - - public Instruction createMoveToStatusRegister(short instr) { - throw new RuntimeException("Thumb does not support status register transfers."); - } - public Instruction createSingleDataTransfer(short instr) { return new SingleDataTransfer(instr); } @@ -633,10 +595,6 @@ return new SoftwareInterrupt(instr); } - public Instruction createSwap(short instr) { - throw new RuntimeException("Thumb does not support SWAP instructions."); - } - public Instruction createUndefinedInstruction(short instr) { return new UndefinedInstruction(instr); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-19 17:33:45 UTC (rev 136) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-19 17:34:26 UTC (rev 137) @@ -1157,7 +1157,7 @@ //if we're supposed to link, then write the previous address into the link register if (i.link) { - regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + (regs.getThumbMode() ? 2 : 4)); + regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + i.size()); } if (regs.getThumbMode()) @@ -1194,9 +1194,6 @@ } public void execute() { - //remember the previous address - - //are we supposed to jump to thumb (thumb=true) or ARM32 (thumb=false)? boolean thumb; @@ -1212,7 +1209,7 @@ else previousAddress = regs.get(i.target.getRegister()); - targetAddress = previousAddress + i.target.getOffset(); + targetAddress = (previousAddress + i.target.getOffset()) | 1; thumb = true; break; @@ -1825,18 +1822,6 @@ return new BranchExchange(new ARM_Instructions.BranchExchange(instr)); } - public ARM_Instruction createCoprocessorDataProcessing(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - - public ARM_Instruction createCoprocessorDataTransfer(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - - public ARM_Instruction createCoprocessorRegisterTransfer(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - public ARM_Instruction createDataProcessing(short instr) { ARM_Instructions.DataProcessing i = new ARM_Instructions.DataProcessing(instr); @@ -1881,18 +1866,6 @@ } } - public ARM_Instruction createLongMultiply(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - - public ARM_Instruction createMoveFromStatusRegister(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - - public ARM_Instruction createMoveToStatusRegister(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - public ARM_Instruction createSingleDataTransfer(short instr) { return new SingleDataTransfer(new ARM_Instructions.SingleDataTransfer(instr)); } @@ -1901,10 +1874,6 @@ return new SoftwareInterrupt(new ARM_Instructions.SoftwareInterrupt(instr)); } - public ARM_Instruction createSwap(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - public ARM_Instruction createUndefinedInstruction(short instr) { return new UndefinedInstruction(instr); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-19 17:33:45 UTC (rev 136) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-19 17:34:26 UTC (rev 137) @@ -231,8 +231,9 @@ value = new OPT_IntConstantOperand(translator.readPC() + operand.getOffset()); } else { - value = translator.arm2ir.getTempInt(9); - translator.arm2ir.appendInstruction(Binary.create(INT_ADD, (OPT_RegisterOperand)value, translator.arm2ir.getRegister(operand.getRegister()), new OPT_IntConstantOperand(operand.getOffset()))); + OPT_RegisterOperand tmp = translator.arm2ir.getTempInt(9); + translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, translator.arm2ir.getRegister(operand.getRegister()), new OPT_IntConstantOperand(operand.getOffset()))); + value = tmp.copy(); } return; @@ -737,7 +738,9 @@ } public int getSuccessor(int pc) { - return pc + 4; + + boolean thumbMode = (pc & 0x1) == 1; + return pc + (thumbMode ? 2 : 4); } public Condition getCondition() { @@ -928,7 +931,12 @@ protected OPT_Operand resolveOperand1() { if (i.Rn == ARM_Registers.PC) { - return new OPT_IntConstantOperand( readPC() ); + int value = readPC(); + + if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD) + value = value & 0xFFFFFFFC; + + return new OPT_IntConstantOperand( value ); } return arm2ir.getRegister(i.Rn); @@ -1057,7 +1065,7 @@ public int getSuccessor(int pc) { if (i.Rd != ARM_Registers.PC) - return pc + 4; + return pc + i.size(); else return -1; } @@ -1532,7 +1540,7 @@ public int getSuccessor(int pc) { //according to the ARM Architecture reference, using the pc as Rd yields an undefined //result. Therefore, we can safely assume that this instruction never equals a branch - return pc + 4; + return pc + i.size(); } } @@ -1722,7 +1730,7 @@ if (i.isLoad && transferPC) return -1; else - return pc + 4; + return pc + i.size(); } } @@ -1737,37 +1745,46 @@ } public void translate() { - - - //if we're supposed to link, then write the previous address into the link register - if (i.link) { - arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); - } - else { - //we should never be returning from the goto - arm2ir.getCurrentBlock().deleteNormalOut(); - } - + //can we pre-calculate to where we're branching? if (i.offset.getType() == OperandWrapper.Type.Immediate) { + + int destination = readPC() + i.offset.getImmediate(); + + if (inThumb()) + destination |= 1; + //we can directly resolve this branch to a fixed address - if (i.link) - arm2ir.appendCall(readPC() + i.getOffset().getImmediate(), lazy, pc + i.size()); - else - arm2ir.appendBranch(readPC() + i.getOffset().getImmediate(), lazy, BranchType.DIRECT_BRANCH); + if (i.link) { + //put the return address into the link register, then branch + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + i.size()))); + arm2ir.appendCall(destination, lazy, pc + i.size()); + } + else { + //just branch and never return from it + arm2ir.appendBranch(destination, lazy, BranchType.DIRECT_BRANCH); + arm2ir.getCurrentBlock().deleteNormalOut(); + } } else { //the branch target is not known at compile time OPT_Operand offset = ResolvedOperand.resolve(ARM_Translator.this, i.offset); - OPT_RegisterOperand dest = arm2ir.getTempInt(0); + OPT_RegisterOperand dest = arm2ir.getTempInt(0); + + if (inThumb()) + arm2ir.appendInstruction(Binary.create(INT_ADD, dest, offset, new OPT_IntConstantOperand(readPC() | 1))); + else + arm2ir.appendInstruction(Binary.create(INT_ADD, dest, offset, new OPT_IntConstantOperand(readPC()))); - arm2ir.appendInstruction(Binary.create(INT_ADD, dest, offset, new OPT_IntConstantOperand(readPC()))); - if (i.link) { + //put the return address into the link register, then branch + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + i.size()))); arm2ir.appendCall(dest, lazy, pc + i.size()); } else { + //just branch and never return from it arm2ir.appendBranch(dest, lazy, BranchType.INDIRECT_BRANCH); + arm2ir.getCurrentBlock().deleteNormalOut(); } } @@ -1817,17 +1834,18 @@ } //Call regs.setThumbMode(true) to enable thumb execution - enableThumb = new OPT_IntConstantOperand(inThumb() ? 0 : 1); + enableThumb = new OPT_IntConstantOperand(1); break; case Register: + if (i.target.getRegister() == ARM_Registers.PC) + targetAddress = new OPT_IntConstantOperand(readPC()); + else + targetAddress = arm2ir.getRegister(i.target.getRegister()); + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); - arm2ir.appendInstruction(Binary.create(INT_AND, tmp, arm2ir.getRegister(i.target.getRegister()), new OPT_IntConstantOperand(0xFFFFFFFE) )); - targetAddress = tmp; - - OPT_RegisterOperand tmp2 = arm2ir.getTempInt(1); - arm2ir.appendInstruction(Binary.create(INT_AND, tmp2, arm2ir.getRegister(i.target.getRegister()), new OPT_IntConstantOperand(0x1) )); - enableThumb = tmp2; + arm2ir.appendInstruction(Binary.create(INT_AND, tmp, arm2ir.getRegister(i.target.getRegister()), new OPT_IntConstantOperand(0x1) )); + enableThumb = tmp; break; default: @@ -1837,7 +1855,7 @@ //write the next address into the link register, if requested so. if (i.link) { - arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(previousAddress - (inThumb() ? 2 : 4)))); + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(previousAddress - i.size()))); } //set the correct processor mode (thumb or not) @@ -1900,7 +1918,7 @@ } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -1966,7 +1984,7 @@ } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -2006,7 +2024,7 @@ public int getSuccessor(int pc) { //Rd should never be the PC, so we can safely predict the next instruction - return pc + 4; + return pc + i.size(); } } @@ -2028,7 +2046,7 @@ } public int getSuccessor(int pc) { - return pc+4; + return pc + i.size(); } } @@ -2061,7 +2079,7 @@ } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -2247,7 +2265,7 @@ if (i.Rd == ARM_Registers.PC && i.isLoad) return -1; - return pc + 4; + return pc + i.size(); } } @@ -2272,6 +2290,12 @@ } private final class DebugNopInstruction implements ARM_Instruction { + + private final boolean thumb; + + public DebugNopInstruction(boolean thumb) { + this.thumb = thumb; + } public Condition getCondition() { return Condition.AL; @@ -2281,7 +2305,7 @@ } public int getSuccessor(int pc) { - return pc+4; + return pc + (thumb ? 2 : 4); } } @@ -2352,21 +2376,21 @@ //TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createCoprocessorDataTransfer(int instr) { // TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createCoprocessorRegisterTransfer(int instr) { // TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createIntMultiply(int instr) { @@ -2402,78 +2426,76 @@ } public ARM_Instruction createBlockDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr)); } public ARM_Instruction createBranch(short instr) { - // TODO Auto-generated method stub - return null; + return new Branch(new ARM_Instructions.Branch(instr)); } public ARM_Instruction createBranchExchange(short instr) { - // TODO Auto-generated method stub - return null; + return new BranchExchange(new ARM_Instructions.BranchExchange(instr)); } - public ARM_Instruction createCoprocessorDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; - } - - public ARM_Instruction createCoprocessorDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; - } - - public ARM_Instruction createCoprocessorRegisterTransfer(short instr) { - // TODO Auto-generated method stub - return null; - } - public ARM_Instruction createDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; - } + ARM_Instructions.DataProcessing i = new ARM_Instructions.DataProcessing(instr); - public ARM_Instruction createLongMultiply(short instr) { - // TODO Auto-generated method stub - return null; - } + switch (i.opcode) { + case ADC: + return new DataProcessing_Adc(i); + case ADD: + return new DataProcessing_Add(i); + case AND: + return new DataProcessing_And(i); + case BIC: + return new DataProcessing_Bic(i); + case CMN: + return new DataProcessing_Cmn(i); + case CMP: + return new DataProcessing_Cmp(i); + case EOR: + return new DataProcessing_Eor(i); + case MOV: + return new DataProcessing_Mov(i); + case MVN: + return new DataProcessing_Mvn(i); + case ORR: + return new DataProcessing_Orr(i); + case RSB: + return new DataProcessing_Rsb(i); + case RSC: + return new DataProcessing_Rsc(i); + case SBC: + return new DataProcessing_Sbc(i); + case SUB: + return new DataProcessing_Sub(i); + case TEQ: + return new DataProcessing_Teq(i); + case TST: + return new DataProcessing_Tst(i); + case CLZ: + return new DataProcessing_Clz(i); - public ARM_Instruction createMoveFromStatusRegister(short instr) { - // TODO Auto-generated method stub - return null; + default: + throw new RuntimeException("Unexpected Data Procesing opcode: " + + i.opcode); + } } - public ARM_Instruction createMoveToStatusRegister(short instr) { - // TODO Auto-generated method stub - return null; - } - public ARM_Instruction createSingleDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new SingleDataTransfer(new ARM_Instructions.SingleDataTransfer(instr)); } public ARM_Instruction createSoftwareInterrupt(short instr) { - // TODO Auto-generated method stub - return null; + return new SoftwareInterrupt(new ARM_Instructions.SoftwareInterrupt(instr)); } - public ARM_Instruction createSwap(short instr) { - // TODO Auto-generated method stub - return null; - } - public ARM_Instruction createUndefinedInstruction(short instr) { - // TODO Auto-generated method stub - return null; + return new UndefinedInstruction(instr); } public ARM_Instruction createIntMultiply(short instr) { - // TODO Auto-generated method stub - return null; + return new IntMultiply(new ARM_Instructions.IntMultiply(instr)); } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-02 18:24:32
|
Revision: 102 http://svn.sourceforge.net/pearcolator/?rev=102&view=rev Author: michael_baer Date: 2007-05-02 11:24:31 -0700 (Wed, 02 May 2007) Log Message: ----------- - intermediate commit, still no working translator Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-02 18:23:53 UTC (rev 101) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-02 18:24:31 UTC (rev 102) @@ -5,6 +5,8 @@ import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; import org.binarytranslator.generic.decoder.DecoderUtils; import org.binarytranslator.generic.decoder.Laziness; import org.jikesrvm.classloader.VM_Atom; @@ -47,8 +49,8 @@ static { psTref = VM_TypeReference.findOrCreate(ARM_ProcessSpace.class); - - registersFref = VM_MemberReference + + registersFref = VM_FieldReference .findOrCreate( psTref, VM_Atom.findOrCreateAsciiAtom("registers"), @@ -82,10 +84,52 @@ protected Laziness createInitialLaziness() { return new ARM_Laziness(); } + + private VM_TypeReference OperatingMode_TypeRef = null; + + /** + * Returns a register operand for values of type <code>OperatingMode</code>. + * @return + */ + public OPT_RegisterOperand getTempOperatingMode() { + if (OperatingMode_TypeRef == null) { + OperatingMode_TypeRef = VM_TypeReference.findOrCreate(ARM_Registers.OperatingMode.class); + } + + return gc.temps.makeTemp(OperatingMode_TypeRef); + } + + /** + * Returns an register operand that is equivalent to the given operating mode. + */ + public OPT_RegisterOperand getTempOperatingMode(OperatingMode mode) { + //We are going to insert a GETFIELD, which will grab the appropriate OperatingMode static instance from + //the OperatingMode class. + OPT_RegisterOperand result = getTempOperatingMode(); + + //the type reference should have been initialized by the previous call to getTempOperatingMode. + //For the sake of defensive programming, we are doing it again here... + if (OperatingMode_TypeRef == null) { + OperatingMode_TypeRef = VM_TypeReference.findOrCreate(ARM_Registers.OperatingMode.class); + } - @Override - protected void fillAllRegisters() { + //grab the field reference to the corresponding field + VM_FieldReference requestedMode_FieldReference = VM_FieldReference.findOrCreate(OperatingMode_TypeRef, VM_Atom.findOrCreateAsciiAtom(mode.name()), VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/arm/os/process/ARM_Registers/OperatingMode;")).asFieldReference(); + //Finally, use a getfield to grab the (static) member field + appendInstructionToCurrentBlock(GetField.create(GETFIELD, result, + null, new OPT_AddressConstantOperand(requestedMode_FieldReference + .peekResolvedField().getOffset()), new OPT_LocationOperand( + requestedMode_FieldReference), new OPT_TrueGuardOperand())); + + return result; + } + + /** + * Returns a RegisterOperand that contains a reference to the currently used ARM_Registers instance. + * Use this reference when calling functions on ARM_Registers. + */ + public OPT_RegisterOperand getArmRegistersReference() { OPT_RegisterOperand ps_registersOp; if (ps_registers != null) { @@ -99,7 +143,33 @@ else { ps_registersOp = new OPT_RegisterOperand(ps_registers, registersTref); } + + return ps_registersOp; + } + + /** + * Writes all current flag values back to their respective registers + */ + public void spillAllFlags(Laziness lazyState) { + + //first resolve the current lazy state (i.e. calculate the values of registers that are not yet resolved) + resolveLaziness(lazyState); + + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + + public void fillAllFlags() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + @Override + protected void fillAllRegisters() { + + //get an operand that contains a reference to the current ps.registers field. + OPT_RegisterOperand ps_registersOp = getArmRegistersReference(); + // Get the array of general purpose registers OPT_RegisterOperand ps_registers_regsOp; if (ps_registers_regs == null) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-02 18:23:53 UTC (rev 101) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-02 18:24:31 UTC (rev 102) @@ -35,15 +35,41 @@ this.ps = ps; this.arm2ir = arm2ir; } + + private OPT_Instruction createCallToRegisters(String methodName, String signature, int numParameters) { + VM_TypeReference RegistersType = VM_TypeReference + .findOrCreate(ARM_Registers.class); + VM_MethodReference methodRef = VM_MemberReference + .findOrCreate(RegistersType, + VM_Atom.findOrCreateAsciiAtom(methodName), + VM_Atom.findOrCreateAsciiAtom(signature)).asMethodReference(); + + VM_Method method = methodRef.resolve(); + + OPT_Instruction call = Call.create(CALL, null, null, null, null, numParameters + 1); + OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(methodRef, method); + + OPT_RegisterOperand thisOperand = arm2ir.getArmRegistersReference(); + + Call.setParam(call, 0, thisOperand); + Call.setGuard(call, new OPT_TrueGuardOperand()); + Call.setMethod(call, methOp); + Call.setAddress(call, new OPT_AddressConstantOperand(method + .getOffset())); + + return call; + } + + private abstract static class ResolvedOperand { protected OPT_Operand value; protected ARM_Translator translator; - public static ResolvedOperand resolveWithShifterCarryOut( + public static ResolvedOperand resolveAndStoreShifterCarryOutToCarry( ARM_Translator translator, OperandWrapper operand) { throw new RuntimeException("Not yet implemented"); } @@ -59,8 +85,6 @@ return value; } - public abstract OPT_Operand getShifterCarryOut(); - protected OPT_RegisterOperand getTempInt() { return translator.arm2ir.getTempInt(0); } @@ -79,11 +103,6 @@ _resolve(operand); } - public OPT_Operand getShifterCarryOut() { - throw new RuntimeException( - "This class does not provide a shifter carry out value."); - } - private void _resolve(OperandWrapper operand) { switch (operand.getType()) { @@ -159,8 +178,9 @@ switch (operand.getShiftType()) { case ASR: /* - * if (shiftAmout >= 32) { value = shiftedOperand >> 31; else value = - * shiftedOperand >> shiftAmount; + * if (shiftAmout >= 32) { value = shiftedOperand >> 31; shiftedOperand >> 1; } + * else + * value = shiftedOperand >> shiftAmount; */ ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); elseBlock = translator.arm2ir.createBlockAfterCurrent(); @@ -172,16 +192,20 @@ OPT_BranchProfileOperand.unlikely())); currentBlock.insertOut(ifBlock); + //shift translator.arm2ir.setCurrentBlock(ifBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_SHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(31))); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, + new OPT_IntConstantOperand(1))); translator.arm2ir.setCurrentBlock(elseBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_SHR, resultRegister, shiftedOperand, shiftAmount)); - return resultRegister; + break; case LSL: /* @@ -206,7 +230,7 @@ translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_SHL, resultRegister, shiftedOperand, shiftAmount)); - return resultRegister; + break; case LSR: @@ -232,7 +256,7 @@ translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_USHR, resultRegister, shiftedOperand, shiftAmount)); - return resultRegister; + break; case ROR: /* @@ -244,35 +268,293 @@ case RRE: /* * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; - * else return resultRegister >> 1; + * else return resultRegister >>> 1; */ - // resultRegister = resultRegister >> 1 + // resultRegister = resultRegister >>> 1 translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + //conditionally, set resultRegister = resultRegister | 0x80000000; ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); ifBlock.insertOut(nextBlock); translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), translator.arm2ir.getCarryFlag(), + new OPT_IntConstantOperand(1), OPT_ConditionOperand + .EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); + + break; + + default: + throw new RuntimeException("Unexpected shift type: " + + operand.getShiftType()); + } + + translator.arm2ir.setCurrentBlock(nextBlock); + return resultRegister; + } + } + + + + + + + private static class ResolvedOperand_WithShifterCarryOut extends + ResolvedOperand { + + private ResolvedOperand_WithShifterCarryOut(ARM_Translator translator, + OperandWrapper operand) { + this.translator = translator; + _resolve(operand); + } + private void _resolve(OperandWrapper operand) { + + switch (operand.getType()) { + case Immediate: + value = new OPT_IntConstantOperand(operand.getImmediate()); + + if (operand.getShiftAmount() != 0) { + OPT_RegisterOperand carryFlag = translator.arm2ir.getCarryFlag(); + OPT_Operand shifterCarryOut = new OPT_IntConstantOperand(((operand.getImmediate() & 0x80000000) != 0) ? 1 : 0); + + //otherwise there is no shifter carry out + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, carryFlag, shifterCarryOut)); + } + return; + + case Register: + //in this case, there is no special shifter carry out (i.e. it equals the carry flag). + int reg = operand.getRegister(); + + if (reg == 15) { + // mind the ARM pc offset + value = new OPT_IntConstantOperand(translator.pc + 8); + return; + } + + value = translator.arm2ir.getRegister(reg); + return; + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + value = resolveShift(operand); + return; + + case PcRelative: + throw new RuntimeException("This operand type does not produce a shifter carry out."); + + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand.getType()); + } + } + + /** + * Translates a bit test, where bit <code>shifterResultBit</code> is tested within <code>value</code> and the result + * is put into the carry flag If <code>shifterResultBit</code> is less than 0, the carry is not changed. + * + */ + private void translateShifterCarryOut(OPT_Operand value, OPT_Operand shifterResultBit) { + + OPT_RegisterOperand carryFlag = translator.arm2ir.getCarryFlag(); + + + OPT_RegisterOperand tmp = getTempInt(); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, + tmp, shifterResultBit, new OPT_IntConstantOperand(1))); + translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, carryFlag, value, tmp.copyRO(), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand())); + } + + /** + * 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 OPT_Operand resolveShift(OperandWrapper operand) { + if (DBT.VerifyAssertions) + DBT + ._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister + || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); + + // consider the "usual" ARM program counter offset + OPT_Operand shiftedOperand; + if (operand.getRegister() == 15) + shiftedOperand = new OPT_IntConstantOperand(translator.pc + 8); + else + shiftedOperand = translator.arm2ir.getRegister(operand.getRegister()); + + OPT_Operand shiftAmount; + + if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) { + // the amount of shift is a constant + shiftAmount = new OPT_IntConstantOperand(operand.getShiftAmount()); + } else { + // the amount of shifting is determined by a register + shiftAmount = translator.arm2ir.getRegister(operand + .getShiftingRegister()); + } + + OPT_BasicBlock currentBlock = translator.arm2ir.getCurrentBlock(); + OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); + + OPT_BasicBlock ifBlock; + OPT_BasicBlock elseBlock; + + OPT_RegisterOperand resultRegister = getTempInt(); + + switch (operand.getShiftType()) { + case ASR: + /* + * if (shiftAmout >= 32) { value = shiftedOperand >> 31; shiftedOperand >> 1; } + * else + * value = shiftedOperand >> shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + ifBlock.insertOut(nextBlock); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( INT_IFCMP, getTempValidation(), shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + new OPT_BranchProfileOperand())); + currentBlock.insertOut(ifBlock); + + //shift twice to simulate arithmetic shift-right by 32 + //circumvents java doing (shiftAmount MOD 32). + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, + new OPT_IntConstantOperand(31))); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, + new OPT_IntConstantOperand(1))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, shiftAmount)); + translateShifterCarryOut(resultRegister, shiftAmount); + + break; + + case LSL: + /* + * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand << + * shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); currentBlock.insertOut(ifBlock); translator.arm2ir.setCurrentBlock(ifBlock); translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + + break; + + case LSR: + + /* + * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand >>> + * shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + + break; + + case ROR: + /* + * return Integer.rotateRight(value, shiftAmount); + */ + translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, + shiftAmount); + return resultRegister; + + case RRE: + /* + * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; + * else return resultRegister >>> 1; + */ + + // resultRegister = resultRegister >>> 1 + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), translator.arm2ir.getCarryFlag(), + new OPT_IntConstantOperand(1), OPT_ConditionOperand + .EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( INT_AND_ACC, resultRegister, new OPT_IntConstantOperand( 0x80000000))); - return resultRegister; + break; default: throw new RuntimeException("Unexpected shift type: " + operand.getShiftType()); } + + translator.arm2ir.setCurrentBlock(nextBlock); + return resultRegister; } } + + + + + + + + + + + + + + + + } /** All ARM interpreter instructions implement this interface. */ @@ -298,69 +580,160 @@ } public void translate() { - throw new RuntimeException("Not yet implemented"); - } - - public Condition getCondition() { - return conditionalInstruction.getCondition(); - } - - /** Return true if the condition required by the conditional instruction is fulfilled, false otherwise.*/ - private boolean isConditionTrue() { + //conditionals are implemented easily: if the condition does not hold, then just + //jump to the block following the conditional instruction + OPT_BasicBlock nextInstruction = arm2ir.getNextBlock(); + arm2ir.getCurrentBlock().insertOut(nextInstruction); + + OPT_BasicBlock currentInstruction = arm2ir.createBlockAfterCurrent(); + switch (conditionalInstruction.getCondition()) { case AL: throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator."); case CC: - return !regs.isCarrySet(); + //return !regs.isCarrySet(); + translateCondition(nextInstruction, arm2ir.getCarryFlag(), OPT_ConditionOperand.NOT_EQUAL()); + break; case CS: - return regs.isCarrySet(); + //return regs.isCarrySet(); + translateCondition(nextInstruction, arm2ir.getCarryFlag(), OPT_ConditionOperand.EQUAL()); + break; case EQ: - return regs.isZeroSet(); + //return regs.isZeroSet(); + translateCondition(nextInstruction, arm2ir.getZeroFlag(), OPT_ConditionOperand.EQUAL()); + break; case GE: - return regs.isNegativeSet() == regs.isOverflowSet(); + //return regs.isNegativeSet() == regs.isOverflowSet(); + translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL(), arm2ir.getOverflowFlag()); + break; case GT: - return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); + translateCondition_GT(nextInstruction); + break; case HI: - return regs.isCarrySet() && !regs.isZeroSet(); + translateCondition_HI(nextInstruction); + break; case LE: - return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); + translateCondition_LE(nextInstruction); + break; case LS: - return !regs.isCarrySet() || regs.isZeroSet(); + translateCondition_LS(nextInstruction); + break; case LT: - return regs.isNegativeSet() != regs.isOverflowSet(); + //return regs.isNegativeSet() != regs.isOverflowSet(); + translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.getOverflowFlag()); + break; case MI: - return regs.isNegativeSet(); + //return regs.isNegativeSet(); + translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL()); + break; case NE: - return !regs.isZeroSet(); + //return !regs.isZeroSet(); + translateCondition(nextInstruction, arm2ir.getZeroFlag(), OPT_ConditionOperand.NOT_EQUAL()); + break; case NV: - return false; + //never execute this instruction + translateCondition(nextInstruction, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL()); + break; case PL: - return !regs.isNegativeSet(); + //return !regs.isNegativeSet(); + translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL()); + break; case VC: - return !regs.isOverflowSet(); + //return !regs.isOverflowSet(); + translateCondition(nextInstruction, arm2ir.getOverflowFlag(), OPT_ConditionOperand.NOT_EQUAL()); + break; case VS: - return regs.isOverflowSet(); + //return regs.isOverflowSet(); + translateCondition(nextInstruction, arm2ir.getOverflowFlag(), OPT_ConditionOperand.EQUAL()); + break; default: throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); } + + arm2ir.setCurrentBlock(currentInstruction); } + private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand operand, OPT_ConditionOperand condition) { + translateCondition(nextInstruction, operand, condition, new OPT_IntConstantOperand(1)); + } + + private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand lhs, OPT_ConditionOperand condition, OPT_Operand rhs) { + + condition = condition.flipCode(); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(9), lhs, rhs, condition, nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + } + + private void translateCondition_HI(OPT_BasicBlock nextInstruction) { + //return regs.isCarrySet() && !regs.isZeroSet(); + OPT_Operand carry = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_RegisterOperand result = arm2ir.getTempValidation(9); + + arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, carry, + new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + } + + private void translateCondition_LS(OPT_BasicBlock nextInstruction) { + //return !regs.isCarrySet() || regs.isZeroSet(); + OPT_Operand carry = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_RegisterOperand result = arm2ir.getTempValidation(9); + + arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, carry, + new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + } + + private void translateCondition_GT(OPT_BasicBlock nextInstruction) { + //return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); + OPT_Operand negative = arm2ir.getNegativeFlag(); + OPT_Operand overflow = arm2ir.getOverflowFlag(); + OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_RegisterOperand result = arm2ir.getTempValidation(9); + + arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, negative, + overflow, OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + } + + private void translateCondition_LE(OPT_BasicBlock nextInstruction) { + //return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); + OPT_Operand negative = arm2ir.getNegativeFlag(); + OPT_Operand overflow = arm2ir.getOverflowFlag(); + OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_RegisterOperand result = arm2ir.getTempValidation(9); + + arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, negative, + overflow, OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + } + + + public Condition getCondition() { + return conditionalInstruction.getCondition(); + } + @Override public String toString() { return conditionalInstruction.toString(); @@ -390,81 +763,102 @@ return ResolvedOperand.resolve(ARM_Translator.this, operand2); } - /** Returns teh register into which the result of a data processing operation shall be stored. */ + /** Returns the register into which the result of a data processing operation shall be stored. */ protected OPT_RegisterOperand getResultRegister() { return arm2ir.getRegister(Rd); - } - - /** Sets the result of an operation. */ - protected void setResult(OPT_RegisterOperand result) { - if (Rd == 15) { - //TODO: This is a jump, handle it accordingly - throw new RuntimeException("Not yet implemented"); - } - } + } public abstract void translate(); /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ - protected final void setFlagsForAdd(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setAddResult(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { if (updateConditionCodes) { if (Rd != 15) { - - //set the carry flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.CARRY_FROM_ADD(), new OPT_BranchProfileOperand())); - - //set the overflow flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); - - //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); - - //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + setAddFlags(result, lhs, rhs); } else { - //TODO: Implement this - regs.restoreSPSR2CPSR(); - throw new RuntimeException("Not yet implemented"); + OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); + arm2ir.appendInstructionToCurrentBlock(s); } } + + if (Rd == 15) + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } + + /** + * Sets the flags according to the result of an add operation. + * @param result + * The result of the add operation. + * @param lhs + * The left-hand-side operator. + * @param rhs + * The add's right-hand-side operator. + */ + protected void setAddFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + //set the carry flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.CARRY_FROM_ADD(), new OPT_BranchProfileOperand())); + + //set the overflow flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } /** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/ - protected final void setFlagsForSub(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setSubResult(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { if (updateConditionCodes) { if (Rd != 15) { - //set the carry flag to not(Borrow) - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); - arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); - - //set the overflow flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); - - //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); - - //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + setSubFlags(result, lhs, rhs); } else { - //TODO: Implement this - regs.restoreSPSR2CPSR(); - throw new RuntimeException("Not yet implemented"); + OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); + arm2ir.appendInstructionToCurrentBlock(s); } } + + if (Rd == 15) + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } + /** + * Sets the processor flags according to the result of a sub operation. + * @param result + * The result of the sub operation. + * @param lhs + * The sub's left-hand-side operator. + * @param rhs + * The sub's right-hand-side operator. + */ + protected void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + //set the carry flag to not(Borrow) + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); + + //set the overflow flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } + public int getSuccessor(int pc) { if (Rd != 15) return pc + 4; @@ -475,48 +869,57 @@ private abstract class DataProcessing_Logical extends DataProcessing { - /** 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 OPT_Operand shifterCarryOut; protected DataProcessing_Logical(int instr) { super(instr); } - /** - * Returns the value of the rhs-operand of the data processing instruction. - * This function also retrieves a value for the shifter carry out, which may be set when resolving - * the 2nd 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. However, the shifter carry out is only calculated, when + * the condition codes are to be modified by this function (because otherwise it won't be used anyway).*/ protected OPT_Operand resolveOperand2() { - ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveWithShifterCarryOut(ARM_Translator.this, operand2); - shifterCarryOut = resolvedOperand2.getShifterCarryOut(); - return resolvedOperand2.getValue(); + + if (updateConditionCodes) { + ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveAndStoreShifterCarryOutToCarry(ARM_Translator.this, operand2); + return resolvedOperand2.getValue(); + } + else { + return super.resolveOperand2(); + } } /** Sets the condition field for logical operations. */ - protected final void setFlagsForLogicalOperator(OPT_Operand result) { + protected final void setLogicalResult(OPT_Operand result) { if (updateConditionCodes) { if (Rd != 15) { - //TODO: Find an equivalent for BOOLEAN_MOVE - arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), shifterCarryOut)); - arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); - - //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); - - //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - + setLogicalFlags(result); } else { - //TODO: Implement this - regs.restoreSPSR2CPSR(); - throw new RuntimeException("Not yet implemented"); + OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); + arm2ir.appendInstructionToCurrentBlock(s); } } + + if (Rd == 15) + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } + + /** + * Sets the flags according to the result of a logical operation. + * @param result + * The result of the logical operation + */ + protected void setLogicalFlags(OPT_Operand result) { + //the shifter carry out has already been set during the resolve-phase + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } } /** Binary and. <code>Rd = op1 & op2 </code>.*/ @@ -532,8 +935,7 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, resolveOperand1(), resolveOperand2())); - setFlagsForLogicalOperator(result); - setResult(result); + setLogicalResult(result); } } @@ -550,8 +952,7 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_XOR, result, resolveOperand1(), resolveOperand2())); - setFlagsForLogicalOperator(result); - setResult(result); + setLogicalResult(result); } } @@ -570,8 +971,7 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); - setFlagsForAdd(result, operand1, operand2); - setResult(result); + setAddResult(result, operand1, operand2); } } @@ -590,8 +990,7 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); - setFlagsForSub(result, operand1, operand2); - setResult(result); + setSubResult(result, operand1, operand2); } } @@ -610,8 +1009,7 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand2, operand1)); - setFlagsForSub(result, operand2, operand1); - setResult(result); + setSubResult(result, operand2, operand1); } } @@ -732,7 +1130,7 @@ public void translate() { OPT_RegisterOperand result = arm2ir.getTempInt(0); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, resolveOperand1(), resolveOperand2())); - setFlagsForLogicalOperator(result); + setLogicalFlags(result); } } @@ -748,7 +1146,7 @@ public void translate() { OPT_RegisterOperand result = arm2ir.getTempInt(0); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_XOR, result, resolveOperand1(), resolveOperand2())); - setFlagsForLogicalOperator(result); + setLogicalFlags(result); } } @@ -766,7 +1164,7 @@ OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = arm2ir.getTempInt(0); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); - setFlagsForSub(result, operand1, operand2); + setSubFlags(result, operand1, operand2); } } @@ -784,7 +1182,7 @@ OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = arm2ir.getTempInt(0); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); - setFlagsForAdd(result, operand1, operand2); + setAddFlags(result, operand1, operand2); } } @@ -802,8 +1200,7 @@ OPT_RegisterOperand result = getResultRegister(); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_OR, result, operand1, operand2)); - setFlagsForLogicalOperator(result); - setResult(result); + setLogicalResult(result); } } @@ -820,9 +1217,7 @@ OPT_RegisterOperand result = getResultRegister(); arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand)); - - setResult(result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -844,13 +1239,12 @@ OPT_RegisterOperand tmp = arm2ir.getTempInt(0); arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_NOT, tmp, operand2)); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, operand1, tmp)); - setFlagsForLogicalOperator(result); - setResult(result); + setLogicalResult(result); } } /** Move and negate. Moves an integer between two registers, negating it on the way. - * <code>Rd = -op2</code>.*/ + * <code>Rd = ~op2</code>.*/ private final class DataProcessing_Mvn extends DataProcessing_Logical { protected DataProcessing_Mvn(int instr) { @@ -861,7 +1255,7 @@ public void translate() { OPT_RegisterOperand result = getResultRegister(); arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_NOT, result, resolveOperand2())); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -875,7 +1269,7 @@ @Override public void translate() { - + //Call Integer.numberOfLeadingZeros() to obtain the result of this operation OPT_RegisterOperand result = getResultRegister(); VM_TypeReference IntegerType = VM_TypeReference @@ -899,7 +1293,6 @@ .getOffset())); arm2ir.appendInstructionToCurrentBlock(s); - setResult(result); } } @@ -1144,7 +1537,7 @@ arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); } - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc+8 + getOffset())); + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc + 8 + getOffset())); } public int getSuccessor(int pc) { @@ -1161,43 +1554,51 @@ } public void translate() { - //TODO: Implement - throw new RuntimeException("Not yet implemented"); - /* //remember the previous address - int previousAddress = regs.get(ARM_Registers.PC) + 8; + int previousAddress = 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 + OPT_Operand targetAddress; - //the address of the instruction we're jumping to - int targetAddress; + //1 if we're supposed to switch to thumb mode after this call, 0 otherwise + OPT_Operand enableThumb; switch (target.getType()) { case PcRelative: - targetAddress = previousAddress + target.getOffset(); - thumb = true; + targetAddress = new OPT_IntConstantOperand(previousAddress + target.getOffset()); + + //Call regs.setThumbMode(true) to enable thumb execution + enableThumb = new OPT_IntConstantOperand(1); break; case Register: - targetAddress = regs.get(target.getRegister()); - thumb = (targetAddress & 0x1) != 0; - targetAddress = targetAddress & 0xFFFFFFFE; + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, tmp, arm2ir.getRegister(target.getRegister()), new OPT_IntConstantOperand(0xFFFFFFFE) )); + targetAddress = tmp; + + OPT_RegisterOperand tmp2 = arm2ir.getTempInt(1); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, tmp2, arm2ir.getRegister(target.getRegister()), new OPT_IntConstantOperand(0x1) )); + enableThumb = tmp2; 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);*/ + + //write the next address into the link register, if requested so. + if (link) { + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(previousAddress - 4))); + } + + //set the correct processor mode (thumb or not) + OPT_Instruction s = createCallToRegisters("setThumbMode", "(Z)V", 1); + Call.setParam(s, 1, enableThumb); + arm2ir.appendInstructionToCurrentBlock(s); + + //jump to the target address + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, targetAddress); } public int getSuccessor(int pc) { @@ -1322,15 +1723,22 @@ public void translate() { - throw new RuntimeException("Not yet implemented"); - /* + //write the current flags back to the registers class + arm2ir.spillAllFlags(lazy); + + OPT_RegisterOperand psrValue = arm2ir.getRegister(Rd); + OPT_Instruction call; + //do we have to transfer the saved or the current PSR? if (transferSavedPSR) { - regs.set(Rd, regs.getSPSR()); - } + call = createCallToRegisters("getSPSR", "()V", 0); + } else { - regs.set(Rd, regs.getCPSR()); - }*/ + call = createCallToRegisters("getCPSR", "()V", 0); + } + + Call.setResult(call, psrValue); + arm2ir.appendInstructionToCurrentBlock(call); } public int getSuccessor(int pc) { @@ -1350,8 +1758,13 @@ public void translate() { //TODO: implement - throw new RuntimeException("Not yet implemented"); + //throw new RuntimeException("Not yet implemented"); + //this variable is going to receive the new psr, which we will set + OPT_Operand new_psr = ResolvedOperand.resolve(ARM_Translator.this, sourceOperand); + + + /* //this variable is going to receive the new psr, which we will set int new_psr = ResolvedOperand.resolve(regs, sourceOperand); @@ -1472,13 +1885,21 @@ public void translate() { //should we simulate a user-mode memory access? If yes, store the current mode and fake a switch //to user mode. - OperatingMode previousMode = null; + + //stores the current operating mode + OPT_RegisterOperand currentOperatingMode = null; + if (forceUserMode) { - //TODO: implement - previousMode = ps.registers.getOperatingMode(); - ps.registers.setOperatingModeWithoutRegisterLayout(ARM_Registers.OperatingMode.USR); + OPT_Instruction call_getOperatingMode = createCallToRegisters("getOperatingMode", "()A", 0); + currentOperatingMode = arm2ir.getTempOperatingMode(); - throw new RuntimeException("Not yet implemented"); + Call.setResult(call_getOperatingMode, currentOperatingMode); + arm2ir.appendInstructionToCurrentBlock(call_getOperatingMode); + + OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1); + Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, arm2ir.getTempOperatingMode(OperatingMode.USR)); + + arm2ir.appendInstructionToCurrentBlock(call_setOperatingModeWithoutRegisterLayout); } //get the address of the memory, that we're supposed access @@ -1546,9 +1967,9 @@ //if we were writing in user mode, then switch back to our previous operating mode if (forceUserMode) { - //TODO: implement - ps.registers.setOperatingModeWithoutRegisterLayout(previousMode); - throw new RuntimeException("Not yet implemented"); + OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1); + Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, currentOperatingMode); + arm2ir.appendInstructionToCurrentBlock(call_setOperatingModeWithoutRegisterLayout); } //should the memory address, which we accessed, be written back into a register? @@ -1562,7 +1983,6 @@ else { //add the offset to the base address and write the result back into Rn OPT_Operand resolvedOffset = resolveOffset(); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, writeBackTarget, address, resolvedOffset)); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-08 16:35:57
|
Revision: 105 http://svn.sourceforge.net/pearcolator/?rev=105&view=rev Author: michael_baer Date: 2007-05-08 09:35:56 -0700 (Tue, 08 May 2007) Log Message: ----------- Fixed bugs in IntMultiply, LongMultiply and Rotate-Right-Extend (RRX) uncovered by sanity tests. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-05-02 18:27:00 UTC (rev 104) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-05-08 16:35:56 UTC (rev 105) @@ -92,8 +92,7 @@ } /** Base class for multiply operations. */ - protected abstract static class MultiplyTemplate - extends ThreeRegistersTemplate { + protected abstract static class MultiplyTemplate extends Instruction { /** @see #updateConditionCodes() */ protected final boolean updateConditionCodes; @@ -103,13 +102,25 @@ /** @see #getRs() */ protected final byte Rs; + + /** @see #getRn() */ + protected final byte Rn; + + /** @see #getRm() */ + protected final byte Rm; + + /** @see #getRd() */ + protected final byte Rd; protected MultiplyTemplate(int instr) { super(instr); updateConditionCodes = Utils.getBit(instr, 20); accumulate = Utils.getBit(instr, 21); + Rd = (byte) Utils.getBits(instr, 16, 19); + Rn = (byte) Utils.getBits(instr, 12, 15); Rs = (byte) Utils.getBits(instr, 8, 11); + Rm = (byte) Utils.getBits(instr, 0, 3); } /** Returns true, if the condition codes shall be updated by the result of this operation. */ @@ -126,6 +137,21 @@ public final byte getRs() { return Rs; } + + /** Returns the register number of the Rm operand register. */ + public final byte getRm() { + return Rm; + } + + /** Returns the register number of the Rn operand register. */ + public final byte getRn() { + return Rn; + } + + /** Returns the register number of the Rd destination register. */ + public final byte getRd() { + return Rd; + } } /** Base class for coprocessor instructions. */ @@ -172,7 +198,7 @@ LSR, ASR, ROR, - RRE + RRX } /** Creates an operand wrapper around a 12 bit immediate value. */ @@ -229,7 +255,7 @@ 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); + return new RegisterShiftImmediateOperand(shiftedRegister, ShiftType.RRX, (byte)1); } //in all other cases, an immediate of zero denotes a shift by 32 @@ -591,7 +617,7 @@ } //this instruction variant yields an undefined result - if (DBT.VerifyAssertions) DBT._assert(Rd != 15 || !writeBack); + if (DBT.VerifyAssertions) DBT._assert(Rd != Rn || !writeBack); } /** Returns true, if this memory access shall be treated as if it had been done in user mode. */ @@ -650,7 +676,6 @@ if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); } @@ -668,7 +693,7 @@ 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); + if (DBT.VerifyAssertions) DBT._assert(Rd != 15); } /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ @@ -686,7 +711,6 @@ return unsigned; } - @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-05-02 18:27:00 UTC (rev 104) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-08 16:35:56 UTC (rev 105) @@ -162,7 +162,7 @@ case ROR: return Integer.rotateRight(value, shiftAmount); - case RRE: + case RRX: if (regs.isCarrySet()) return (value >> 1) | 0x80000000; else @@ -315,7 +315,7 @@ return Integer.rotateRight(value, shiftAmount); } - case RRE: + case RRX: shifterCarryOut = (value & 0x1) != 0; if (regs.isCarrySet()) Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-02 18:27:00 UTC (rev 104) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-08 16:35:56 UTC (rev 105) @@ -265,7 +265,7 @@ translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); return resultRegister; - case RRE: + case RRX: /* * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; * else return resultRegister >>> 1; @@ -504,7 +504,7 @@ shiftAmount); return resultRegister; - case RRE: + case RRX: /* * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; * else return resultRegister >>> 1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-14 22:14:09
|
Revision: 114 http://svn.sourceforge.net/pearcolator/?rev=114&view=rev Author: michael_baer Date: 2007-05-14 15:14:10 -0700 (Mon, 14 May 2007) Log Message: ----------- First ARM DBT version that runs glibc "Hello World" Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-11 17:38:08 UTC (rev 113) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-14 22:14:10 UTC (rev 114) @@ -371,17 +371,8 @@ @Override protected int translateInstruction(Laziness lazy, int pc) { - System.out.println("Translating address: 0x" + Integer.toHexString(pc)); - System.out.println("Instruction: " + ARM_Disassembler.disassemble(pc, ps).asString()); - OPT_BasicBlock curBlock = getCurrentBlock(); - - int nextAddr = translator.translateInstruction(pc, (ARM_Laziness)lazy); - - if (nextAddr == -1) { - printNextBlocks(curBlock, 5); - } - + int nextAddr = translator.translateInstruction(pc, (ARM_Laziness)lazy); return nextAddr; } @@ -390,7 +381,7 @@ * @param block * @param count */ - private void printNextBlocks(OPT_BasicBlock block, int count) { + public void printNextBlocks(OPT_BasicBlock block, int count) { do { block.printExtended(); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-11 17:38:08 UTC (rev 113) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-14 22:14:10 UTC (rev 114) @@ -639,7 +639,7 @@ } else if (operand2 != Integer.MAX_VALUE) { operand2++; } else { - regs.setFlags(operand1 > 0, operand1 != 0, true, true); + regs.setFlags(true, true, true, true); //set the result to any of the operands regs.set(Rd, operand1); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-11 17:38:08 UTC (rev 113) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-14 22:14:10 UTC (rev 114) @@ -104,10 +104,6 @@ return value; } - protected OPT_RegisterOperand getTempInt() { - return translator.arm2ir.getTempInt(0); - } - private static class ResolvedOperand_WithoutShifterCarryOut extends ResolvedOperand { @@ -181,7 +177,7 @@ .getShiftingRegister()); } - OPT_RegisterOperand resultRegister = getTempInt(); + OPT_RegisterOperand resultRegister = translator.arm2ir.getTempInt(9); switch (operand.getShiftType()) { case ASR: @@ -221,18 +217,18 @@ case RRX: /* - * value = resultRegister >>> 1; - * if (regs.isCarrySet()) value |= 0x80000000; + * result = shiftedOperand >>> 1; + * if (regs.isCarrySet()) result |= 0x80000000; */ - // resultRegister = resultRegister >>> 1 - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( - INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + // resultRegister = shiftedOperand >>> 1 + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); //conditionally, set resultRegister = resultRegister | 0x80000000; OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); - OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); + OPT_BasicBlock nextBlock = translator.arm2ir.createBlockAfterCurrent(); OPT_BasicBlock block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); //Current block @@ -247,7 +243,7 @@ translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + translator.arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create( INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); translator.arm2ir.setCurrentBlock(nextBlock); @@ -261,11 +257,6 @@ } } - - - - - private static class ResolvedOperand_WithShifterCarryOut extends ResolvedOperand { @@ -350,15 +341,13 @@ .getShiftingRegister()); } - OPT_RegisterOperand resultRegister = getTempInt(); + OPT_RegisterOperand resultRegister = translator.arm2ir.getTempInt(8); + OPT_RegisterOperand tmp = translator.arm2ir.getTempInt(9); + OPT_RegisterOperand validation = translator.arm2ir.getTempValidation(0); - OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); + OPT_BasicBlock nextBlock = translator.arm2ir.createBlockAfterCurrent(); OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); OPT_BasicBlock block1, block2, block3; - - OPT_RegisterOperand validation = translator.arm2ir.getTempValidation(0); - - OPT_RegisterOperand tmp = translator.arm2ir.getTempInt(9); switch (operand.getShiftType()) { case ASR: @@ -492,13 +481,13 @@ case RRX: /* - * value = resultRegister >>> 1; + * value = shiftedOperand >>> 1; * if (regs.isCarrySet()) value |= 0x80000000; */ - // resultRegister = resultRegister >>> 1 - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( - INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + // resultRegister = shiftedOperand >>> 1 + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, new OPT_IntConstantOperand(1), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); //conditionally, set resultRegister = resultRegister | 0x80000000; @@ -516,7 +505,7 @@ translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + translator.arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create( INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); break; @@ -662,7 +651,7 @@ default: throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); } - + arm2ir.setCurrentBlock(condBlock); conditionalInstruction.translate(); @@ -685,7 +674,7 @@ private void translateCondition_HI(OPT_BasicBlock nextInstruction) { //return regs.isCarrySet() && !regs.isZeroSet(); OPT_Operand carry = arm2ir.getCarryFlag(); - OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, carry, @@ -697,7 +686,7 @@ private void translateCondition_LS(OPT_BasicBlock nextInstruction) { //return !regs.isCarrySet() || regs.isZeroSet(); OPT_Operand carry = arm2ir.getCarryFlag(); - OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, carry, @@ -710,7 +699,7 @@ //return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); OPT_Operand negative = arm2ir.getNegativeFlag(); OPT_Operand overflow = arm2ir.getOverflowFlag(); - OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, negative, @@ -723,7 +712,7 @@ //return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); OPT_Operand negative = arm2ir.getNegativeFlag(); OPT_Operand overflow = arm2ir.getOverflowFlag(); - OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, negative, @@ -732,7 +721,6 @@ arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } - public Condition getCondition() { return conditionalInstruction.getCondition(); } @@ -802,7 +790,7 @@ * @param rhs * The add's right-hand-side operator. */ - protected void setAddFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setAddFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { //set the carry flag arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.CARRY_FROM_ADD(), new OPT_BranchProfileOperand())); @@ -848,7 +836,7 @@ * @param rhs * The sub's right-hand-side operator. */ - protected void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { //set the carry flag to not(Borrow) arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); @@ -888,7 +876,7 @@ protected OPT_Operand resolveOperand2() { if (updateConditionCodes) { - return ResolvedOperand.resolveAndStoreShifterCarryOutToCarry(ARM_Translator.this, operand2); + return ResolvedOperand.resolveAndStoreShifterCarryOutToCarry(ARM_Translator.this, operand2); } else { return super.resolveOperand2(); @@ -918,7 +906,7 @@ * @param result * The result of the logical operation */ - protected void setLogicalFlags(OPT_Operand result) { + protected final void setLogicalFlags(OPT_Operand result) { //the shifter carry out has already been set during the resolve-phase //set the negative flag @@ -1016,7 +1004,7 @@ OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = getResultRegister(); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand2, operand1)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand2, operand1)); setSubResult(result, operand2, operand1); } @@ -1034,43 +1022,28 @@ @Override public void translate() { - throw new RuntimeException("Not yet implemented"); - - /* OPT_Operand operand1 = resolveOperand1(); OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = getResultRegister(); - OPT_RegisterOperand long_op1 = arm2ir.getTempLong(0); - OPT_RegisterOperand long_op2 = arm2ir.getTempLong(1); - OPT_RegisterOperand long_result = arm2ir.getTempLong(2); - OPT_RegisterOperand long_tmp = arm2ir.getTempLong(3); + OPT_BasicBlock addWithoutCarry = arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock addWithCarry = arm2ir.createBlockAfterCurrentNotInCFG(); + + //Is the carry set at all? if not, just jump to addWithoutCarry + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand1)); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.getCurrentBlock().insertOut(addWithCarry); + + //Yes, the carry flag is set. Pre-increase the result by one to account for the carry. + arm2ir.setCurrentBlock(addWithCarry); + arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_ADD_ACC, result, new OPT_IntConstantOperand(1))); + addWithCarry.insertOut(addWithoutCarry); + + //Finally, add the second operands to the result + arm2ir.setCurrentBlock(addWithoutCarry); + arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_ADD_ACC, result, operand2)); - //convert the operands to longs. Be careful to treat them as unsigned ints during the conversion - arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, long_op1, operand1)); - arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_op1, long_op1, new OPT_LongConstantOperand(0xFFFFFFFF))); - arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, long_op2, operand2)); - arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_op2, long_op2, new OPT_LongConstantOperand(0xFFFFFFFF))); - - //perform the actual addition - arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_ADD, long_result, long_op1, long_op2)); - arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_ADD, long_result, long_result, new OPT_LongConstantOperand(1))); - arm2ir.appendInstructionToCurrentBlock(Unary.create(LONG_2INT, result, long_result)); - - //set the carry flag if the upper 32 bit of the result are != 0 - arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_tmp, long_result, new OPT_LongConstantOperand(0xFFFFFFFF))); - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), long_tmp, new OPT_LongConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), OPT_BranchProfileOperand.unlikely())); - - //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); - - //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - - //commit the result - setResult(result);*/ + setAddResult(result, operand1, operand2); } } @@ -1084,28 +1057,26 @@ public void translate() { OPT_Operand operand1 = resolveOperand1(); OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); - //TODO: Implement - throw new RuntimeException("Not yet implemented"); - - /* - if (!regs.isCarrySet()) { - if (operand1 != Integer.MIN_VALUE) { - operand1--; - } else if (operand2 != Integer.MIN_VALUE) { - operand2--; - } else { - //TODO: Remove this exception, when the correct behavior has been verified. - throw new RuntimeException("I'm interested in finding a case where this occurs, so this exception is sooner or later going to 'notify' me.."); - //regs.setFlags(operand1 > 0, operand1 != 0, true, true); - //return; - } - } + OPT_BasicBlock subWithoutCarry = arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock subWithCarry = arm2ir.createBlockAfterCurrentNotInCFG(); - int result = operand1 - operand2; + //Is the carry set? if yes, just jump to subWithoutCarry + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand1)); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), subWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.getCurrentBlock().insertOut(subWithCarry); + + //No, the carry flag is not set. That means, we have to use the carry within the subtraction (weird arm logic). + arm2ir.setCurrentBlock(subWithCarry); + arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_SUB_ACC, result, new OPT_IntConstantOperand(1))); + subWithCarry.insertOut(subWithoutCarry); - regs.set(Rd, result); - setFlagsForSub(operand1, operand2);*/ + //Finally, subtract the second operands from the result + arm2ir.setCurrentBlock(subWithoutCarry); + arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_SUB_ACC, result, operand2)); + + setSubResult(result, operand1, operand2); } } @@ -1950,15 +1921,23 @@ switch (size) { case Word: + //perform the actual memory access ps.memory.translateLoad32(address, value); //according to the ARM reference, the last two bits cause the value to be right-rotated - OPT_RegisterOperand rotation = arm2ir.getTempInt(0); + OPT_RegisterOperand rotation = arm2ir.getTempInt(1); + + //make sure that we're not loosing the address due to the shifting + OPT_RegisterOperand adrCopy = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, adrCopy, address)); //rotation = (address & 0x3) * 8 arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, rotation, address, new OPT_IntConstantOperand(0x3))); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHL, rotation, rotation, new OPT_IntConstantOperand(3))); arm2ir.appendRotateRight(value, value, rotation); + + //allow further usage of the memory address + address = adrCopy; break; case HalfWord: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-13 16:35:33
|
Revision: 131 http://svn.sourceforge.net/pearcolator/?rev=131&view=rev Author: michael_baer Date: 2007-06-13 09:35:34 -0700 (Wed, 13 Jun 2007) Log Message: ----------- Moving towards Thumb support... Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.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/ARM_Translator.java src/org/binarytranslator/arch/arm/decoder/CountingInstructionFactory.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-06-13 16:35:34 UTC (rev 131) @@ -3,7 +3,6 @@ import java.util.ArrayList; import org.binarytranslator.DBT; -import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; @@ -24,15 +23,19 @@ private OPT_Register regMap[] = new OPT_Register[16]; /** The ARM carry flag. */ + private boolean carryUsed; private OPT_Register carryFlag; /** The ARM zero flag. */ + private boolean zeroUsed; private OPT_Register zeroFlag; /** The ARM negative flag. */ + private boolean negativeUsed; private OPT_Register negativeFlag; /** The ARM overflow flag. */ + private boolean overflowUsed; private OPT_Register overflowFlag; /** Set to true for each register that is in use during the current trace */ @@ -215,22 +218,31 @@ private void spillAllFlags() { OPT_RegisterOperand ps_registersOp = getArmRegistersReference(); + OPT_RegisterOperand flag; //store the carry flag - OPT_RegisterOperand flag = new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); - appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_carryFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_carryFlag_Fref), new OPT_TrueGuardOperand()) ); + if (carryUsed) { + flag = new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); + appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_carryFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_carryFlag_Fref), new OPT_TrueGuardOperand()) ); + } //store the negative flag - flag = new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean); - appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_negativeFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_negativeFlag_Fref), new OPT_TrueGuardOperand()) ); + if (negativeUsed) { + flag = new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean); + appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_negativeFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_negativeFlag_Fref), new OPT_TrueGuardOperand()) ); + } //store the zero flag - flag = new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean); - appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_zeroFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_zeroFlag_Fref), new OPT_TrueGuardOperand()) ); + if (zeroUsed) { + flag = new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean); + appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_zeroFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_zeroFlag_Fref), new OPT_TrueGuardOperand()) ); + } //store the overflow flag - flag = new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean); - appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_overflowFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_overflowFlag_Fref), new OPT_TrueGuardOperand()) ); + if (overflowUsed) { + flag = new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean); + appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_overflowFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_overflowFlag_Fref), new OPT_TrueGuardOperand()) ); + } } public void fillAllFlags() { @@ -308,18 +320,22 @@ } public OPT_RegisterOperand getCarryFlag() { + carryUsed = true; return new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); } public OPT_RegisterOperand getZeroFlag() { + zeroUsed = true; return new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean); } public OPT_RegisterOperand getNegativeFlag() { + negativeUsed = true; return new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean); } public OPT_RegisterOperand getOverflowFlag() { + overflowUsed = true; return new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean); } @@ -328,11 +344,24 @@ ArrayList<OPT_Register> unusedRegisters = new ArrayList<OPT_Register>(); - for (int i = 0; i < regUsed.length; i++) + for (int i = 0; i < regUsed.length; i++) { if (!regUsed[i]) { unusedRegisters.add(regMap[i]); } + } + if (!carryUsed) + unusedRegisters.add(carryFlag); + + if (!negativeUsed) + unusedRegisters.add(negativeFlag); + + if (!overflowUsed) + unusedRegisters.add(overflowFlag); + + if (!zeroUsed) + unusedRegisters.add(zeroFlag); + return unusedRegisters.toArray(new OPT_Register[unusedRegisters.size()]); } @@ -345,6 +374,15 @@ public void resolveLaziness(Laziness laziness) { //NO-OP, as we're not using laziness at the moment } + + @Override + public void appendSystemCall(Laziness lazy) { + super.appendSystemCall(lazy); + + //ARM system calls may change all registers + for (int i = 0; i < 15; i++) + regUsed[i] = true; + } @Override protected void spillAllRegisters() { @@ -353,10 +391,8 @@ OPT_RegisterOperand ps_registers_regsOp = new OPT_RegisterOperand( ps_registers_regs, registers_regs_Tref); for (int i = 0; i < regMap.length; i++) { - // We can save spills if the trace has no syscalls and the register was - // never used - if ((DBT_Options.singleInstrTranslation == false) - || (regUsed[i] == true)) { + // We can save spills if the register was never used + if (regUsed[i] == true) { appendInstruction(AStore.create(INT_ASTORE, new OPT_RegisterOperand(regMap[i], VM_TypeReference.Int), ps_registers_regsOp.copyRO(), new OPT_IntConstantOperand(i), Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-13 16:35:34 UTC (rev 131) @@ -1,7 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction; -import org.binarytranslator.arch.arm.decoder.ARM_Instructions.MultipleDataTransfer; +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; @@ -320,7 +320,7 @@ instr.getRd(), instr.getRm(), instr.getRn())); } - public void visit(MultipleDataTransfer instr) { + public void visit(BlockDataTransfer instr) { String mnemonic = instr.isLoad() ? "LDM" : "STM"; String baseRegister = "r" + instr.getBaseRegister(); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-13 16:35:34 UTC (rev 131) @@ -286,6 +286,22 @@ T createMoveFromStatusRegister(int instr); T createMoveToStatusRegister(int instr); T createUndefinedInstruction(int instr); + + T createDataProcessing(short instr); + T createSwap(short instr); + T createSingleDataTransfer(short instr); + T createBlockDataTransfer(short instr); + T createshortMultiply(short instr); + T createLongMultiply(short instr); + T createSoftwareshorterrupt(short instr); + T createBranch(short instr); + T createBranchExchange(short instr); + T createCoprocessorDataTransfer(short instr); + T createCoprocessorDataProcessing(short instr); + T createCoprocessorRegisterTransfer(short instr); + T createMoveFromStatusRegister(short instr); + T createMoveToStatusRegister(short instr); + T createUndefinedInstruction(short instr); } /** @@ -295,7 +311,7 @@ private static class DefaultFactory implements ARM_InstructionFactory<ARM_Instructions.Instruction> { public Instruction createBlockDataTransfer(int instr) { - return new MultipleDataTransfer(instr); + return new BlockDataTransfer(instr); } public Instruction createBranch(int instr) { @@ -353,6 +369,81 @@ public Instruction createUndefinedInstruction(int instr) { return null; } + + public Instruction createBlockDataTransfer(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createBranch(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createBranchExchange(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createCoprocessorDataProcessing(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createCoprocessorDataTransfer(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createCoprocessorRegisterTransfer(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createDataProcessing(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createLongMultiply(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createMoveFromStatusRegister(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createMoveToStatusRegister(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createSingleDataTransfer(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createSoftwareshorterrupt(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createSwap(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createUndefinedInstruction(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createshortMultiply(short instr) { + // TODO Auto-generated method stub + return null; + } } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-06-13 16:35:34 UTC (rev 131) @@ -10,7 +10,7 @@ void visit(IntMultiply instr); void visit(LongMultiply instr); void visit(Swap instr); - void visit(MultipleDataTransfer instr); + void visit(BlockDataTransfer instr); void visit(SoftwareInterrupt instr); void visit(Branch instr); void visit(BranchExchange instr); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-13 16:35:34 UTC (rev 131) @@ -1,6 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.DBT; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper.ShiftType; /** * In the ARM decoder model, the decoding and usage (translating/interpreting/disassembling) of instructions @@ -26,6 +27,14 @@ /** @see #getCondition() */ protected final Condition condition; + + private Instruction () { + this.condition = Condition.AL; + } + + private Instruction (Condition condition) { + this.condition = condition; + } private Instruction(int instr) { condition = Condition.values()[(instr & 0xF0000000) >>> 28]; @@ -45,52 +54,6 @@ 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) Utils.getBits(instr, 12, 15); - Rn = (byte) Utils.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) Utils.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 Instruction { @@ -216,6 +179,14 @@ return new PcRelativeOperand(offset); } + public static OperandWrapper createRegisterShiftImmediate(byte register, ShiftType type, byte amount) { + return new RegisterShiftImmediateOperand(register, type, amount); + } + + public static OperandWrapper createRegisterShiftRegister(byte register, ShiftType type, byte reg2) { + return new RegisterShiftRegisterOperand(register, type, reg2); + } + public static OperandWrapper decodeDataProcessingOperand(int instr) { if (Utils.getBit(instr, 25)) { //this is a right-rotated immediate value @@ -467,7 +438,7 @@ } /** Represents a Data Processing instruction. */ - public static class DataProcessing extends TwoRegistersTemplate { + public final 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 @@ -475,7 +446,13 @@ public enum Opcode { AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN, CLZ } + + /** @see #getRn() */ + protected final byte Rn; + /** @see #getRd() */ + protected final byte Rd; + /** @see #hasSetConditionCodes() */ protected final boolean updateConditionCodes; @@ -484,14 +461,153 @@ /** @see #getOperand2() */ protected final OperandWrapper operand2; + + public DataProcessing(short instr) { + if (Utils.getBits(instr, 13, 15) == 0) { + //shift by immediate, add/subtract register or add/subtract immediate + Rd = (byte)Utils.getBits(instr, 0, 2); + Rn = (byte)Utils.getBits(instr, 3, 5); + updateConditionCodes = true; + + if (Utils.getBits(instr, 11, 12) == 0) { + //shift by immediate + opcode = Opcode.MOV; + ShiftType type = ShiftType.values()[Utils.getBits(instr, 11, 12)]; + operand2 = OperandWrapper.createRegisterShiftImmediate(Rn, type, (byte)Utils.getBits(instr, 6, 10)); + } + else { + //add/subtract register or add/subtract immediate + opcode = Utils.getBit(instr, 9) ? Opcode.SUB : Opcode.ADD; + if (Utils.getBit(instr, 10)) + operand2 = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 8)); + else + operand2 = OperandWrapper.createRegister((byte)Utils.getBits(instr, 6, 8)); + } + } + else { + if (Utils.getBit(instr, 13)) { + //Move, Compare, Add, Subtract immediate + Rd = (byte)Utils.getBits(instr, 8, 10); + Rn = Rd; + operand2 = OperandWrapper.createImmediate(instr & 0xFF); + updateConditionCodes = true; + + switch (Utils.getBits(instr, 11, 12)) { + case 0: + opcode = Opcode.MOV; + break; + case 1: + opcode = Opcode.CMP; + break; + case 2: + opcode = Opcode.ADD; + break; + case 3: + opcode = Opcode.SUB; + break; + default: + throw new RuntimeException("Values other than 0-4 cannot be represented within 2 bits."); + } + } + else { + Rd = (byte)Utils.getBits(instr, 0, 2); + byte finalRn = (byte)Utils.getBits(instr, 3, 5); + updateConditionCodes = true; + + switch (Utils.getBits(instr, 6, 9)) { + case 0: + opcode = Opcode.AND; + operand2 = OperandWrapper.createRegister(Rd); + break; + case 1: + opcode = Opcode.EOR; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 2: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSL, finalRn); + break; + + case 3: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSR, finalRn); + break; + + case 4: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ASR, finalRn); + break; + + case 5: + opcode = Opcode.ADC; + operand2 = OperandWrapper.createRegister(Rd); + break; - /** @see #getRd() */ - protected final byte Rd; + case 6: + opcode = Opcode.SBC; + operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; + break; + + case 7: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ROR, finalRn); + break; + + case 8: + opcode = Opcode.TST; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 9: + opcode = Opcode.RSB; + operand2 = OperandWrapper.createImmediate(0); + break; + + case 10: + opcode = Opcode.CMP; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 11: + opcode = Opcode.CMN; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 12: + opcode = Opcode.ORR; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 13: + throw new RuntimeException("This is actually a multiply instruction."); + + case 14: + opcode = Opcode.BIC; + operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; + break; + + case 15: + opcode = Opcode.MVN; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + default: + throw new RuntimeException("Only values 0-15 can be represented within 4 bits."); + } + + Rn = finalRn; + } + } + } public DataProcessing(int instr) { super(instr); Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); updateConditionCodes = Utils.getBit(instr, 20); @@ -525,11 +641,21 @@ public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); } + + /** 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; + } } /** Represents a LDR/SDR instruction. */ - public static class SingleDataTransfer extends - TwoRegistersTemplate { + public final static class SingleDataTransfer extends + Instruction { public enum TransferSize { Byte, @@ -561,8 +687,17 @@ /** @see #getOffset() */ protected final OperandWrapper offset; + /** @see #getRn() */ + protected final byte Rn; + + /** @see #getRd() */ + protected final byte Rd; + public SingleDataTransfer(int instr) { super(instr); + + Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); preIndexing = Utils.getBit(instr, 24); positiveOffset = Utils.getBit(instr, 23); @@ -620,6 +755,16 @@ if (DBT.VerifyAssertions) DBT._assert(Rd != Rn || !writeBack); } + /** 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; + } + /** Returns true, if this memory access shall be treated as if it had been done in user mode. */ public final boolean forceUserMode() { return forceUserMode; @@ -667,7 +812,7 @@ } /** Represents a normal (not long) multiply instruction. */ - public static class IntMultiply extends MultiplyTemplate { + public final static class IntMultiply extends MultiplyTemplate { protected IntMultiply(int instr) { super(instr); @@ -682,7 +827,7 @@ } /** Represents a long multiply instruction. */ - public static class LongMultiply extends MultiplyTemplate { + public final static class LongMultiply extends MultiplyTemplate { /** @see #isUnsigned() */ protected final boolean unsigned; @@ -717,13 +862,27 @@ } /** Represents a SWP/SWPB instruction. */ - public static class Swap extends ThreeRegistersTemplate { + public final static class Swap extends Instruction { /** @see #swapByte() */ protected final boolean swapByte; + + /** @see #getRm() */ + protected final byte Rm; + + /** @see #getRn() */ + protected final byte Rn; + /** @see #getRd() */ + protected final byte Rd; + public Swap(int instr) { super(instr); + + Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); + + Rm = (byte) Utils.getBits(instr, 0, 3); swapByte = Utils.getBit(instr, 22); } @@ -731,15 +890,29 @@ public final boolean swapByte() { return swapByte; } + + /** Returns the number of the second operand register, starting from 0.*/ + public final byte getRm() { + return Rm; + } + + /** Returns the number of the operation's destination register, starting from 0.*/ + public final byte getRd() { + return Rd; + } - @Override + /** Returns the number of the operation's first operand register, starting from 0.*/ + public final byte getRn() { + return Rn; + } + public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); } } /** Represents a LDM/STM instruction. */ - public static class MultipleDataTransfer extends Instruction { + public final static class BlockDataTransfer extends Instruction { /** @see #postIndexing() */ protected final boolean postIndexing; @@ -762,7 +935,7 @@ /** Contains a set bit at position N if rN should be transferred using this instruction.*/ protected final int registerList; - public MultipleDataTransfer(int instr) { + public BlockDataTransfer(int instr) { super(instr); postIndexing = !Utils.getBit(instr, 24); @@ -819,10 +992,15 @@ } /** Represents a SWI instruction*/ - public static class SoftwareInterrupt extends Instruction { + public final static class SoftwareInterrupt extends Instruction { /** @see #getInterruptNumber() */ protected final int interruptNumber; + + public SoftwareInterrupt(short instr) { + super(Condition.AL); + interruptNumber = instr & 0xFF; + } public SoftwareInterrupt(int instr) { super(instr); @@ -872,7 +1050,7 @@ } /** Represents a BX instruction set */ - public static class BranchExchange extends Instruction { + public final static class BranchExchange extends Instruction { /** @see #target() */ protected final OperandWrapper target; @@ -919,7 +1097,7 @@ } /** Represents a LDC/STC instruction. */ - public static class CoprocessorDataTransfer extends CoprocessorTemplate { + public final static class CoprocessorDataTransfer extends CoprocessorTemplate { /** @see #getOffset() */ protected final int offset; @@ -1004,7 +1182,7 @@ } /** Represents a CDP instruction. */ - public static class CoprocessorDataProcessing extends CoprocessorTemplate { + public final static class CoprocessorDataProcessing extends CoprocessorTemplate { /** @see #getOpcode() */ protected final byte opcode; @@ -1055,7 +1233,7 @@ } /** Represents a MRC/MCR instruction. */ - public static class CoprocessorRegisterTransfer extends CoprocessorTemplate { + public final static class CoprocessorRegisterTransfer extends CoprocessorTemplate { /** @see #getOpcode() */ protected final byte opcode; @@ -1115,7 +1293,7 @@ } /** Represents a MRS instruction. */ - public static class MoveFromStatusRegister extends Instruction { + public final static class MoveFromStatusRegister extends Instruction { /** @see #getRd() */ protected final byte Rd; @@ -1149,7 +1327,7 @@ } /** Represents a MSR instruction. */ - public static class MoveToStatusRegister extends Instruction { + public final static class MoveToStatusRegister extends Instruction { /** @see #transferControlField() */ protected final boolean transferControl; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-13 16:35:34 UTC (rev 131) @@ -35,7 +35,7 @@ public ARM_Interpreter(ARM_ProcessSpace ps) { this.ps = ps; this.regs = ps.registers; - instructionFactory = new CountingInstructionFactory<ARM_Instruction>(new InterpreterFactory()); + instructionFactory = new InterpreterFactory(); //new CountingInstructionFactory<ARM_Instruction>( } /** Decodes the instruction at the given address.*/ @@ -340,7 +340,6 @@ /** 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(); } @@ -351,10 +350,12 @@ private final class ConditionalDecorator implements Interpreter.Instruction { protected final ARM_Instruction conditionalInstruction; + private final Condition condition; /** Decorates an ARM interpreter instruction, by making it execute conditionally. */ protected ConditionalDecorator(ARM_Instruction i) { conditionalInstruction = i; + this.condition = i.getCondition(); } public void execute() { @@ -380,7 +381,7 @@ /** Return true if the condition required by the conditional instruction is fulfilled, false otherwise.*/ private boolean isConditionTrue() { - switch (conditionalInstruction.getCondition()) { + switch (condition) { case AL: throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator."); @@ -430,7 +431,7 @@ return regs.isOverflowSet(); default: - throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); + throw new RuntimeException("Unexpected condition code: " + condition); } } @@ -441,26 +442,27 @@ } /** A base class for all data processing interpreter instructions, including CLZ.*/ - private abstract class DataProcessing extends ARM_Instructions.DataProcessing - implements ARM_Instruction { + private abstract class DataProcessing implements ARM_Instruction { + + protected final ARM_Instructions.DataProcessing i; - protected DataProcessing(int instr) { - super(instr); + protected DataProcessing(ARM_Instructions.DataProcessing instr) { + i = instr; } /** Returns the value of operand 1 of the data processing instruction. This is always a register value. */ protected int resolveOperand1() { - if (Rn == ARM_Registers.PC) { - return regs.get(Rn) + 8; + if (i.Rn == ARM_Registers.PC) { + return regs.get(i.Rn) + 8; } - return regs.get(Rn); + return regs.get(i.Rn); } /** Returns the value of the rhs-operand of the data processing instruction. */ protected int resolveOperand2() { - return ResolvedOperand.resolve(regs, operand2); + return ResolvedOperand.resolve(regs, i.operand2); } public abstract void execute(); @@ -474,11 +476,11 @@ protected final void setAddResult(int lhs, int rhs) { setFlagsForAdd(lhs, rhs); - if (DBT_Options.profileDuringInterpretation && Rd == 15) { + if (DBT_Options.profileDuringInterpretation && i.Rd == 15) { ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs + rhs, BranchType.INDIRECT_BRANCH); } - regs.set(Rd, lhs + rhs); + regs.set(i.Rd, lhs + rhs); } /** @@ -490,18 +492,18 @@ protected final void setSubResult(int lhs, int rhs) { setFlagsForSub(lhs, rhs); - if (DBT_Options.profileDuringInterpretation && Rd == 15) { + if (DBT_Options.profileDuringInterpretation && i.Rd == 15) { ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs - rhs, BranchType.INDIRECT_BRANCH); } - regs.set(Rd, lhs - rhs); + regs.set(i.Rd, lhs - rhs); } /** 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) { - if (Rd != 15) { + if (i.updateConditionCodes) { + if (i.Rd != 15) { int result = lhs + rhs; boolean carry = Utils.unsignedAddOverflow(lhs, rhs); boolean overflow = Utils.signedAddOverflow(lhs, rhs); @@ -516,8 +518,8 @@ /** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/ protected final void setFlagsForSub(int lhs, int rhs) { - if (updateConditionCodes) { - if (Rd != 15) { + if (i.updateConditionCodes) { + if (i.Rd != 15) { int result = lhs - rhs; boolean carry = !Utils.unsignedSubOverflow(lhs, rhs); boolean overflow = Utils.signedSubOverflow(lhs, rhs); @@ -528,9 +530,13 @@ } } } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { - if (Rd != 15) + if (i.Rd != 15) return pc + 4; else return -1; @@ -543,7 +549,7 @@ * out value. The value of the barrel shifter is stored within this variable. */ protected boolean shifterCarryOut; - protected DataProcessing_Logical(int instr) { + protected DataProcessing_Logical(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -552,8 +558,8 @@ * the condition codes are to be modified by this function (because otherwise it won't be used anyway).*/ protected int resolveOperand2() { - if (updateConditionCodes) { - ResolvedOperand operand = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); + if (i.updateConditionCodes) { + ResolvedOperand operand = ResolvedOperand.resolveWithShifterCarryOut(regs, i.operand2); shifterCarryOut = operand.getShifterCarryOut(); return operand.getValue(); } @@ -566,22 +572,22 @@ * is set, also sets the flags accordingly. */ protected final void setLogicalResult(int result) { - if (DBT_Options.profileDuringInterpretation && Rd == 15) { - if (getOpcode() == Opcode.MOV && operand2.getType() == OperandWrapper.Type.Register && operand2.getRegister() == ARM_Registers.LR) + if (DBT_Options.profileDuringInterpretation && i.Rd == 15) { + if (i.getOpcode() == Opcode.MOV && i.operand2.getType() == OperandWrapper.Type.Register && i.operand2.getRegister() == ARM_Registers.LR) ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), result); else ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); } - regs.set(Rd, result); + regs.set(i.Rd, result); setFlagsForLogicalOperator(result); } /** Sets the condition field for logical operations. */ protected final void setFlagsForLogicalOperator(int result) { - if (updateConditionCodes) { - if (Rd != 15) { + if (i.updateConditionCodes) { + if (i.Rd != 15) { regs.setFlags(result < 0, result == 0, shifterCarryOut); } else { regs.restoreSPSR2CPSR(); @@ -593,7 +599,7 @@ /** Binary and. <code>Rd = op1 & op2 </code>.*/ private final class DataProcessing_And extends DataProcessing_Logical { - protected DataProcessing_And(int instr) { + protected DataProcessing_And(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -607,7 +613,7 @@ /** Exclusive or. <code>Rd = op1 ^ op2 </code>.*/ private final class DataProcessing_Eor extends DataProcessing_Logical { - protected DataProcessing_Eor(int instr) { + protected DataProcessing_Eor(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -621,7 +627,7 @@ /** Add. <code>Rd = op1 + op2 </code>.*/ private final class DataProcessing_Add extends DataProcessing { - public DataProcessing_Add(int instr) { + public DataProcessing_Add(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -636,7 +642,7 @@ /** Subtract. <code>Rd = op1 - op2 </code>.*/ private final class DataProcessing_Sub extends DataProcessing { - public DataProcessing_Sub(int instr) { + public DataProcessing_Sub(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -651,7 +657,7 @@ /** Reverse subtract. <code>Rd = op2 - op1</code>.*/ private final class DataProcessing_Rsb extends DataProcessing { - protected DataProcessing_Rsb(int instr) { + protected DataProcessing_Rsb(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -668,7 +674,7 @@ * not cause an overflow). Then, the normal add-routine is being invoked. */ private final class DataProcessing_Adc extends DataProcessing { - protected DataProcessing_Adc(int instr) { + protected DataProcessing_Adc(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -686,7 +692,7 @@ regs.setFlags(true, true, true, true); //set the result to any of the operands - regs.set(Rd, operand1); + regs.set(i.Rd, operand1); return; } } @@ -698,7 +704,7 @@ /** Subtract with carry. <code>Rd = op1 - op2 - NOT(CARRY)</code>.*/ private class DataProcessing_Sbc extends DataProcessing { - protected DataProcessing_Sbc(int instr) { + protected DataProcessing_Sbc(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -727,7 +733,7 @@ /** Reserve subtract with carry. <code>Rd = -op1 + op2 - NOT(CARRY)</code>.*/ private final class DataProcessing_Rsc extends DataProcessing_Sbc { - protected DataProcessing_Rsc(int instr) { + protected DataProcessing_Rsc(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -746,7 +752,7 @@ * <code>Flags = op1 & op2</code>*/ private final class DataProcessing_Tst extends DataProcessing_Logical { - protected DataProcessing_Tst(int instr) { + protected DataProcessing_Tst(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -760,7 +766,7 @@ * <code>Flags = op1 ^ op2</code> */ private final class DataProcessing_Teq extends DataProcessing_Logical { - protected DataProcessing_Teq(int instr) { + protected DataProcessing_Teq(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -774,7 +780,7 @@ * <code>Flags = op1 - op2</code> */ private final class DataProcessing_Cmp extends DataProcessing { - protected DataProcessing_Cmp(int instr) { + protected DataProcessing_Cmp(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -788,7 +794,7 @@ * <code>Flags = op1 + op2</code>. */ private final class DataProcessing_Cmn extends DataProcessing { - protected DataProcessing_Cmn(int instr) { + protected DataProcessing_Cmn(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -801,7 +807,7 @@ /** Binary or. <code>Rd = op1 | op2</code>. */ private final class DataProcessing_Orr extends DataProcessing_Logical { - protected DataProcessing_Orr(int instr) { + protected DataProcessing_Orr(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -814,7 +820,7 @@ private final class DataProcessing_Mov extends DataProcessing_Logical { - protected DataProcessing_Mov(int instr) { + protected DataProcessing_Mov(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -830,7 +836,7 @@ * <code>Rd = op1 & (~op2)</code>.*/ private final class DataProcessing_Bic extends DataProcessing_Logical { - protected DataProcessing_Bic(int instr) { + protected DataProcessing_Bic(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -846,7 +852,7 @@ * <code>Rd = ~op2</code>.*/ private final class DataProcessing_Mvn extends DataProcessing_Logical { - protected DataProcessing_Mvn(int instr) { + protected DataProcessing_Mvn(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -861,43 +867,48 @@ * <code>Rd = Number_Of_Leading_Zeroes(op2) </code> */ private final class DataProcessing_Clz extends DataProcessing { - protected DataProcessing_Clz(int instr) { + protected DataProcessing_Clz(ARM_Instructions.DataProcessing instr) { super(instr); } @Override public void execute() { int result = Integer.numberOfLeadingZeros(resolveOperand2()); - regs.set(Rd, result); + regs.set(i.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 final class Swap extends ARM_Instructions.Swap implements - ARM_Instruction { + private final class Swap implements ARM_Instruction { + + private final ARM_Instructions.Swap i; - public Swap(int instr) { - super(instr); + public Swap(ARM_Instructions.Swap instr) { + i = instr; } + + public Condition getCondition() { + return i.condition; + } public void execute() { - int memAddr = regs.get(Rn); + int memAddr = regs.get(i.Rn); //swap exchanges the value of a memory address with the value in a register - if (!swapByte) { + if (!i.swapByte) { int tmp = ps.memory.load32(memAddr); - ps.memory.store32(memAddr, regs.get(Rm)); + ps.memory.store32(memAddr, regs.get(i.Rm)); //according to the ARM architecture reference, the value loaded from a memory address is rotated //by the number of ones in the first two bits of the address - regs.set(Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); + regs.set(i.Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); } else { int tmp = ps.memory.loadUnsigned8(memAddr); - ps.memory.store8(memAddr, regs.get(Rm)); - regs.set(Rd, tmp); + ps.memory.store8(memAddr, regs.get(i.Rm)); + regs.set(i.Rd, tmp); } } @@ -909,8 +920,10 @@ } /** Transfer multiple registers at once between the register bank and the memory. */ - private final class BlockDataTransfer extends ARM_Instructions.MultipleDataTransfer + private final class BlockDataTransfer implements ARM_Instruction { + + private final ARM_Instructions.BlockDataTransfer i; /** the lowest address that we're reading a register from / writing a register to */ private final int registerCount; @@ -923,14 +936,14 @@ /** True if the PC should be transferred to, false otherwise. */ private final boolean transferPC; - public BlockDataTransfer(int instr) { - super(instr); + public BlockDataTransfer(ARM_Instructions.BlockDataTransfer instr) { + i = instr; - transferPC = transferRegister(15); + transferPC = i.transferRegister(15); int regCount = 0; for (int i = 0; i <= 14; i++) - if (transferRegister(i)) { + if (this.i.transferRegister(i)) { registersToTransfer[regCount++] = i; } @@ -941,10 +954,10 @@ public void execute() { //build the address, which generally ignores the last two bits - int startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + int startAddress = regs.get(i.baseRegister) & 0xFFFFFFFC; - if (!incrementBase) { - if (postIndexing) { + if (!i.incrementBase) { + if (i.postIndexing) { //post-indexing, backward reading startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; } else { @@ -952,7 +965,7 @@ startAddress -= (registerCount + (transferPC ? 2 : 1)) * 4; } } else { - if (postIndexing) { + if (i.postIndexing) { //post-indexing, forward reading startAddress -= 4; } else { @@ -965,14 +978,14 @@ OperatingMode previousMode = ps.registers.getOperatingMode(); //if we should transfer the user mode registers... - if (forceUser) { + if (i.forceUser) { //... then change the current register map, but do NOT change the current processor mode ps.registers.switchOperatingMode(OperatingMode.USR); ps.registers.setOperatingModeWithoutRegisterLayout(previousMode); } //are we supposed to load or store multiple registers? - if (isLoad) { + if (i.isLoad) { int nextReg = 0; while (registersToTransfer[nextReg] != -1) { @@ -989,7 +1002,7 @@ if (DBT_Options.profileDuringInterpretation) ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), newpc); - if (forceUser) { + if (i.forceUser) { //when we are transferring the PC with a forced-user transfer, then we also want to //restore the CPSR from the SPSR. //However, at the moment our register layout is different from our operating mode. @@ -1030,16 +1043,16 @@ } //restore the register layout, if we were transferring the user mode registers - if (forceUser) { + if (i.forceUser) { ps.registers.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); ps.registers.switchOperatingMode(previousMode); } - if (writeBack) { + if (i.writeBack) { //write the last address we read from back to a register - if (!incrementBase) { + if (!i.incrementBase) { //backward reading - if (postIndexing) { + if (i.postIndexing) { //backward reading, post-indexing nextAddress = startAddress; } @@ -1050,17 +1063,21 @@ } else { //forward reading - if (postIndexing) + if (i.postIndexing) nextAddress += 4; } - regs.set(baseRegister, nextAddress); + regs.set(i.baseRegister, nextAddress); } } + public Condition getCondition() { + return i.condition; + } + 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 && transferPC) + if (i.isLoad && transferPC) return -1; else return pc + 4; @@ -1068,38 +1085,45 @@ } /** Branch to another instruction address. */ - private final class Branch extends ARM_Instructions.Branch implements - ARM_Instruction { + private final class Branch implements ARM_Instruction { + + private final ARM_Instructions.Branch i; - public Branch(int instr) { - super(instr); + public Branch(ARM_Instructions.Branch instr) { + i = instr; } public void execute() { //if we're supposed to link, then write the previous address into the link register - if (link) { + if (i.link) { regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + 4); if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + getOffset() + 8, regs.get(ARM_Registers.PC) + 4); + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + i.getOffset() + 8, regs.get(ARM_Registers.PC) + 4); } else { if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + getOffset() + 8, BranchType.DIRECT_BRANCH); + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + i.getOffset() + 8, BranchType.DIRECT_BRANCH); } } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { - return pc + getOffset() + 8; + return pc + i.getOffset() + 8; } } /** Branch to another instruction address and switch between ARM32 and Thumb code on the way.*/ - private final class BranchExchange extends ARM_Instructions.BranchExchange + private final class BranchExchange implements ARM_Instruction { + + private final ARM_Instructions.BranchExchange i; - public BranchExchange(int instr) { - super(instr); + public BranchExchange(ARM_Instructions.BranchExchange instr) { + i = instr; } public void execute() { @@ -1112,42 +1136,45 @@ //the address of the instruction we're jumping to int targetAddress; - switch (target.getType()) { + switch (i.target.getType()) { case PcRelative: - targetAddress = previousAddress + target.getOffset(); + targetAddress = previousAddress + i.target.getOffset(); thumb = true; break; case Register: - targetAddress = regs.get(target.getRegister()); + targetAddress = regs.get(i.target.getRegister()); thumb = (targetAddress & 0x1) != 0; targetAddress = targetAddress & 0xFFFFFFFE; break; default: throw new RuntimeException("Unexpected Operand type: " - + target.getType()); + + i.target.getType()); } //if we're supposed to link, then write the previous address into the link register - if (link) { + if (i.link) { regs.set(ARM_Registers.LR, previousAddress - 4); ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.CALL); } else { ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.DIRECT_BRANCH); } - //jump to the new address regs.set(ARM_Registers.PC, targetAddress); regs.setThumbMode(thumb); } + + public Condition getCondition() { + return i.condition; + } 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(); + if (i.target.getType() == OperandWrapper.Type.PcRelative) { + return pc + i.target.getOffset(); } else { //otherwise we can't predict it return -1; @@ -1156,34 +1183,40 @@ } /** Multiply two integers into a register, possibly adding the value of a third register on the way. */ - private final class IntMultiply extends ARM_Instructions.IntMultiply implements + private final class IntMultiply implements ARM_Instruction { + + private final ARM_Instructions.IntMultiply i; - protected IntMultiply(int instr) { - super(instr); + protected IntMultiply(ARM_Instructions.IntMultiply instr) { + i = instr; } public void execute() { //get the two operands //we don't need to consider that any operand might be the PC, because the ARM //Ref. manual specifies the usage of the PC has undefined results in this operation - int operand1 = regs.get(Rm); - int operand2 = regs.get(Rs); + int operand1 = regs.get(i.Rm); + int operand2 = regs.get(i.Rs); //calculate the result int result = operand1 * operand2; - if (accumulate) { - result += regs.get(Rn); + if (i.accumulate) { + result += regs.get(i.Rn); } //and finally, update the register map - regs.set(Rd, result); + regs.set(i.Rd, result); - if (updateConditionCodes) { + if (i.updateConditionCodes) { regs.setFlags(result < 0, result == 0); } } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { return pc + 4; @@ -1191,11 +1224,13 @@ } /** Multiply two longs into a register, possibly adding the value of a third register on the way. */ - private final class LongMultiply extends ARM_Instructions.LongMultiply implements + private final class LongMultiply implements ARM_Instruction { + + private final ARM_Instructions.LongMultiply i; - protected LongMultiply(int instr) { - super(instr); + protected LongMultiply(ARM_Instructions.LongMultiply instr) { + i = instr; } public void execute() { @@ -1204,11 +1239,11 @@ // We don't need to consider that any operand might be the PC, because the // ARM Ref. manual specifies the usage of the PC has undefined results in this // operation - long operand1 = regs.get(Rm); - long operand2 = regs.get(Rs); + long operand1 = regs.get(i.Rm); + long operand2 = regs.get(i.Rs); //get rid of the signs, if we're supposed to do unsigned multiplication - if (unsigned) { + if (i.unsigned) { operand1 = operand1 & 0xFFFFFFFF; operand2 = operand2 & 0xFFFFFFFF; } @@ -1216,23 +1251,27 @@ // calculate the result long result = operand1 * operand2; - if (accumulate) { + if (i.accumulate) { //treat the register as an unsigned value - long operand = regs.get(getRdLow()); + long operand = regs.get(i.getRdLow()); operand &= 0xFFFFFFFF; result += operand; - result += regs.get(getRdHigh()) << 32; + result += regs.get(i.getRdHigh()) << 32; } // and finally, update the register map - regs.set(getRdLow(), (int) result); - regs.set(getRdHigh(), (int) (result >>> 32)); + regs.set(i.getRdLow(), (int) result); + regs.set(i.getRdHigh(), (int) (result >>> 32)); - if (updateConditionCodes) { + if (i.updateConditionCodes) { regs.setFlags(result < 0, result == 0); } } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { return pc + 4; @@ -1240,24 +1279,28 @@ } /** Move the value of the program status register into a register. */ - private final class MoveFromStatusRegister extends - ARM_Instructions.MoveFromStatusRegister implements - ARM_Instruction { + private final class MoveFromStatusRegister implements ARM_Instruction { + + private final ARM_Instructions.MoveFromStatusRegister i; - public MoveFromStatusRegister(int instr) { - super(instr); + public MoveFromStatusRegister(ARM_Instructions.MoveFromStatusRegister instr) { + i = instr; } public void execute() { //do we have to transfer the saved or the current PSR? - if (transferSavedPSR) { - regs.set(Rd, regs.getSPSR()); + if (i.transferSavedPSR) { + regs.set(i.Rd, regs.getSPSR()); } else { - regs.set(Rd, regs.getCPSR()); + regs.set(i.Rd, regs.getCPSR()); } } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { //Rd should never be the PC, so we can safely predict the next instruction @@ -1265,17 +1308,17 @@ } } - private final class MoveToStatusRegister extends - ARM_Instructions.MoveToStatusRegister implements - ARM_Instruction { + private final class MoveToStatusRegister implements ARM_Instruction { + + private final ARM_Instructions.MoveToStatusRegister i; - public MoveToStatusRegister(int instr) { - super(instr); + public MoveToStatusRegister(ARM_Instructions.MoveToStatusRegister instr) { + i = instr; } public void execute() { //this variable is going to receive the new psr, which we will set - int new_psr = ResolvedOperand.resolve(regs, sourceOperand); + int new_psr = ResolvedOperand.resolve(regs, i.sourceOperand); //are we currently in a privileged mode? boolean inPrivilegedMode = (regs.getOperatingMode() != ARM_Registers.OperatingMode.USR); @@ -1284,7 +1327,7 @@ int old_psr; //get the currect value for old_psr - if (transferSavedPSR) { + if (i.transferSavedPSR) { //if the current mode does not have a SPSR, then do nothing if (inPrivilegedMode && regs.getOperatingMode() != ARM_Registers.OperatingMode.SYS) return; @@ -1296,31 +1339,35 @@ } //create a new CPSR value according to what pieces of the CPSR we are actually required to set - if (!transferControl || !inPrivilegedMode) { + if (!i.transferControl || !inPrivilegedMode) { new_psr &= 0xFFFFFF00; new_psr |= (old_psr & 0xFF); } - if (!transferExtension || !inPrivilegedMode) { + if (!i.transferExtension || !inPrivilegedMode) { new_psr &= 0xFFFF00FF; new_psr |= (old_psr & 0xFF00); } - if (!transferStatus || !inPrivilegedMode) { + if (!i.transferStatus || !inPrivilegedMode) { new_psr &= 0xFF00FFFF; new_psr |= (old_psr & 0xFF0000); } - if (!transferFlags) { + if (!i.transferFlags) { new_psr &= 0x00FFFFFF; new_psr |= (old_psr & 0xFF000000); } - if (transferSavedPSR) + if (i.transferSavedPSR) regs.setSPSR(new_psr); else regs.setCPSR(new_psr); } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { return pc+4; @@ -1328,38 +1375,43 @@ } /** Invoke a software interrupt. */ - private final class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt - implements ARM_Instruction { + private final class SoftwareInterrupt implements ARM_Instruction { + + private final ARM_Instructions.SoftwareInterrupt i; - public SoftwareInterrupt(int instr) { - super(instr); + public SoftwareInterrupt(ARM_Instructions.SoftwareInterrupt instr) { + i = instr; } public void execute() { ps.doSysCall(); } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { return -1; } - } /** 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 final class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer - implements ARM_Instruction { + private final class SingleDataTransfer implements ARM_Instruction { + + private final ARM_Instructions.SingleDataTransfer i; - public SingleDataTransfer(int instr) { - super(instr); + public SingleDataTransfer(ARM_Instructions.SingleDataTransfer instr) { + i = instr; } /** Resolves the offset, which is (when post-indexing is not used) to be added to the * base address to create the final address. */ private int resolveOffset() { - int addrOffset = ResolvedOperand.resolve(regs, offset); + int addrOffset = ResolvedOperand.resolve(regs, i.offset); - if (positiveOffset) + if (i.positiveOffset) return addrOffset; else return -1 * addrOffset; @@ -1369,14 +1421,14 @@ private int resolveAddress() { //acquire the base address - int base = regs.get(Rn); + int base = regs.get(i.Rn); //take ARM's PC offset into account - if (Rn == 15) + if (i.Rn == 15) base += 8; //if we a... [truncated message content] |
From: <mic...@us...> - 2007-06-19 12:24:54
|
Revision: 135 http://svn.sourceforge.net/pearcolator/?rev=135&view=rev Author: michael_baer Date: 2007-06-19 05:24:56 -0700 (Tue, 19 Jun 2007) Log Message: ----------- Added a Null-Object for undefined instructions, instead of returning null from the decoder. 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/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-19 09:10:03 UTC (rev 134) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-19 12:24:56 UTC (rev 135) @@ -17,6 +17,7 @@ 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.ARM_InstructionVisitor; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.UndefinedInstruction; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; @@ -438,5 +439,9 @@ setResult(String.format("MSR%s %s, %s", cond(instr), fields, operand(instr.getSource()))); } + + public void visit(UndefinedInstruction instr) { + setResult("--- (Undefined " + (instr.isThumb ? "Thumb" : "ARM") + " instruction, code 0x" + Integer.toHexString(instr.binaryInstruction) + ")"); + } } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-19 09:10:03 UTC (rev 134) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-19 12:24:56 UTC (rev 135) @@ -582,7 +582,7 @@ } public Instruction createUndefinedInstruction(int instr) { - return null; + return new UndefinedInstruction(instr); } public Instruction createBlockDataTransfer(short instr) { @@ -638,7 +638,7 @@ } public Instruction createUndefinedInstruction(short instr) { - return null; + return new UndefinedInstruction(instr); } public Instruction createIntMultiply(short instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-19 09:10:03 UTC (rev 134) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-19 12:24:56 UTC (rev 135) @@ -47,6 +47,11 @@ this.isThumb = false; } + public Instruction(boolean isThumb) { + condition = Condition.AL; + this.isThumb = isThumb; + } + public final int size() { return isThumb ? 2 : 4; } @@ -1674,9 +1679,31 @@ } } + public static class UndefinedInstruction extends Instruction { + + protected final int binaryInstruction; + + public UndefinedInstruction(short instruction) { + super(false); + this.binaryInstruction = instruction; + } + + public UndefinedInstruction(int instruction) { + super(true); + this.binaryInstruction = instruction; + } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } + + } + public interface ARM_InstructionVisitor { void visit(DataProcessing instr); + void visit(UndefinedInstruction instr); void visit(SingleDataTransfer instr); void visit(IntMultiply instr); void visit(LongMultiply instr); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-19 09:10:03 UTC (rev 134) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-19 12:24:56 UTC (rev 135) @@ -1737,16 +1737,27 @@ } public void translate() { - + + + //if we're supposed to link, then write the previous address into the link register + if (i.link) { + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); + } + else { + //we should never be returning from the goto + arm2ir.getCurrentBlock().deleteNormalOut(); + } + + //can we pre-calculate to where we're branching? if (i.offset.getType() == OperandWrapper.Type.Immediate) { //we can directly resolve this branch to a fixed address if (i.link) - arm2ir.appendCall( readPC() + i.getOffset().getImmediate(), lazy, pc + i.size()); + arm2ir.appendCall(readPC() + i.getOffset().getImmediate(), lazy, pc + i.size()); else arm2ir.appendBranch(readPC() + i.getOffset().getImmediate(), lazy, BranchType.DIRECT_BRANCH); } else { - + //the branch target is not known at compile time OPT_Operand offset = ResolvedOperand.resolve(ARM_Translator.this, i.offset); OPT_RegisterOperand dest = arm2ir.getTempInt(0); @@ -1759,15 +1770,6 @@ arm2ir.appendBranch(dest, lazy, BranchType.INDIRECT_BRANCH); } } - - //if we're supposed to link, then write the previous address into the link register - if (i.link) { - arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); - } - else { - //we should never be returning from the goto - arm2ir.getCurrentBlock().deleteNormalOut(); - } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-20 13:25:36
|
Revision: 138 http://svn.sourceforge.net/pearcolator/?rev=138&view=rev Author: michael_baer Date: 2007-06-20 06:25:36 -0700 (Wed, 20 Jun 2007) Log Message: ----------- Thumb interpret and translator pass validating Dhrystone test. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-19 17:34:26 UTC (rev 137) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-20 13:25:36 UTC (rev 138) @@ -473,8 +473,9 @@ else { //add/subtract register or add/subtract immediate opcode = Utils.getBit(instr, 9) ? Opcode.SUB : Opcode.ADD; - if (Utils.getBit(instr, 10)) + if (Utils.getBit(instr, 10)) { operand2 = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 8)); + } else operand2 = OperandWrapper.createRegister((byte)Utils.getBits(instr, 6, 8)); } @@ -746,7 +747,7 @@ Rd = (byte)Utils.getBits(instr, 0, 2); Rn = (byte)Utils.getBits(instr, 3, 5); - if (Utils.getBits(instr, 13, 15) == 0x5) { + if (Utils.getBits(instr, 12, 15) == 0x5) { //load store register offset offset = OperandWrapper.createRegister((byte)Utils.getBits(instr, 6, 8)); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-19 17:34:26 UTC (rev 137) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-20 13:25:36 UTC (rev 138) @@ -480,7 +480,8 @@ if (i.Rn == ARM_Registers.PC) { int value = regs.readPC(); - if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD) + //this is a very special instruction encoding that demands that the PC is read with an ARM32 mask. + if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD && i.operand2.getType() == OperandWrapper.Type.Immediate) value = value & 0xFFFFFFFC; return value; @@ -504,12 +505,18 @@ */ protected final void setAddResult(int lhs, int rhs) { setFlagsForAdd(lhs, rhs); - - if (DBT_Options.profileDuringInterpretation && i.Rd == 15) { - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs + rhs, BranchType.INDIRECT_BRANCH); + int result = lhs + rhs; + + if (i.Rd == ARM_Registers.PC) { + if (regs.getThumbMode()) + result |= 1; + + if (DBT_Options.profileDuringInterpretation) { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); + } } - regs.set(i.Rd, lhs + rhs); + regs.set(i.Rd, result); } /** @@ -520,12 +527,18 @@ */ protected final void setSubResult(int lhs, int rhs) { setFlagsForSub(lhs, rhs); + int result = lhs - rhs; - if (DBT_Options.profileDuringInterpretation && i.Rd == 15) { - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs - rhs, BranchType.INDIRECT_BRANCH); + if (i.Rd == ARM_Registers.PC) { + if (regs.getThumbMode()) + result |= 1; + + if (DBT_Options.profileDuringInterpretation) { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); + } } - regs.set(i.Rd, lhs - rhs); + regs.set(i.Rd, result); } /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-19 17:34:26 UTC (rev 137) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-20 13:25:36 UTC (rev 138) @@ -933,7 +933,7 @@ if (i.Rn == ARM_Registers.PC) { int value = readPC(); - if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD) + if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD && i.operand2.getType() == OperandWrapper.Type.Immediate) value = value & 0xFFFFFFFC; return new OPT_IntConstantOperand( value ); @@ -959,7 +959,7 @@ protected final void setAddResult(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) { if (i.updateConditionCodes) { - if (i.Rd != 15) { + if (i.Rd != ARM_Registers.PC) { setAddFlags(result, lhs, rhs); } else { @@ -968,8 +968,12 @@ } } - if (i.Rd == 15) { + if (i.Rd == ARM_Registers.PC) { + if (inThumb()) { + arm2ir.appendInstruction(Binary.create(INT_OR, result.copyRO(), result.copy(), new OPT_IntConstantOperand(1))); + } + if (i.updateConditionCodes) arm2ir.appendBranch(result, lazy, BranchType.INDIRECT_BRANCH); else @@ -1011,7 +1015,7 @@ protected final void setSubResult(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) { if (i.updateConditionCodes) { - if (i.Rd != 15) { + if (i.Rd != ARM_Registers.PC) { setSubFlags(result, lhs, rhs); } else { @@ -1020,7 +1024,12 @@ } } - if (i.Rd == 15) { + if (i.Rd == ARM_Registers.PC) { + + if (inThumb()) { + arm2ir.appendInstruction(Binary.create(INT_OR, result.copyRO(), result.copy(), new OPT_IntConstantOperand(1))); + } + if (i.updateConditionCodes) arm2ir.appendBranch(result, lazy, BranchType.INDIRECT_BRANCH); else @@ -1640,7 +1649,7 @@ translateWriteback(startAddress.copyRO(), nextAddress.copyRO()); //shall we switch to thumb mode? - OPT_BasicBlock finishInstruction = arm2ir.createBlockAfterCurrentNotInCFG(); + /*OPT_BasicBlock finishInstruction = arm2ir.createBlockAfterCurrentNotInCFG(); OPT_BasicBlock switchToARMBlock = arm2ir.createBlockAfterCurrentNotInCFG(); OPT_BasicBlock switchToThumbBlock = arm2ir.createBlockAfterCurrentNotInCFG(); @@ -1671,6 +1680,8 @@ //according to the APCS, these types of instructions are usually function returns arm2ir.setCurrentBlock(finishInstruction); + arm2ir.appendBranch(regPC, lazy, BranchType.RETURN);*/ + arm2ir.appendBranch(regPC, lazy, BranchType.RETURN); return; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-08-20 21:08:44
|
Revision: 169 http://pearcolator.svn.sourceforge.net/pearcolator/?rev=169&view=rev Author: michael_baer Date: 2007-08-20 14:08:34 -0700 (Mon, 20 Aug 2007) Log Message: ----------- - Introduce option to use optimized flag handling instructions - otherwise resorting to traditional flag evaluation Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Options.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-20 14:12:59 UTC (rev 168) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-20 21:08:34 UTC (rev 169) @@ -198,6 +198,7 @@ /** Called when the ARM flags shall be set by a SUB operation. This sets all ARM flags. */ public abstract void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2); + public abstract void appendReverseSubFlags(ARM_Laziness lazy, OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs); } /** Implements a flag behavior that will immediately evaluate all flag values. */ @@ -209,7 +210,23 @@ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Zero), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), result.copy(), op1.copy(), OPT_ConditionOperand.LOWER(), new OPT_BranchProfileOperand())); appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); - appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); + + if (ARM_Options.useOptimizedFlags) { + appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); + } + else { + //resolve overflow + OPT_RegisterOperand overflow = getFlag(Flag.Overflow); + OPT_RegisterOperand tmp1 = getTempInt(5); + OPT_RegisterOperand tmp2 = getTempInt(6); + OPT_RegisterOperand tmp_bool = gc.temps.makeTempBoolean(); + + appendInstruction(Binary.create(INT_SUB, tmp1.copyRO(), new OPT_IntConstantOperand(Integer.MAX_VALUE), op2.copy())); + appendInstruction(Binary.create(INT_SUB, tmp2.copyRO(), new OPT_IntConstantOperand(Integer.MIN_VALUE), op2.copy())); + appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, tmp_bool.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.GREATER_EQUAL(), new OPT_BranchProfileOperand(), op1.copy(), tmp1.copy(), OPT_ConditionOperand.GREATER(), OPT_BranchProfileOperand.unlikely())); + appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, overflow.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS() , new OPT_BranchProfileOperand(), op1.copy(), tmp2.copy(), OPT_ConditionOperand.LESS(), OPT_BranchProfileOperand.unlikely())); + appendInstruction(Binary.create(INT_OR, overflow.copyRO(), overflow.copy(), tmp_bool.copy())); + } } @Override @@ -223,9 +240,29 @@ @Override public void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) { appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Zero), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); - appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand())); - appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); + appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + if (ARM_Options.useOptimizedFlags) { + appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand())); + appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); + } + else { + //resolve carry + appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.LOWER().flipCode(), new OPT_BranchProfileOperand())); + + //resolve overflow + OPT_RegisterOperand overflow = getFlag(Flag.Overflow); + OPT_RegisterOperand tmp1 = getTempInt(5); + OPT_RegisterOperand tmp2 = getTempInt(6); + OPT_RegisterOperand tmp_bool = gc.temps.makeTempBoolean(); + + appendInstruction(Binary.create(INT_ADD, tmp1.copyRO(), new OPT_IntConstantOperand(Integer.MIN_VALUE), op2.copy())); + appendInstruction(Binary.create(INT_ADD, tmp2.copyRO(), new OPT_IntConstantOperand(Integer.MAX_VALUE), op2.copy())); + + appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, tmp_bool.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.GREATER_EQUAL(), new OPT_BranchProfileOperand(), op1.copy(), tmp1.copy(), OPT_ConditionOperand.LESS(), OPT_BranchProfileOperand.unlikely())); + appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, overflow.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS() , new OPT_BranchProfileOperand(), op1.copy(), tmp2.copy(), OPT_ConditionOperand.GREATER(), OPT_BranchProfileOperand.unlikely())); + appendInstruction(Binary.create(INT_OR, overflow.copyRO(), overflow.copy(), tmp_bool.copy())); + } } @Override @@ -237,6 +274,11 @@ public void onFlagWrite(Flag flag, ARM_Laziness lazy) { //nothing to do here, because the flags are already resolved } + + @Override + public void appendReverseSubFlags(ARM_Laziness lazy, OPT_RegisterOperand result, OPT_Operand op1, OPT_Operand op2) { + appendSubFlags(lazy, result, op2, op1); + } } /** Implements a flag behavior that will use lazy evaluation to only determine a flag value @@ -366,7 +408,13 @@ case LogicalOpAfterSub: case Sub: - appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand())); + + if (ARM_Options.useOptimizedFlags) { + appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand())); + } + else { + appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.LOWER().flipCode(), new OPT_BranchProfileOperand())); + } break; default: @@ -382,12 +430,40 @@ switch (lazy.getOperation()) { case Add: case LogicalOpAfterAdd: - appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); + if (ARM_Options.useOptimizedFlags) { + appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); + } + else { + OPT_RegisterOperand tmp1 = getTempInt(5); + OPT_RegisterOperand tmp2 = getTempInt(6); + OPT_RegisterOperand tmp_bool = gc.temps.makeTempBoolean(); + + appendInstruction(Binary.create(INT_SUB, tmp1.copyRO(), new OPT_IntConstantOperand(Integer.MAX_VALUE), op2.copy())); + appendInstruction(Binary.create(INT_SUB, tmp2.copyRO(), new OPT_IntConstantOperand(Integer.MIN_VALUE), op2.copy())); + appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, tmp_bool.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.GREATER_EQUAL(), new OPT_BranchProfileOperand(), op1.copy(), tmp1.copy(), OPT_ConditionOperand.GREATER(), OPT_BranchProfileOperand.unlikely())); + appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, getFlag(Flag.Overflow), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS() , new OPT_BranchProfileOperand(), op1.copy(), tmp2.copy(), OPT_ConditionOperand.LESS(), OPT_BranchProfileOperand.unlikely())); + appendInstruction(Binary.create(INT_OR, getFlag(Flag.Overflow), getFlag(Flag.Overflow), tmp_bool.copy())); + } break; case Sub: case LogicalOpAfterSub: - appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); + if (ARM_Options.useOptimizedFlags) { + appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); + } + else { + //resolve overflow + OPT_RegisterOperand tmp1 = getTempInt(5); + OPT_RegisterOperand tmp2 = getTempInt(6); + OPT_RegisterOperand tmp_bool = gc.temps.makeTempBoolean(); + + appendInstruction(Binary.create(INT_ADD, tmp1.copyRO(), new OPT_IntConstantOperand(Integer.MIN_VALUE), op2.copy())); + appendInstruction(Binary.create(INT_ADD, tmp2.copyRO(), new OPT_IntConstantOperand(Integer.MAX_VALUE), op2.copy())); + + appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, tmp_bool.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.GREATER_EQUAL(), new OPT_BranchProfileOperand(), op1.copy(), tmp1.copy(), OPT_ConditionOperand.LESS(), OPT_BranchProfileOperand.unlikely())); + appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, flagRegister, op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS() , new OPT_BranchProfileOperand(), op1.copy(), tmp2.copy(), OPT_ConditionOperand.GREATER(), OPT_BranchProfileOperand.unlikely())); + appendInstruction(Binary.create(INT_OR, flagRegister.copyRO(), flagRegister.copy(), tmp_bool.copy())); + } break; default: @@ -416,6 +492,11 @@ public void onFlagWrite(Flag flag, ARM_Laziness lazy) { lazy.setValid(flag, true); } + + @Override + public void appendReverseSubFlags(ARM_Laziness lazy, OPT_RegisterOperand result, OPT_Operand op1, OPT_Operand op2) { + appendSubFlags(lazy, result, op2, op1); + } } @Override @@ -701,6 +782,12 @@ flagBehavior.appendSubFlags(lazy, result, op1, op2); } + + public void appendReverseSubFlags(ARM_Laziness lazy, OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) { + zeroUsed = negativeUsed = carryUsed = overflowUsed = true; + flagBehavior.appendReverseSubFlags(lazy, result, lhs, rhs); + } + public void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) { zeroUsed = negativeUsed = carryUsed = overflowUsed = true; flagBehavior.appendAddFlags(lazy, result, op1, op2); @@ -846,4 +933,5 @@ appendInstruction(BooleanCmp.create(OPT_Operators.BOOLEAN_CMP_INT, target, target, new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand())); } + } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-20 14:12:59 UTC (rev 168) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-20 21:08:34 UTC (rev 169) @@ -24,12 +24,15 @@ /** Set to true to enable a fastpath for the decoding of data processing instructions.. */ public final static boolean DATAPROCESSING_DECODER_FASTPATH = false; + + /** Shall ARM use the optimized BORROW_FROM_SUB() etc. operations? */ + public static boolean useOptimizedFlags = false; /** This variable describes, if the translated program shall be optimized using profiling information. */ public static boolean optimizeTranslationByProfiling = false; /** This variable describes, if the translated program shall be optimized using lazy evaluation.*/ - public static FlagBehaviour flagEvaluation = FlagBehaviour.Lazy; + public static FlagBehaviour flagEvaluation = FlagBehaviour.Immediate; /** Describes the default behaviour for dealing with ARM function calls and indirect jumps. */ public static InliningBehaviour inlining = InliningBehaviour.Default; @@ -47,7 +50,9 @@ inlining = ARM_Options.InliningBehaviour.valueOf(value); } else if (key.equalsIgnoreCase("memory")) { memoryModel = ARM_Options.MemoryModel.valueOf(value); - } + } else if (key.equalsIgnoreCase("optimizedFlags")) { + useOptimizedFlags = Boolean.parseBoolean(value); + } else { throw new Error("Unknown ARM option: " + key); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-20 14:12:59 UTC (rev 168) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-20 21:08:34 UTC (rev 169) @@ -843,22 +843,35 @@ case CC: //return !regs.isCarrySet(); - translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readCarryFlag(lazy), OPT_ConditionOperand.NOT_EQUAL()); + { + OPT_Operand carry = arm2ir.readCarryFlag(lazy); + translateCondition(nextInstruction_InstructionSkipped, profileOperand, carry, OPT_ConditionOperand.NOT_EQUAL()); + } break; case CS: //return regs.isCarrySet(); - translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readCarryFlag(lazy), OPT_ConditionOperand.EQUAL()); + { + OPT_Operand carry = arm2ir.readCarryFlag(lazy); + translateCondition(nextInstruction_InstructionSkipped, profileOperand, carry, OPT_ConditionOperand.EQUAL()); + } break; case EQ: //return regs.isZeroSet(); - translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readZeroFlag(lazy), OPT_ConditionOperand.EQUAL()); + { + OPT_Operand zero = arm2ir.readZeroFlag(lazy); + translateCondition(nextInstruction_InstructionSkipped, profileOperand, zero, OPT_ConditionOperand.EQUAL()); + } break; case GE: //return regs.isNegativeSet() == regs.isOverflowSet(); - translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.EQUAL(), arm2ir.readOverflowFlag(lazy)); + { + OPT_Operand overflow = arm2ir.readOverflowFlag(lazy); + OPT_Operand negative = arm2ir.readNegativeFlag(lazy); + translateCondition(nextInstruction_InstructionSkipped, profileOperand, negative, OPT_ConditionOperand.EQUAL(), overflow); + } break; case GT: @@ -879,17 +892,27 @@ case LT: //return regs.isNegativeSet() != regs.isOverflowSet(); - translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.readOverflowFlag(lazy)); + { + OPT_Operand overflow = arm2ir.readOverflowFlag(lazy); + OPT_Operand negative = arm2ir.readNegativeFlag(lazy); + translateCondition(nextInstruction_InstructionSkipped, profileOperand, negative, OPT_ConditionOperand.NOT_EQUAL(), overflow); + } break; case MI: //return regs.isNegativeSet(); - translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.EQUAL()); + { + OPT_Operand negative = arm2ir.readNegativeFlag(lazy); + translateCondition(nextInstruction_InstructionSkipped, profileOperand, negative, OPT_ConditionOperand.EQUAL()); + } break; case NE: //return !regs.isZeroSet(); - translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readZeroFlag(lazy), OPT_ConditionOperand.NOT_EQUAL()); + { + OPT_Operand zero = arm2ir.readZeroFlag(lazy); + translateCondition(nextInstruction_InstructionSkipped, profileOperand, zero, OPT_ConditionOperand.NOT_EQUAL()); + } break; case NV: @@ -899,17 +922,26 @@ case PL: //return !regs.isNegativeSet(); - translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.NOT_EQUAL()); + { + OPT_Operand negative = arm2ir.readNegativeFlag(lazy); + translateCondition(nextInstruction_InstructionSkipped, profileOperand, negative, OPT_ConditionOperand.NOT_EQUAL()); + } break; case VC: //return !regs.isOverflowSet(); - translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readOverflowFlag(lazy), OPT_ConditionOperand.NOT_EQUAL()); + { + OPT_Operand overflow = arm2ir.readOverflowFlag(lazy); + translateCondition(nextInstruction_InstructionSkipped, profileOperand, overflow, OPT_ConditionOperand.NOT_EQUAL()); + } break; case VS: //return regs.isOverflowSet(); - translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readOverflowFlag(lazy), OPT_ConditionOperand.EQUAL()); + { + OPT_Operand overflow = arm2ir.readOverflowFlag(lazy); + translateCondition(nextInstruction_InstructionSkipped, profileOperand, overflow, OPT_ConditionOperand.EQUAL()); + } break; default: @@ -997,8 +1029,8 @@ private void translateCondition_GT(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) { //return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); + OPT_Operand overflow = arm2ir.readOverflowFlag(lazy); OPT_Operand negative = arm2ir.readNegativeFlag(lazy); - OPT_Operand overflow = arm2ir.readOverflowFlag(lazy); OPT_Operand zero = arm2ir.readZeroFlag(lazy); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); @@ -1010,8 +1042,8 @@ private void translateCondition_LE(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) { //return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); + OPT_Operand overflow = arm2ir.readOverflowFlag(lazy); OPT_Operand negative = arm2ir.readNegativeFlag(lazy); - OPT_Operand overflow = arm2ir.readOverflowFlag(lazy); OPT_Operand zero = arm2ir.readZeroFlag(lazy); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); @@ -1109,11 +1141,14 @@ } /** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/ - protected final void setSubResult(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setSubResult(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs, boolean wasReverseSub) { if (i.updateConditionCodes) { if (i.Rd != ARM_Registers.PC) { - setSubFlags(result, lhs, rhs); + if (wasReverseSub) + setReverseSubFlags(result, lhs, rhs); + else + setSubFlags(result, lhs, rhs); } else { OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); @@ -1136,7 +1171,12 @@ arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(i.Rd), result.copy()) ); } } + + private void setReverseSubFlags(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) { + arm2ir.appendReverseSubFlags(lazy, result, lhs, rhs); + } + /** * Sets the processor flags according to the result of a sub operation. * @param result @@ -1147,7 +1187,6 @@ * The sub's right-hand-side operator. */ protected final void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { - arm2ir.appendSubFlags(lazy, result, lhs, rhs); } @@ -1294,7 +1333,7 @@ arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2)); - setSubResult(result, operand1, operand2); + setSubResult(result, operand1, operand2, false); } } @@ -1313,7 +1352,7 @@ arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand2, operand1)); - setSubResult(result, operand2, operand1); + setSubResult(result, operand1, operand2, true); } } @@ -1385,7 +1424,7 @@ //Finally, subtract the second operands from the result arm2ir.setCurrentBlock(subWithoutCarry); arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2.copy())); - setSubResult(result, operand1, operand2); + setSubResult(result, operand1, operand2, false); } } @@ -2188,8 +2227,9 @@ return base; //add the offset to the base register + OPT_Operand offset = resolveOffset(); OPT_RegisterOperand tmp = arm2ir.getTempInt(0); - arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, base, resolveOffset())); + arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, base, offset)); if (i.isThumb && i.isLoad && i.Rn == ARM_Registers.PC) { //with thumb, bit 1 of the address is always ignored - address = address & 0xFFFFFFFC; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |