From: <mic...@us...> - 2007-04-17 18:11:38
|
Revision: 60 http://svn.sourceforge.net/pearcolator/?rev=60&view=rev Author: michael_baer Date: 2007-04-17 11:11:39 -0700 (Tue, 17 Apr 2007) Log Message: ----------- Temporarily saving progress made while implementing an initial ARM interpreter. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java src/org/binarytranslator/generic/decoder/DisassembledInstruction.java Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/generic/decoder/Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-17 18:11:39 UTC (rev 60) @@ -164,7 +164,10 @@ op.getShiftAmount()); case PcRelative: - return String.format("#%x", op.getOffset() + address + 8); + if (address != -1) + return String.format("#%x", op.getOffset() + address + 8); + else + return String.format("#<%x + pc>", op.getOffset()); case Register: return "r" + op.getRegister(); @@ -312,9 +315,11 @@ public void visit(Branch instr) { String mnemonic = instr.link() ? "BL" : "B"; - setResult(String.format("%s%s #%x", mnemonic, cond(instr), instr - .getOffset() - + address)); + + if (address != -1) + setResult(String.format("%s%s #%x", mnemonic, cond(instr), instr.getOffset() + address + 8)); + else + setResult(String.format("%s%s #<%x + pc>", mnemonic, cond(instr), instr.getOffset())); } public void visit(BranchExchange instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-17 18:11:39 UTC (rev 60) @@ -51,7 +51,7 @@ * An object representation of the decoded instruction. */ static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { - if (getBit(instruction, 27)) { + if (Utils.getBit(instruction, 27)) { return decode_1xx(instruction, factory); } else { @@ -59,29 +59,14 @@ } } - /** - * Checks if a bit is set within a word. - * @param word - * The word that is being examined. - * @param bit - * The number of the bit that is to be checked, starting from zero. - * @return - * True, if the given bit is set within the word, false otherwise. - */ - private static final boolean getBit(int word, int bit) { - if (DBT.VerifyAssertions) - DBT._assert(bit >= 0 && bit <= 31); - return (word & (1 << bit)) != 0; - } - private static <T> T decode_0xx(int instr, ARM_InstructionFactory<T> factory) { if ((instr & 0xF0000000) == 0xF0000000) { return factory.createUndefinedInstruction(instr); } - if (getBit(instr, 26)) { + if (Utils.getBit(instr, 26)) { //opcode: 01 - if (getBit(instr, 25) && getBit(instr, 4)) + if (Utils.getBit(instr, 25) && Utils.getBit(instr, 4)) return factory.createUndefinedInstruction(instr); else return factory.createSingleDataTransfer(instr); @@ -93,7 +78,7 @@ } private static <T> T decode_1xx(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 26)) { + if (Utils.getBit(instr, 26)) { //opcode: 11 return decode_11x( instr, factory); } @@ -104,14 +89,14 @@ } private static <T> T decode_00x(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 25)) + if (Utils.getBit(instr, 25)) return decode_001(instr, factory); else return decode_000(instr, factory); } private static <T> T decode_10x(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 25)) { + if (Utils.getBit(instr, 25)) { //opcode: 101 if ((instr & 0xF0000000) == 0xF0000000) return factory.createBranchExchange(instr); @@ -129,12 +114,12 @@ private static <T> T decode_000(int instr, ARM_InstructionFactory<T> factory) { //opcode: 000 - if (getBit(instr, 24) && !getBit(instr, 23) && !getBit(instr, 20)) { + if (Utils.getBit(instr, 24) && !Utils.getBit(instr, 23) && !Utils.getBit(instr, 20)) { //opcode: 00010xx0 - those are the new instructions, which the ARM ref. manual calls "misc. instructions" return decode_00010xx0(instr, factory); } else { - if (getBit(instr, 4) == false || getBit(instr, 7) == false) + if (Utils.getBit(instr, 4) == false || Utils.getBit(instr, 7) == false) return factory.createDataProcessing(instr); return decode_multiplies_extra_load_stores(instr, factory); @@ -143,11 +128,11 @@ private static <T> T decode_001(int instr, ARM_InstructionFactory<T> factory) { //opcode: 001 - if (!getBit(instr, 24) || getBit(instr, 23) || getBit(instr, 20)) { + if (!Utils.getBit(instr, 24) || Utils.getBit(instr, 23) || Utils.getBit(instr, 20)) { return factory.createDataProcessing(instr); } - if (getBit(instr, 21)) + if (Utils.getBit(instr, 21)) return factory.createMoveToStatusRegister(instr); else return factory.createUndefinedInstruction(instr); @@ -155,13 +140,13 @@ private static <T> T decode_11x(int instr, ARM_InstructionFactory<T> factory) { - if (getBit(instr, 25) == false) { + if (Utils.getBit(instr, 25) == false) { //opcode: 110 return factory.createCoprocessorDataTransfer(instr); } //opcode: 111 - if (getBit(instr, 24)) { + if (Utils.getBit(instr, 24)) { //opcode: 1111 if ((instr & 0xF0000000) == 0xF0000000) return factory.createUndefinedInstruction(instr); @@ -170,7 +155,7 @@ } else { //opcode: 1110 - if (getBit(instr, 4)) { + if (Utils.getBit(instr, 4)) { return factory.createCoprocessorDataTransfer(instr); } else { @@ -185,7 +170,7 @@ */ private static <T> T decode_00010xx0(int instr, ARM_InstructionFactory<T> factory) { // - if (getBit(instr, 6) || getBit(instr, 7)) { + if (Utils.getBit(instr, 6) || Utils.getBit(instr, 7)) { //enhanced DSP multiplications, DSP add/subtracts and software breakpoints //we might want to support these in the future, so when in debug mode, catch if any program actually uses them if (DBT.VerifyAssertions) DBT._assert(false); @@ -193,14 +178,14 @@ } else { //bit 6 and 7 are clear - if (getBit(instr, 4)) { - if (getBit(instr, 22)) + if (Utils.getBit(instr, 4)) { + if (Utils.getBit(instr, 22)) return factory.createCountLeadingZeros(instr); else return factory.createBranchExchange(instr); } else { - if (getBit(instr, 21)) + if (Utils.getBit(instr, 21)) return factory.createMoveToStatusRegister(instr); else return factory.createMoveFromStatusRegister(instr); @@ -215,25 +200,25 @@ */ private static <T> T decode_multiplies_extra_load_stores(int instr, ARM_InstructionFactory<T> factory) { //Here, we already know that bits 4 and 7 are set, while bit 25-27 are clear - if (getBit(instr, 6)) { + if (Utils.getBit(instr, 6)) { //load/store signed half-word or two words - if (getBit(instr, 20)) + if (Utils.getBit(instr, 20)) return factory.createSingleDataTransfer(instr); else return factory.createUndefinedInstruction(instr); //two words immediate offset } else { - if (getBit(instr, 5)) { + if (Utils.getBit(instr, 5)) { //load/store half-word return factory.createSingleDataTransfer(instr); } else { //Multiply, multiply long or Swap - if (getBit(instr, 24)) { + if (Utils.getBit(instr, 24)) { return factory.createSwap(instr); } else { - if (getBit(instr, 23)) + if (Utils.getBit(instr, 23)) return factory.createLongMultiply(instr); else return factory.createIntMultiply(instr); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-17 18:11:39 UTC (rev 60) @@ -17,52 +17,6 @@ */ public class ARM_Instructions { - /** - * Checks if a bit is set within a word. - * @param word - * The word that is being examined. - * @param bit - * The number of the bit that is to be checked, starting from zero. - * @return - * True, if the given bit is set within the word, false otherwise. - */ - private static final boolean getBit(int word, int bit) { - if (DBT.VerifyAssertions) - DBT._assert(bit >= 0 && bit <= 31); - return (word & (1 << bit)) != 0; - } - - /** - * Extracts a subsequence of bits from a word. - * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. - * @param word - * The word that is to be examined. - * @param from - * The first bit (starting from 0) that is to be extracted. - * @param to - * The last bit (starting from 0) that is to be extracted from the word. - * @return - * A zero-based version of the bit sequence. - */ - private static final int getBits(int word, int from, int to) { - if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to <= 31); - return (word & ((1 << (to + 1)) - 1)) >> from; - } - - /** - * Sign extends a given value. - * @param value - * The value to sign extends. - * @param bitsUsed - * The number bits used within this values. - * @return - * A sign extended value. - */ - public static int signExtend(int value, int bitsUsed) { - return (value << (32 - bitsUsed)) >> (32 - bitsUsed); - } - /** A base class for all (conditional) ARM instructions. */ public abstract static class Instruction { @@ -74,7 +28,7 @@ protected final Condition condition; private Instruction(int instr) { - condition = Condition.values()[(byte) getBits(instr, 28, 31)]; + condition = Condition.values()[(byte) Utils.getBits(instr, 28, 31)]; } /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ @@ -103,8 +57,8 @@ public TwoRegistersTemplate(int instr) { super(instr); - Rd = (byte) getBits(instr, 12, 15); - Rn = (byte) getBits(instr, 16, 19); + Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); } /** Returns the number of the operation's destination register, starting from 0.*/ @@ -128,7 +82,7 @@ public ThreeRegistersTemplate(int instr) { super(instr); - Rm = (byte) getBits(instr, 0, 3); + Rm = (byte) Utils.getBits(instr, 0, 3); } /** Returns the number of the second operand register, starting from 0.*/ @@ -153,9 +107,9 @@ protected MultiplyTemplate(int instr) { super(instr); - updateConditionCodes = getBit(instr, 20); - accumulate = getBit(instr, 21); - Rs = (byte) getBits(instr, 8, 11); + updateConditionCodes = Utils.getBit(instr, 20); + accumulate = Utils.getBit(instr, 21); + Rs = (byte) Utils.getBits(instr, 8, 11); } /** Returns true, if the condition codes shall be updated by the result of this operation. */ @@ -189,9 +143,9 @@ public CoprocessorTemplate(int instr) { super(instr); - cpNum = (byte) getBits(instr, 8, 11); - Rd = (byte) getBits(instr, 12, 15); - Rn = (byte) getBits(instr, 16, 19); + cpNum = (byte) Utils.getBits(instr, 8, 11); + Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); } /** Returns the coprocessor that shall process this instruction */ @@ -238,32 +192,35 @@ /** Creates an operand wrapper, that represents a register shifted by an immediate or a register, depending on the instruction. */ public static OperandWrapper decodeShiftedRegister(int instr) { - ShiftType shift = ShiftType.values()[getBits(instr, 5, 6)]; + ShiftType shift = ShiftType.values()[Utils.getBits(instr, 5, 6)]; byte shiftedRegister = (byte) (instr & 0xF); - if (getBit(instr, 4)) { + if (Utils.getBit(instr, 4)) { //shift by a register - byte shiftingRegister = (byte)getBits(instr, 8, 11); + byte shiftingRegister = (byte)Utils.getBits(instr, 8, 11); return new RegisterShiftRegisterOperand(shiftedRegister, shift, shiftingRegister); } else { //shift by an immediate - byte immediate = (byte)getBits(instr, 7, 11); + byte immediate = (byte)Utils.getBits(instr, 7, 11); if (immediate == 0) { - //if we are shifting by zero, we might forget about the shift + + if (shift == ShiftType.LSL) { + //If we are shifting by zero with LSL, then this is supposed to denote a register operand + return new RegisterOperand(shiftedRegister); + } + if (shift == ShiftType.ROR) { //However, if the shift type was RotateRight, then ARM meant do a RotateRightExtend by 1 return new RegisterShiftImmediateOperand(shiftedRegister, shift, (byte)1); } - else { - //Otherwise, really forget about the shifting - return new RegisterOperand(shiftedRegister); - } + + //in all other cases, an immediate of zero denotes a shift by 32 + immediate = 32; } - else { - return new RegisterShiftImmediateOperand(shiftedRegister, shift, immediate); - } + + return new RegisterShiftImmediateOperand(shiftedRegister, shift, immediate); } } @@ -305,15 +262,20 @@ /** @see #getImmediate() */ protected final int immediate; - + protected ImmediateOperand(int immediate) { this.immediate = immediate; } - + @Override public int getImmediate() { return immediate; } + + @Override + public byte getShiftAmount() { + return 0; + } @Override public Type getType() { @@ -452,11 +414,11 @@ public DataProcessing(int instr) { super(instr); - updateConditionCodes = getBit(instr, 20); - opcode = Opcode.values()[(byte) getBits(instr, 21, 24)]; + updateConditionCodes = Utils.getBit(instr, 20); + opcode = Opcode.values()[(byte) Utils.getBits(instr, 21, 24)]; - if (getBit(instr, 25)) - operand2 = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); + if (Utils.getBit(instr, 25)) + operand2 = OperandWrapper.createImmediate(Integer.rotateRight(instr & 0xFF, Utils.getBits(instr, 8, 11) << 2)); else operand2 = OperandWrapper.decodeShiftedRegister(instr); } @@ -519,40 +481,40 @@ public SingleDataTransfer(int instr) { super(instr); - preIndexing = getBit(instr, 24); - positiveOffset = getBit(instr, 23); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); + preIndexing = Utils.getBit(instr, 24); + positiveOffset = Utils.getBit(instr, 23); + writeBack = Utils.getBit(instr, 21); + isLoad = Utils.getBit(instr, 20); - if (getBit(instr, 26)) { + if (Utils.getBit(instr, 26)) { //this is an unsigned byte or word transfer signExtend = false; forceUserMode = !preIndexing && writeBack; - if (getBit(instr, 22)) + if (Utils.getBit(instr, 22)) size = TransferSize.Byte; else size = TransferSize.Word; - if (getBit(instr, 25)) + if (Utils.getBit(instr, 25)) offset = OperandWrapper.createImmediate(instr & 0xFF); else offset = OperandWrapper.decodeShiftedRegister(instr); } else { //this is a byte or half-word transfer - if (getBit(instr, 5)) + if (Utils.getBit(instr, 5)) size = TransferSize.HalfWord; else size = TransferSize.Byte; - signExtend = getBit(instr, 6); + signExtend = Utils.getBit(instr, 6); forceUserMode = false; - if (getBit(instr, 22)) { + if (Utils.getBit(instr, 22)) { //immediate offset - offset = OperandWrapper.createImmediate((getBits(instr, 8, 11) << 4) | (instr & 0xF)); + offset = OperandWrapper.createImmediate((Utils.getBits(instr, 8, 11) << 4) | (instr & 0xF)); } else { //register offset @@ -616,7 +578,8 @@ protected IntMultiply(int instr) { super(instr); - if (DBT.VerifyAssertions) DBT._assert(accumulate || Rn == 0); + //check for instruction combinations that show undefined behaviour on ARM + if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } @Override @@ -634,7 +597,10 @@ public LongMultiply(int instr) { super(instr); - unsigned = getBit(instr, 22); + unsigned = Utils.getBit(instr, 22); + + //check for instruction combinations that show undefined behaviour on ARM + if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ @@ -666,7 +632,7 @@ public Swap(int instr) { super(instr); - swapByte = getBit(instr, 22); + swapByte = Utils.getBit(instr, 22); } /** Returns true, if a byte shall be swapped or false, if an int (32 bit) shall be swapped. */ @@ -707,12 +673,12 @@ public BlockDataTransfer(int instr) { super(instr); - postIndexing = getBit(instr, 24); - incrementBase = getBit(instr, 23); - forceUser = getBit(instr, 22); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); - baseRegister = (byte) getBits(instr, 16, 19); + postIndexing = Utils.getBit(instr, 24); + incrementBase = Utils.getBit(instr, 23); + forceUser = Utils.getBit(instr, 22); + writeBack = Utils.getBit(instr, 21); + isLoad = Utils.getBit(instr, 20); + baseRegister = (byte) Utils.getBits(instr, 16, 19); registerList = instr; } @@ -721,7 +687,7 @@ if (DBT.VerifyAssertions) DBT._assert(r >= 0 && r < 16); - return getBit(registerList, r); + return Utils.getBit(registerList, r); } /** True if the base register shall be changed after each single transfer, otherwise changed it before each transfer. */ @@ -793,7 +759,7 @@ public Branch(int instr) { super(instr); - link = getBit(instr, 24); + link = Utils.getBit(instr, 24); offset = instr & 0xFFF; } @@ -823,23 +789,23 @@ protected final boolean link; public BranchExchange(int instr) { - super(getBit(instr, 27) ? 0xE0000000 : instr); + super(Utils.getBit(instr, 27) ? 0xE0000000 : instr); - if (getBit(instr, 27)) { + if (Utils.getBit(instr, 27)) { //this is the immediate version of a BLX link = true; //sign extend jump target - int jumpTarget = signExtend(instr & 0xFFF, 24) << 2; + int jumpTarget = Utils.signExtend(instr & 0xFFF, 24) << 2; //are we addressing a half-byte? - if (getBit(instr, 24)) + if (Utils.getBit(instr, 24)) jumpTarget += 2; target = OperandWrapper.createPcRelative(jumpTarget); } else { - link = getBit(instr, 5); + link = Utils.getBit(instr, 5); target = OperandWrapper.createRegister((byte) (instr & 0xF)); } } @@ -881,16 +847,16 @@ public CoprocessorDataTransfer(int instr) { super(instr); - preIndexing = getBit(instr, 24); - largeTransfer = getBit(instr, 22); - writeBack = getBit(instr, 21); - isLoad = getBit(instr, 20); + preIndexing = Utils.getBit(instr, 24); + largeTransfer = Utils.getBit(instr, 22); + writeBack = Utils.getBit(instr, 21); + isLoad = Utils.getBit(instr, 20); if (!writeBack && !preIndexing) { offset = instr & 0xFF; } else { - if (getBit(instr, 23)) + if (Utils.getBit(instr, 23)) offset = (instr & 0xFF) << 2; else offset = - ((instr & 0xFF) << 2); @@ -960,8 +926,8 @@ public CoprocessorDataProcessing(int instr) { super(instr); - opcode = (byte) getBits(instr, 20, 23); - cpInfo = (byte) getBits(instr, 5, 7); + opcode = (byte) Utils.getBits(instr, 20, 23); + cpInfo = (byte) Utils.getBits(instr, 5, 7); cpRm = (byte) (instr & 0xF); } @@ -1014,10 +980,10 @@ public CoprocessorRegisterTransfer(int instr) { super(instr); - opcode = (byte) getBits(instr, 21, 23); - cpInfo = (byte) getBits(instr, 5, 7); + opcode = (byte) Utils.getBits(instr, 21, 23); + cpInfo = (byte) Utils.getBits(instr, 5, 7); cpRm = (byte) (instr & 0xF); - isLoad = getBit(instr, 20); + isLoad = Utils.getBit(instr, 20); } /** Returns true if this operation is a load from a coprocessor or false if it is a store to coprocessor. */ @@ -1068,8 +1034,8 @@ public MoveFromStatusRegister(int instr) { super(instr); - Rd = (byte) getBits(instr, 12, 15); - transferSavedPSR = getBit(instr, 22); + Rd = (byte) Utils.getBits(instr, 12, 15); + transferSavedPSR = Utils.getBit(instr, 22); } /** Returns the number of the destination register. */ @@ -1112,15 +1078,15 @@ public MoveToStatusRegister(int instr) { super(instr); - transferControl = getBit(instr, 16); - transferExtension = getBit(instr, 17); - transferStatus = getBit(instr, 18); - transferFlags = getBit(instr, 19); + transferControl = Utils.getBit(instr, 16); + transferExtension = Utils.getBit(instr, 17); + transferStatus = Utils.getBit(instr, 18); + transferFlags = Utils.getBit(instr, 19); - transferSavedPSR = getBit(instr, 22); + transferSavedPSR = Utils.getBit(instr, 22); - if (getBit(instr, 25)) - sourceOperand = OperandWrapper.createImmediate((instr & 0xFF) << getBits(instr, 8, 11)); + if (Utils.getBit(instr, 25)) + sourceOperand = OperandWrapper.createImmediate((instr & 0xFF) << Utils.getBits(instr, 8, 11)); else sourceOperand = OperandWrapper.decodeShiftedRegister(instr); } @@ -1174,7 +1140,7 @@ super(instr); Rm = (byte) (instr & 0xF); - Rd = (byte) getBits(instr, 12, 15); + Rd = (byte) Utils.getBits(instr, 12, 15); } /** Returns the source register for this operation. */ Added: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-17 18:11:39 UTC (rev 60) @@ -0,0 +1,821 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.decoder.Interpreter.Instruction; + +public class ARM_Interpreter { + + protected final ARM_ProcessSpace ps; + + protected final ARM_Registers regs; + + public ARM_Interpreter(ARM_ProcessSpace ps) { + this.ps = ps; + this.regs = ps.registers; + } + + private final class ConditionalDecorator implements Interpreter.Instruction { + + protected final Interpreter.Instruction conditionalInstruction; + + protected ConditionalDecorator(Interpreter.Instruction i) { + conditionalInstruction = i; + } + + public void execute() { + conditionalInstruction.execute(); + } + + public int getSuccessor(int pc) { + return -1; + } + } + + private abstract class DataProcessing extends ARM_Instructions.DataProcessing + implements Interpreter.Instruction { + + protected boolean shifterCarryOut; + + protected DataProcessing(int instr) { + super(instr); + } + + protected final int resolveShift(OperandWrapper operand) { + + int value = regs.get(operand.getRegister()); + byte shiftAmount; + + if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) + shiftAmount = operand.getShiftAmount(); + else { + shiftAmount = (byte) (regs.get(operand.getShiftingRegister()) & 0xF); + } + + switch (operand.getShiftType()) { + case ASR: + + if (shiftAmount > 32) + shiftAmount = 32; + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >>> shiftAmount; + } + + case LSL: + + if (shiftAmount > 32) + shiftAmount = 32; + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, 32 - shiftAmount); + return value << shiftAmount; + } + + case LSR: + + if (shiftAmount > 32) + shiftAmount = 32; + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, shiftAmount - 1); + return value >> shiftAmount; + } + + case ROR: + + if (shiftAmount == 0) { + shifterCarryOut = regs.isCarrySet(); + return value; + } else { + shifterCarryOut = Utils.getBit(value, shiftAmount & 0x1F); + return Integer.rotateRight(value, shiftAmount); + } + + case RRE: + shifterCarryOut = (value & 0x1) != 0; + + if (regs.isCarrySet()) + return (value >> 1) | 0x80000000; + else + return value >> 1; + + default: + throw new RuntimeException("Unexpected shift type: " + + operand.getShiftType()); + } + } + + protected int resolveOperand2() { + int value; + + switch (operand2.getType()) { + case Immediate: + value = operand2.getImmediate(); + + if (operand2.getShiftAmount() == 0) + shifterCarryOut = regs.isCarrySet(); + else + shifterCarryOut = (value & 0x80000000) != 0; + + case Register: + shifterCarryOut = regs.isCarrySet(); + return regs.get(operand2.getRegister()); + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + return resolveShift(operand2); + + case PcRelative: + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand2.getType()); + } + } + + + public abstract void execute(); + + protected final void setFlagsForResult(int result) { + + if (updateConditionCodes) { + if (Rd != 15) { + regs.setFlags(result < 0, result == 0, shifterCarryOut); + } else { + regs.restoreSPSR2CPSR(); + } + } + } + + protected final void setFlagsForAdd(int lhs, int rhs) { + + if (updateConditionCodes) { + if (Rd != 15) { + int result = lhs + rhs; + boolean carry = Utils.unsignedAddOverflow(lhs, rhs); + boolean overflow = Utils.signedAddOverflow(lhs, rhs); + regs.setFlags(result < 0, result == 0, carry, overflow); + } + else { + regs.restoreSPSR2CPSR(); + } + } + } + + public int getSuccessor(int pc) { + if (Rd == 15) + return pc + 4; + else + return -1; + } + } + + private final class DataProcessing_And extends DataProcessing { + + protected DataProcessing_And(int instr) { + super(instr); + } + + + @Override + public void execute() { + int result = regs.get(Rn) & resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private final class DataProcessing_Eor extends DataProcessing { + + protected DataProcessing_Eor(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = regs.get(Rn) ^ resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Add extends DataProcessing { + + public DataProcessing_Add(int instr) { + super(instr); + } + + protected int resolveOperand1() { + return regs.get(Rn); + } + + public void execute() { + int operand1 = resolveOperand1(); + int operand2 = resolveOperand2(); + int result = operand1 + operand2; + + regs.set(Rd, result); + setFlagsForAdd(operand1, operand2); + } + } + + private final class DataProcessing_Sub extends DataProcessing_Add { + + public DataProcessing_Sub(int instr) { + super(instr); + } + + @Override + protected int resolveOperand2() { + return -super.resolveOperand2(); + } + } + + private final class DataProcessing_Rsb extends DataProcessing_Add { + + protected DataProcessing_Rsb(int instr) { + super(instr); + } + + @Override + protected int resolveOperand1() { + return -super.resolveOperand1(); + } + } + + private class DataProcessing_Adc extends DataProcessing_Add { + + protected int cachedOperand1; + protected int cachedOperand2; + + protected DataProcessing_Adc(int instr) { + super(instr); + } + + @Override + protected int resolveOperand1() { + return cachedOperand1; + } + + @Override + protected int resolveOperand2() { + return cachedOperand2; + } + + @Override + public void execute() { + cachedOperand1 = super.resolveOperand1(); + cachedOperand2 = super.resolveOperand2(); + + if (regs.isCarrySet()) { + if (cachedOperand1 != Integer.MAX_VALUE) { + cachedOperand1++; + } else if (cachedOperand2 != Integer.MAX_VALUE) { + cachedOperand2++; + } else { + regs.setFlags(cachedOperand1 > 0, cachedOperand1 != 0, true, true); + return; + } + } + + super.execute(); + } + } + + private class DataProcessing_Sbc extends DataProcessing_Adc { + + protected DataProcessing_Sbc(int instr) { + super(instr); + } + + @Override + protected int resolveOperand2() { + return -cachedOperand2; + } + } + + private class DataProcessing_Rsc extends DataProcessing_Adc { + + protected DataProcessing_Rsc(int instr) { + super(instr); + } + + @Override + protected int resolveOperand1() { + return -cachedOperand1; + } + } + + private class DataProcessing_Tst extends DataProcessing { + + protected DataProcessing_Tst(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForResult(regs.get(Rn) & resolveOperand2()); + } + } + + private class DataProcessing_Teq extends DataProcessing { + + protected DataProcessing_Teq(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForResult(regs.get(Rn) ^ resolveOperand2()); + } + } + + private class DataProcessing_Cmp extends DataProcessing { + + protected DataProcessing_Cmp(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForAdd(regs.get(Rn), -resolveOperand2()); + } + } + + private class DataProcessing_Cmn extends DataProcessing { + + protected DataProcessing_Cmn(int instr) { + super(instr); + } + + @Override + public void execute() { + setFlagsForAdd(regs.get(Rn), resolveOperand2()); + } + } + + private class DataProcessing_Orr extends DataProcessing { + + protected DataProcessing_Orr(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = regs.get(Rn) | resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Mov extends DataProcessing { + + protected DataProcessing_Mov(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Bic extends DataProcessing { + + protected DataProcessing_Bic(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = regs.get(Rn) & (~resolveOperand2()); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class DataProcessing_Mvn extends DataProcessing { + + protected DataProcessing_Mvn(int instr) { + super(instr); + } + + @Override + public void execute() { + int result = ~resolveOperand2(); + regs.set(Rd, result); + setFlagsForResult(result); + } + } + + private class Swap extends ARM_Instructions.Swap implements Interpreter.Instruction { + + public Swap(int instr) { + super(instr); + } + + public void execute() { + int memAddr = regs.get(Rn); + + //swap exchanges the value of a memory address with the value in a register + int tmp = ps.memory.load32(memAddr); + ps.memory.store16(memAddr, regs.get(Rm)); + + //according to the ARM architecture reference, the value loaded from a memory address is rotated + //according to the number of ones in the first two bits of the address + regs.set(Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class BlockDataTransfer extends ARM_Instructions.BlockDataTransfer implements Interpreter.Instruction { + + public BlockDataTransfer(int instr) { + super(instr); + } + + public void execute() { + //start address ignores the last two bits + int startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + + //build a map of registers that are to be transfered + int registerCount = 0; + boolean transferPC = false; + int[] registersToTransfer = new int[16]; + + for (int i = 0; i < 14; i++) + if (transferRegister(i)) { + registersToTransfer[registerCount++] = i; + } + + //also remember if we're supposed to transfer the pc, but don't include it in the register list + transferPC = transferRegister(15); + + if (!incrementBase) { + if (postIndexing) + startAddress -= (registerCount + (transferPC ? -1 : 0)) * 4; //post-indexing, backward reading + else + startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; //pre-indexing, backward-reading + } + else if (postIndexing) { + //post-indexing, forward reading + startAddress -= 4; + } + + //are we supposed to load or store multiple registers? + if (isLoad) { + //read the actual registers + for (int i = 0; i < registerCount; i++) { + startAddress += 4; + regs.set(registersToTransfer[i], ps.memory.load32(startAddress)); + } + + //if we also transferred the program counter + if (transferPC) { + int newpc = ps.memory.load32(startAddress + 4); + regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); + + //shall we switch to thumb mode + regs.setThumbMode((newpc & 0x1) != 0); + } + } + else { + //also transfer the program counter, if requested so + if (transferPC) + registersToTransfer[registerCount++] = 15; + + for (int i = 0; i < registerCount; i++) { + startAddress += 4; + ps.memory.store32(startAddress, regs.get(i)); + } + } + } + + public int getSuccessor(int pc) { + //if we're loading values into the PC, then we can't tell where this instruction will be going + if (isLoad && transferRegister(ARM_Registers.PC)) + return -1; + else + return pc+4; + } + } + + private class Branch extends ARM_Instructions.Branch implements Interpreter.Instruction { + + public Branch(int instr) { + super(instr); + } + + public void execute() { + int previousAddress = regs.get(ARM_Registers.PC); + + //jump to the new address + regs.set(ARM_Registers.PC, previousAddress + getOffset()); + + //if we're supposed to link, then write the previous address into the link register + if (link) + regs.set(ARM_Registers.LR, previousAddress + 4); + } + + public int getSuccessor(int pc) { + return pc + getOffset(); + } + } + + private class BranchExchange extends ARM_Instructions.BranchExchange implements Interpreter.Instruction { + + public BranchExchange(int instr) { + super(instr); + } + + public void execute() { + int previousAddress = regs.get(ARM_Registers.PC); + boolean thumb; + int targetAddress; + + switch (target.getType()) { + case PcRelative: + targetAddress = previousAddress + target.getOffset(); + thumb = true; + break; + + case Register: + targetAddress = regs.get(target.getRegister()); + thumb = (targetAddress & 0x1) != 0; + targetAddress = targetAddress & 0xFFFFFFFE; + break; + + default: + throw new RuntimeException("Unexpected Operand type: " + target.getType()); + } + + //jump to the new address + regs.set(ARM_Registers.PC, targetAddress); + regs.setThumbMode(thumb); + + //if we're supposed to link, then write the previous address into the link register + if (link) + regs.set(ARM_Registers.LR, previousAddress + 4); + } + + public int getSuccessor(int pc) { + //if we're jumping relative to the PC, then we can predict the next instruction + if (target.getType() == OperandWrapper.Type.PcRelative) { + return pc + target.getOffset(); + } + else { + //otherwise we can't predict it + return -1; + } + } + } + + private class CountLeadingZeros extends ARM_Instructions.CountLeadingZeros implements Interpreter.Instruction { + + public CountLeadingZeros(int instr) { + super(instr); + } + + public void execute() { + int leadingZeros = Integer.numberOfLeadingZeros(regs.get(Rm)); + regs.set(Rd, leadingZeros); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class IntMultiply extends ARM_Instructions.IntMultiply implements Interpreter.Instruction { + + protected IntMultiply(int instr) { + super(instr); + } + + public void execute() { + int result = regs.get(Rm) * regs.get(Rs); + + if (accumulate) + result += regs.get(Rn); + + regs.set(Rd, result); + + if (updateConditionCodes) { + regs.setFlags(result < 0, result == 0); + } + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class MoveFromStatusRegister extends ARM_Instructions.MoveFromStatusRegister implements Interpreter.Instruction { + + public MoveFromStatusRegister(int instr) { + super(instr); + } + + public void execute() { + int statusRegisterValue; + + if (transferSavedPSR) { + statusRegisterValue = regs.getSPSR(); + } + else { + statusRegisterValue = regs.getCPSR(); + } + + regs.set(Rd, statusRegisterValue); + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + private class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt implements Interpreter.Instruction { + + public SoftwareInterrupt(int instr) { + super(instr); + } + + public void execute() { + ps.doSysCall(); + } + + public int getSuccessor(int pc) { + return -1; + } + + } + + private class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer implements Interpreter.Instruction { + + public SingleDataTransfer(int instr) { + super(instr); + } + + public void execute() { + + } + + public int getSuccessor(int pc) { + //if we're loading to the PC, then the next instruction is undefined + if (Rd == ARM_Registers.PC) + return -1; + + return pc+4; + } + + } + + private class UndefinedInstruction implements Interpreter.Instruction { + + private final int instruction; + + public UndefinedInstruction(int instr) { + this.instruction = instr; + } + + public void execute() { + throw new RuntimeException("Undefined instruction: " + instruction); + } + + public int getSuccessor(int pc) { + return -1; + } + } + + class InterpreterFactory implements + ARM_InstructionFactory<Interpreter.Instruction> { + + public Interpreter.Instruction createDataProcessing(int instr) { + Opcode opcode = Opcode.values()[Utils.getBits(instr, 21, 24)]; + + switch (opcode) { + case ADC: + return new DataProcessing_Adc(instr); + case ADD: + return new DataProcessing_Add(instr); + case AND: + return new DataProcessing_And(instr); + case BIC: + return new DataProcessing_Bic(instr); + case CMN: + return new DataProcessing_Cmn(instr); + case CMP: + return new DataProcessing_Cmp(instr); + case EOR: + return new DataProcessing_Eor(instr); + case MOV: + return new DataProcessing_Mov(instr); + case MVN: + return new DataProcessing_Mvn(instr); + case ORR: + return new DataProcessing_Orr(instr); + case RSB: + return new DataProcessing_Rsb(instr); + case RSC: + return new DataProcessing_Rsc(instr); + case SBC: + return new DataProcessing_Sbc(instr); + case SUB: + return new DataProcessing_Sub(instr); + case TEQ: + return new DataProcessing_Teq(instr); + case TST: + return new DataProcessing_Tst(instr); + + default: + throw new RuntimeException("Unexpected Data Procesing opcode: " + + opcode); + } + } + + public Instruction createBlockDataTransfer(int instr) { + return new BlockDataTransfer(instr); + } + + public Instruction createBranch(int instr) { + return new Branch(instr); + } + + public Instruction createBranchExchange(int instr) { + return new BranchExchange(instr); + } + + public Instruction createCoprocessorDataProcessing(int instr) { + //TODO: Implement coprocessor instructions + throw new RuntimeException("Coprocessor instructions are not yet supported."); + } + + public Instruction createCoprocessorDataTransfer(int instr) { +// TODO: Implement coprocessor instructions + throw new RuntimeException("Coprocessor instructions are not yet supported."); + } + + public Instruction createCoprocessorRegisterTransfer(int instr) { +// TODO: Implement coprocessor instructions + throw new RuntimeException("Coprocessor instructions are not yet supported."); + } + + public Instruction createCountLeadingZeros(int instr) { + return new CountLeadingZeros(instr); + } + + public Instruction createIntMultiply(int instr) { + return new IntMultiply(instr); + } + + public Instruction createLongMultiply(int instr) { + throw new RuntimeException("Long Multiplications are not yet supported."); + } + + public Instruction createMoveFromStatusRegister(int instr) { + return new MoveFromStatusRegister(instr); + } + + public Instruction createMoveToStatusRegister(int instr) { + //TODO: Implement Register -> CPSR transfers + throw new RuntimeException("Modifying the status register using MSR is not yet supported."); + } + + public Instruction createSingleDataTransfer(int instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createSoftwareInterrupt(int instr) { + return new SoftwareInterrupt(instr); + } + + public Instruction createSwap(int instr) { + return new Swap(instr); + } + + public Instruction createUndefinedInstruction(int instr) { + return new UndefinedInstruction(instr); + } + } + +} Added: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-04-17 18:11:39 UTC (rev 60) @@ -0,0 +1,84 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.DBT; + +class Utils { + + /** + * Checks if a bit is set within a word. + * @param word + * The word that is being examined. + * @param bit + * The number of the bit that is to be checked, starting from zero. + * @return + * True, if the given bit is set within the word, false otherwise. + */ + static final boolean getBit(int word, int bit) { + if (DBT.VerifyAssertions) + DBT._assert(bit >= 0 && bit <= 31); + return (word & (1 << bit)) != 0; + } + + /** + * Extracts a subsequence of bits from a word. + * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. + * @param word + * The word that is to be examined. + * @param from + * The first bit (starting from 0) that is to be extracted. + * @param to + * The last bit (starting from 0) that is to be extracted from the word. + * @return + * A zero-based version of the bit sequence. + */ + static final int getBits(int word, int from, int to) { + if (DBT.VerifyAssertions) + DBT._assert(from < to && from >= 0 && to <= 31); + return (word & ((1 << (to + 1)) - 1)) >> from; + } + + /** + * Sign extends a given value. + * @param value + * The value to sign extends. + * @param bitsUsed + * The number bits used within this values. + * @return + * A sign extended value. + */ + static int signExtend(int value, int bitsUsed) { + return (value << (32 - bitsUsed)) >> (32 - bitsUsed); + } + + /** + * Returns true, if the addition of both operands as unsigned integers will cause an overflow. + * This basically checks <code> operand1 + operand2 > Integer.MAX_VALUE</code>. + */ + static boolean unsignedAddOverflow(int operand1, int operand2) { + return operand1 > Integer.MAX_VALUE - operand2; + } + + /** + * Returns true, if the subtraction of both operand1 - operand2 (both unsigned) will be a negative number. + * That only happens when <code>operand1 < operand2</code> + */ + static boolean unsignedSubOverflow(int operand1, int operand2) { + return operand1 < operand2; + } + + /** + * Returns true, if the addition of both operands as unsigned integers will cause an overflow. + * The algorithm for this code was taken from http://msdn2.microsoft.com/en-us/library/ms972705.aspx. + */ + static boolean signedAddOverflow(int operand1, int operand2) { + //overflow can only occur when both signs differ + if ((operand1 ^ operand2) >= 0) { + return false; + } + + if (operand1 < 0) + return operand1 < Integer.MIN_VALUE - operand2; + else + return Integer.MAX_VALUE - operand1 < operand2; + } +} Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-04-17 18:11:39 UTC (rev 60) @@ -75,7 +75,7 @@ public static ProcessSpace createProcessSpaceFromBinary(Loader loader) throws IOException { if (loader.isARM_ABI() || loader.isSysV_ABI()) { - report("Creating ARM Linux ABI [rocess space"); + report("Creating ARM Linux ABI Process space"); return new ARM_LinuxProcessSpace(); } else { report("Creating ARM image process space."); @@ -96,21 +96,21 @@ */ @Uninterruptible public int getCurrentInstructionAddress() { - return registers.read(ARM_Registers.PC); + return registers.get(ARM_Registers.PC); } /** * Sets the current instruction's address */ public void setCurrentInstructionAddress(int pc) { - registers.write(ARM_Registers.PC, pc); + registers.set(ARM_Registers.PC, pc); } /** * Return as an integer the current instruction's address */ public int getCurrentStackAddress() { - return registers.read(14); + return registers.get(ARM_Registers.SP); } /** Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-04-17 18:11:39 UTC (rev 60) @@ -4,8 +4,8 @@ public final class ARM_Registers { - public final static int SP = 14; - + public final static int SP = 13; + public final static int LR = 14; public final static int PC = 15; /** @@ -77,23 +77,38 @@ public final static byte OPERATING_MODE_ABT = 0x17; public final static byte OPERATING_MODE_UND = 0x1A; + + /** Is the processor currently in thumb mode? */ + private boolean thumbMode = false; public ARM_Registers() { } - public int read(int reg) { + /** Returns the value of the specified register. */ + public int get(int reg) { if (VM.VerifyAssertions) VM._assert(reg < 16); return regs[reg]; } - public void write(int reg, int value) { + /** Sets the value of the specified register (<code>reg</code>) to <code>value</code>. */ + public void set(int reg, int value) { if (VM.VerifyAssertions) VM._assert(reg < 16); regs[reg] = value; } + + /** + * Restores the saved program status register of the current operating mode to the CPSR, + * thereby effectively switching to a different operating mode. + */ + public void restoreSPSR2CPSR() { + if (VM.VerifyAssertions) VM._assert(operatingMode != OPERATING_MODE_USR && operatingMode != OPERATING_MODE_SVC); + + setFlagsFromCPSR(getSPSR()); + } /** * Returns the content of ARM's Current Program Status Register. @@ -104,8 +119,13 @@ return (flagNegative ? 1 << 31 : 0) | (flagZero ? 1 << 30 : 0) | (flagCarry ? 1 << 29 : 0) | (flagOverflow ? 1 << 28 : 0) | (flagIRQsDisabled ? 1 << 7 : 0) | (flagFIQsDisabled ? 1 << 6 : 0) - | operatingMode; + | (thumbMode ? 1 << 5 : 0) | operatingMode; } + + /** Returns the content of the current mode's Saved Program Status register.*/ + public int getSPSR() { + throw new RuntimeException("Accessing the SPSR is not yet implemented"); + } /** * Restores the processor state to the state saved within the given CPSR. @@ -114,7 +134,69 @@ * ARM CPSR register content */ public void setFlagsFromCPSR(int cpsr) { - throw new RuntimeException("Not yet implemented."); + throw new RuntimeException("Interpreting a previous SPSR is not yet implemented."); } + + /** + * This function switches the processor to either ARM or Thumb mode. + * + * @param enable + * Set to true to enable execution of thumb code, false otherwise. + */ + public void setThumbMode(boolean enable) { + thumbMode = enable; + } + + /** + * Sets all flags at once. This operation is very common in the ARm architecture and therefore + * implemented explicitely. + * @param negative + * The value of the negative flag. + * @param zero + * The value of the zero flag. + * @param carry + * The value of the carry flag. + * @param overflow + * The value of the overflow flag. + */ + public void setFlags(boolean negative, boolean zero, boolean carry, boolean overflow) { + flagNegative = negative; + flagZero = zero; + flagCarry = carry; + flagOverflow = overflow; + } + + /** + * Sets all flags, except for the overflow flag, at once. This operation is very common in the ARm architecture and therefore + * implemented explicitely. + * @param negative + * The value of the negative flag. + * @param zero + * The value of the zero flag. + * @param carry + * The value of the carry flag. + */ + public void setFlags(boolean negative, boolean zero, boolean carry) { + flagNegative = negative; + flagZero = zero; + flagCarry = carry; + } + + /** + * Sets the negative and zero flags at once. + * @param negative + * The value of the negative flag. + * @param zero + * The value of the zero flag. + */ + public void setFlags(boolean negative, boolean zero) { + flagNegative = negative; + flagZero = zero; + } + + /** Returns true if the carry flag is set, false otherwise. */ + public boolean isCarrySet() { + return flagCarry; + } } Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-04-17 18:11:39 UTC (rev 60) @@ -29,7 +29,7 @@ @Override public void initialise(Loader loader, int pc, int brk) { - registers.write(ARM_Registers.PC, pc); + registers.set(ARM_Registers.PC, pc); } } Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-17 18:11:39 UTC (rev 60) @@ -47,7 +47,7 @@ @Override public void initialise(Loader loader, int pc, int brk) { - registers.write(ARM_Registers.PC, pc); + registers.set(ARM_Registers.PC, pc); this.brk = brk; // initialize the stack Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_SyscallArgumentIterator.java 2007-04-17 18:11:39 UTC (rev 60) @@ -15,7 +15,7 @@ } public int nextInt() { - return ps.registers.read(currentArgument++); + return ps.registers.get(currentArgument++); } public long nextLong() { Modified: src/org/binarytranslator/generic/decoder/DisassembledInstruction.java =================================================================== --- src/org/binarytranslator/generic/decoder/DisassembledInstruction.java 2007-04-16 21:28:29 UTC (rev 59) +++ src/org/binarytranslator/generic/decoder/DisassembledInstruction.java 2007-04-17 18:11:39 UTC (rev 60) @@ -1,7 +1,8 @@ package org.binarytranslator.generic.decoder; /** - * Represents a disassembled instruction. + * Represents an instruction, after it has been decoded by a disassembler. + * The instruction should be printable in the format of the target system's assembly language. * * @author Michael Baer */ Added: src/org/binarytranslator/generic/decoder/Interpreter.java =================================================================== --- src/org/binarytranslator/generic/decoder/Interpreter.java (rev 0) +++ src/org/binarytranslator/generic/decoder/Interpreter.java 2007-04-17 18:11:39 UTC (rev 60) @@ -0,0 +1,12 @@ +package org.binarytranslator.generic.decoder; + +public interface Interpreter { + + public interface Instruction { + + void execute(); + int getSuccessor(int pc); + } + + Instruction decode(int pc); +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |