From: <mic...@us...> - 2007-06-18 17:06:44
|
Revision: 133 http://svn.sourceforge.net/pearcolator/?rev=133&view=rev Author: michael_baer Date: 2007-06-18 10:06:44 -0700 (Mon, 18 Jun 2007) Log Message: ----------- First version that runs libc "Hello World" in Thumb code Modified Paths: -------------- src/org/binarytranslator/DBT_Options.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_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/Utils.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/generic/execution/InterpreterController.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/DBT_Options.java 2007-06-18 17:06:44 UTC (rev 133) @@ -19,7 +19,7 @@ public class DBT_Options { /** Remove features that will only work on jikes? */ - public final static boolean buildForSunVM = false; + public final static boolean buildForSunVM = true; /** Enable the profiling of application during interpretation? */ public final static boolean profileDuringInterpretation = true; @@ -102,7 +102,7 @@ public static boolean debugTranslation = true; /** In ProcessSpace, print syscall numbers. */ - public static boolean debugSyscall = false; + public static boolean debugSyscall = true; /** In ProcessSpace, print syscall numbers. */ public static boolean debugSyscallMore = false; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-18 17:06:44 UTC (rev 133) @@ -19,7 +19,6 @@ 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; -import org.binarytranslator.generic.os.process.ProcessSpace; /** * This class transfers an ARM instruction into a human-readable assembly @@ -54,7 +53,7 @@ decodedInstruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction); } - DisassemblingVisitor disassembler = new DisassemblingVisitor(address); + DisassemblingVisitor disassembler = new DisassemblingVisitor(); decodedInstruction.visit(disassembler); return disassembler.result; @@ -130,17 +129,9 @@ /** This field receives the disassembled instruction. */ private ARM_DisassembledInstruction result; - /** The address of the instruction which is currently decoded or -1, if that address is not known. */ - private int address; - private DisassemblingVisitor() { - this.address = -1; } - private DisassemblingVisitor(int address) { - this.address = address; - } - /** Wraps a decoded assembly statement within an {@link ARM_DisassembledInstruction} object and * stores it as the result of this operation. */ private void setResult(String assembly) { @@ -180,10 +171,7 @@ op.getShiftAmount()); case RegisterOffset: - if (address != -1) - return String.format("#0x%x", op.getOffset() + address + 8); - else - return String.format("#<%d + pc>", op.getOffset()); + return String.format("#<r%d + %d>", op.getRegister(), op.getOffset()); case Register: return "r" + op.getRegister(); @@ -361,11 +349,7 @@ public void visit(Branch instr) { String mnemonic = instr.link() ? "BL" : "B"; - - if (address != -1) - setResult(String.format("%s%s #%d", mnemonic, cond(instr), instr.getOffset() + address + 8)); - else - setResult(String.format("%s%s #<%d + pc>", mnemonic, cond(instr), instr.getOffset())); + setResult(String.format("%s%s [PC + %s]", mnemonic, cond(instr), operand(instr.offset))); } 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-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-18 17:06:44 UTC (rev 133) @@ -336,10 +336,14 @@ } else { //bit8==bit9==bit10==1? - if ((instr & 0x70) == 0x70) + if ((instr & 0x700) == 0x700) return factory.createBranchExchange(instr); - return factory.createDataProcessing(instr); + //We're not treating multiplication as data processing + if (Utils.getBits(instr, 6, 10) == 13) + return factory.createIntMultiply(instr); + else + return factory.createDataProcessing(instr); } } } @@ -361,20 +365,15 @@ @Override <T> T decode(short instr, ARM_InstructionFactory<T> factory) { - if (Utils.getBit(instr, 11)) { - return factory.createSingleDataTransfer(instr); + //bit9==bit10==bit11==1? + if ((instr & 0x0E00) == 0x0E00) { + if (Utils.getBit(instr, 8)) + return factory.createSoftwareInterrupt(instr); + else + return factory.createUndefinedInstruction(instr); } - else { - //bit9==bit10==bit11==1? - if ((instr & 0xE0) == 0xE0) { - if (Utils.getBit(instr, 8)) - return factory.createSoftwareInterrupt(instr); - else - return factory.createUndefinedInstruction(instr); - } - - return factory.createBranch(instr); - } + + return factory.createBranch(instr); } } @@ -424,7 +423,7 @@ */ static <T> T decode(short instruction, ARM_InstructionFactory<T> factory) { - int bits_12_15 = Utils.getBits(instruction, 12, 15); + int bits_12_15 = (instruction & 0xF000) >>> 12; return prefixDecoders[bits_12_15].decode(instruction, factory); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-18 17:06:44 UTC (rev 133) @@ -22,6 +22,8 @@ /** A base class for all (conditional) ARM instructions. */ public abstract static class Instruction { + protected final boolean isThumb; + public enum Condition { EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV } @@ -31,15 +33,22 @@ private Instruction () { this.condition = Condition.AL; + this.isThumb = true; } private Instruction (Condition condition) { this.condition = condition; + this.isThumb = true; } private Instruction(int instr) { condition = Condition.values()[(instr & 0xF0000000) >>> 28]; + this.isThumb = false; } + + public final int size() { + return isThumb ? 2 : 4; + } /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ public final Condition getCondition() { @@ -54,69 +63,6 @@ /** 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 multiply operations. */ - protected abstract static class MultiplyTemplate extends Instruction { - - /** @see #updateConditionCodes() */ - protected final boolean updateConditionCodes; - - /** @see #accumulate() */ - protected final boolean accumulate; - - /** @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. */ - 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; - } - - /** 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. */ protected static abstract class CoprocessorTemplate extends Instruction { @@ -473,7 +419,7 @@ updateConditionCodes = false; Rd = (byte)Utils.getBits(instr, 8, 10); Rn = (byte)(Utils.getBit(instr, 11) ? ARM_Registers.SP : ARM_Registers.PC); - operand2 = OperandWrapper.createImmediate(instr & 0xFF); + operand2 = OperandWrapper.createImmediate((instr & 0xFF) << 2); return; } @@ -484,12 +430,12 @@ opcode = Utils.getBit(instr, 7) ? Opcode.SUB : Opcode.ADD; Rd = (byte)ARM_Registers.SP; Rn = (byte)ARM_Registers.SP; - operand2 = OperandWrapper.createImmediate(instr & 0x7F); + operand2 = OperandWrapper.createImmediate((instr & 0x7F) << 2); return; } - if (Utils.getBits(instr, 14, 15) == 0x7) { + if (Utils.getBits(instr, 13, 15) == 0x7) { //first instruction of a long bl/blx if (DBT.VerifyAssertions) DBT._assert(Utils.getBits(instr, 11, 12) == 2); @@ -512,7 +458,7 @@ Rn = (byte)Utils.getBits(instr, 3, 5); updateConditionCodes = true; - if (Utils.getBits(instr, 11, 12) == 0) { + if (Utils.getBits(instr, 11, 12) != 0x3) { //shift by immediate opcode = Opcode.MOV; ShiftType type = ShiftType.values()[Utils.getBits(instr, 11, 12)]; @@ -559,19 +505,21 @@ Rd = (byte)(Utils.getBits(instr, 0, 2) + (Utils.getBit(instr, 7) ? 8 : 0)); Rn = Rd; operand2 = OperandWrapper.createRegister((byte)(Utils.getBits(instr, 3, 5) + (Utils.getBit(instr, 6) ? 8 : 0))); - updateConditionCodes = true; switch (Utils.getBits(instr, 8, 9)) { case 0: opcode = Opcode.ADD; + updateConditionCodes = false; break; case 1: opcode = Opcode.CMP; + updateConditionCodes = true; break; case 2: opcode = Opcode.MOV; + updateConditionCodes = false; break; case 3: @@ -631,6 +579,7 @@ case 8: opcode = Opcode.TST; operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; break; case 9: @@ -641,11 +590,13 @@ case 10: opcode = Opcode.CMP; operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; break; case 11: opcode = Opcode.CMN; operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; break; case 12: @@ -778,7 +729,7 @@ Utils.getBits(instr, 12, 15) == 0x9) { //load from literal pool or stack load/store Rd = (byte) Utils.getBits(instr, 8, 10); - offset = OperandWrapper.createImmediate(instr & 0xFF); + offset = OperandWrapper.createImmediate((instr & 0xFF) * 4); isLoad = Utils.getBit(instr, 11); signExtend = false; size = TransferSize.Word; @@ -812,7 +763,6 @@ } else { //load/store word/halfword/byte with immediate offset - offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10)); isLoad = Utils.getBit(instr, 11); signExtend = false; @@ -824,6 +774,23 @@ //transfer Half-word size = TransferSize.HalfWord; } + + switch (size) { + case Word: + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10) << 2); + break; + + case HalfWord: + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10) << 1); + break; + + case Byte: + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10)); + break; + + default: + throw new RuntimeException("Unexpected transfer size."); + } } } } @@ -947,23 +914,105 @@ } /** Represents a normal (not long) multiply instruction. */ - public final static class IntMultiply extends MultiplyTemplate { + public final static class IntMultiply extends Instruction { + + /** @see #updateConditionCodes() */ + protected final boolean updateConditionCodes; + + /** @see #accumulate() */ + protected final boolean accumulate; + + /** @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 IntMultiply(short instr) { + updateConditionCodes = true; + accumulate = false; + Rd = (byte)Utils.getBits(instr, 0, 2); + Rm = (byte)Utils.getBits(instr, 3, 5); + Rn = Rd; + Rs = Rd; + } protected IntMultiply(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); + //check for instruction combinations that show undefined behaviour on ARM if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } + + /** 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; + } + + /** 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; + } + public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); } } /** Represents a long multiply instruction. */ - public final static class LongMultiply extends MultiplyTemplate { + public final static class LongMultiply extends Instruction { + /** @see #updateConditionCodes() */ + protected final boolean updateConditionCodes; + + /** @see #accumulate() */ + protected final boolean accumulate; + + /** @see #getRs() */ + protected final byte Rs; + + /** @see #getRn() */ + protected final byte RdLow; + + /** @see #getRm() */ + protected final byte Rm; + + /** @see #getRd() */ + protected final byte RdHigh; + /** @see #isUnsigned() */ protected final boolean unsigned; @@ -971,19 +1020,45 @@ super(instr); unsigned = Utils.getBit(instr, 22); + updateConditionCodes = Utils.getBit(instr, 20); + accumulate = Utils.getBit(instr, 21); + RdHigh = (byte) Utils.getBits(instr, 16, 19); + RdLow = (byte) Utils.getBits(instr, 12, 15); + Rs = (byte) Utils.getBits(instr, 8, 11); + Rm = (byte) Utils.getBits(instr, 0, 3); //check for instruction combinations that show undefined behaviour on ARM - if (DBT.VerifyAssertions) DBT._assert(Rd != 15); + if (DBT.VerifyAssertions) DBT._assert(RdHigh != 15 && RdLow != 15); } + /** 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; + } + + /** Returns the register number of the Rm operand register. */ + public final byte getRm() { + return Rm; + } + /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ public final byte getRdHigh() { - return Rd; + return RdHigh; } /** Long multiplication stores its result in two registers. This function gets the register which receives the low int. */ public final byte getRdLow() { - return Rn; + return RdLow; } /** Returns true, if this is an unsigned multiplication or false if it is a signed multiplication. */ @@ -1074,11 +1149,12 @@ forceUser = false; writeBack = true; isLoad = Utils.getBit(instr, 11); - incrementBase = postIndexing = isLoad; int regList = instr & 0xFF; - if (Utils.getBit(instr, 14)) { + if (!Utils.getBit(instr, 14)) { + incrementBase = postIndexing = isLoad; + //PUSH / POP registers baseRegister = ARM_Registers.SP; @@ -1097,6 +1173,7 @@ else { //LDMIA/STMIA baseRegister = (byte)Utils.getBits(instr, 8, 10); + incrementBase = postIndexing = true; } registerList = regList; @@ -1192,19 +1269,23 @@ protected final boolean link; /** @see #getOffset() */ - protected final int offset; + protected final OperandWrapper offset; public Branch(short instr) { - super (Utils.getBit(instr, 13) ? Condition.values()[Utils.getBits(instr, 8, 11)] : Condition.AL); - - if (Utils.getBit(instr, 13)) { - offset = instr & 0xFF; + super (Utils.getBit(instr, 13) ? Condition.AL : Condition.values()[Utils.getBits(instr, 8, 11)]); + + if (!Utils.getBit(instr, 13)) { + offset = OperandWrapper.createImmediate(Utils.signExtend(instr & 0xFF, 8) << 1); link = false; } else { - offset = Utils.getBits(instr, 0, 10); link = Utils.getBit(instr, 12); + if (link) + offset = OperandWrapper.createRegisterOffset(link ? ARM_Registers.LR : ARM_Registers.PC, (Utils.getBits(instr, 0, 10) << 1) - 2); + else + offset = OperandWrapper.createImmediate(Utils.signExtend(Utils.getBits(instr, 0, 10), 11) << 1); + //only the second instruction of a long branch is actually a branch if (DBT.VerifyAssertions && link) DBT._assert(Utils.getBit(instr, 11)); } @@ -1214,7 +1295,7 @@ public Branch(int instr) { super(instr); link = Utils.getBit(instr, 24); - offset = Utils.signExtend((instr & 0xFFFFFF) << 2, 26); + offset = OperandWrapper.createImmediate(Utils.signExtend((instr & 0xFFFFFF) << 2, 26)); } /** Should the current PC be put into the lr? */ @@ -1223,7 +1304,7 @@ } /** The offset of the target address to the PC */ - public final int getOffset() { + public final OperandWrapper getOffset() { return offset; } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-18 17:06:44 UTC (rev 133) @@ -374,21 +374,25 @@ public void execute() { if (isConditionTrue()) { + int nextInstruction = conditionalInstruction.getSuccessor(ps.getCurrentInstructionAddress()); conditionalInstruction.execute(); - int nextInstruction = conditionalInstruction.getSuccessor(ps.getCurrentInstructionAddress()); - if (nextInstruction != -1) ps.setCurrentInstructionAddress(nextInstruction); } - else - ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress()+4); + else { + ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress() + (regs.getThumbMode() ? 2 : 4)); + } } public int getSuccessor(int pc) { //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; + + int conditionalSuccessor = conditionalInstruction.getSuccessor(pc); + boolean thumbMode = (pc & 0x1) == 1; + + if (conditionalSuccessor == pc + 4 && !thumbMode) + return conditionalSuccessor; //ARM may have conditional non-jump instructions else return -1; } @@ -463,12 +467,22 @@ protected DataProcessing(ARM_Instructions.DataProcessing instr) { i = instr; } + + @Override + public String toString() { + return i.toString(); + } /** Returns the value of operand 1 of the data processing instruction. This is always a register value. */ protected int resolveOperand1() { if (i.Rn == ARM_Registers.PC) { - return regs.readPC(); + int value = regs.readPC(); + + if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD) + value = value & 0xFFFFFFFC; + + return value; } return regs.get(i.Rn); @@ -551,7 +565,7 @@ public int getSuccessor(int pc) { if (i.Rd != 15) - return pc + 4; + return pc + i.size(); else return -1; } @@ -925,11 +939,16 @@ regs.set(i.Rd, tmp); } } + + @Override + public String toString() { + return i.toString(); + } 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(); } } @@ -1036,7 +1055,7 @@ } else { //shall we switch to thumb mode - regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); + regs.set(ARM_Registers.PC, newpc); regs.setThumbMode((newpc & 0x1) != 0); } } @@ -1062,7 +1081,7 @@ ps.registers.switchOperatingMode(previousMode); } - if (i.writeBack) { + if (i.writeBack && !i.transferRegister(i.baseRegister)) { //write the last address we read from back to a register if (!i.incrementBase) { //backward reading @@ -1089,12 +1108,17 @@ return i.condition; } + @Override + public String toString() { + return i.toString(); + } + 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 (i.isLoad && transferPC) return -1; else - return pc + 4; + return pc + i.size(); } } @@ -1108,25 +1132,53 @@ } public void execute() { + + int destination; + BranchType branchType; + + if (i.offset.getType() != OperandWrapper.Type.Immediate) { + branchType = BranchType.INDIRECT_BRANCH; + } + else { + branchType = BranchType.DIRECT_BRANCH; + } + + destination = regs.readPC() + ResolvedOperand.resolve(regs, i.offset); + + if (DBT_Options.profileDuringInterpretation) { + if (i.link) { + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), destination, regs.get(ARM_Registers.PC) + i.size()); + } + else { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), destination, branchType); + } + } + //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)); - - if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), regs.get(ARM_Registers.PC) + 4); } - else { - if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), BranchType.DIRECT_BRANCH); - } + + if (regs.getThumbMode()) + destination |= 1; + + regs.set(ARM_Registers.PC, destination); } public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc + i.getOffset() + 8; + if (i.offset.getType() == OperandWrapper.Type.Immediate) + return (pc + 2*i.size() + i.getOffset().getImmediate()) | (pc & 1); + else + return -1; } } @@ -1164,9 +1216,13 @@ break; case Register: - targetAddress = regs.get(i.target.getRegister()); + if (i.target.getRegister() != ARM_Registers.PC) + targetAddress = regs.get(i.target.getRegister()); + else + targetAddress = regs.readPC(); + thumb = (targetAddress & 0x1) != 0; - targetAddress = targetAddress & 0xFFFFFFFE; + //targetAddress = targetAddress & 0xFFFFFFFE; break; default: @@ -1177,7 +1233,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.readPC() - (regs.getThumbMode() ? 2 : 4)); - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.CALL); + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), targetAddress, regs.get(ARM_Registers.PC) + i.size()); } else { ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.DIRECT_BRANCH); @@ -1191,10 +1247,15 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { //if we're jumping relative to the PC, then we can predict the next instruction - if (i.target.getType() == OperandWrapper.Type.RegisterOffset) { + if (i.target.getType() == OperandWrapper.Type.RegisterOffset && i.target.getRegister() == ARM_Registers.PC) { return pc + i.target.getOffset(); } else { //otherwise we can't predict it @@ -1238,9 +1299,14 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -1293,9 +1359,14 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -1319,13 +1390,18 @@ } } + @Override + public String toString() { + return i.toString(); + } + 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 - return pc + 4; + return pc + i.size(); } } @@ -1389,9 +1465,14 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc+4; + return pc + i.size(); } } @@ -1411,6 +1492,11 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { return -1; @@ -1445,8 +1531,13 @@ int base; //take ARM's PC offset into account - if (i.Rn == ARM_Registers.PC) + if (i.Rn == ARM_Registers.PC) { base = regs.readPC(); + + //Thumb mode has this weird way of accessing the PC sometimes + if (i.isThumb && i.isLoad) + base = base & 0xFFFFFFFC; + } else base = regs.get(i.Rn); @@ -1504,7 +1595,7 @@ regs.set(i.Rd, value); if (DBT_Options.profileDuringInterpretation) { - if (i.Rd == 15) + if (i.Rd == ARM_Registers.PC) ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), value, BranchType.INDIRECT_BRANCH); } } @@ -1551,13 +1642,18 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { //if we're loading to the PC, then the next instruction is undefined if (i.Rd == ARM_Registers.PC && i.isLoad) return -1; - return pc + 4; + return pc + i.size(); } } @@ -1582,6 +1678,12 @@ } private final class DebugNopInstruction implements ARM_Instruction { + + private boolean isThumb; + + public DebugNopInstruction(boolean isThumb) { + this.isThumb = isThumb; + } public void execute() { } @@ -1591,7 +1693,7 @@ } public int getSuccessor(int pc) { - return pc+4; + return pc + (isThumb ? 2 : 4); } } @@ -1661,21 +1763,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) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-18 17:06:44 UTC (rev 133) @@ -1686,7 +1686,7 @@ } private void translateWriteback(OPT_RegisterOperand startAddress, OPT_RegisterOperand nextAddress) { - if (i.writeBack) { + if (i.writeBack && !i.transferRegister(i.baseRegister)) { OPT_RegisterOperand writeBackTarget = arm2ir.getRegister(i.baseRegister); //write the last address we read from back to a register @@ -1737,20 +1737,38 @@ } public void translate() { + + 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()); + else + arm2ir.appendBranch(readPC() + i.getOffset().getImmediate(), lazy, BranchType.DIRECT_BRANCH); + } + else { + + OPT_Operand offset = ResolvedOperand.resolve(ARM_Translator.this, i.offset); + OPT_RegisterOperand dest = arm2ir.getTempInt(0); + + arm2ir.appendInstruction(Binary.create(INT_ADD, dest, offset, new OPT_IntConstantOperand(readPC()))); + + if (i.link) { + arm2ir.appendCall(dest, lazy, pc + i.size()); + } + else { + 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) { + 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(); } - - if (i.link) - arm2ir.appendCall( readPC() + i.getOffset(), lazy, pc + 4); - else - arm2ir.appendBranch(readPC() + i.getOffset(), lazy, BranchType.DIRECT_BRANCH); + } public Condition getCondition() { @@ -1758,7 +1776,10 @@ } public int getSuccessor(int pc) { - return readPC() + i.getOffset(); + if (i.offset.getType() == OperandWrapper.Type.Immediate) + return readPC() + i.getOffset().getImmediate(); + else + return -1; } } @@ -2086,6 +2107,13 @@ //add the offset to the base register OPT_RegisterOperand tmp = arm2ir.getTempInt(0); arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, base, resolveOffset())); + + if (i.isThumb && i.isLoad && i.Rn == ARM_Registers.PC) { + //with thumb, bit 1 of the address is always ignored - address = address & 0xFFFFFFFC; + //see ARM reference manual for further details + arm2ir.appendInstruction(Binary.create(INT_AND, tmp.copyRO(), tmp.copy(), new OPT_IntConstantOperand(0xFFFFFFFC))); + } + return tmp.copy(); } Modified: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-06-18 17:06:44 UTC (rev 133) @@ -53,7 +53,7 @@ */ static final int getBits(short word, int from, int to) { if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to < 15); + DBT._assert(from < to && from >= 0 && to <= 15); return (word & ((1 << (to + 1)) - 1)) >> from; } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-06-18 17:06:44 UTC (rev 133) @@ -289,11 +289,13 @@ * or 4 (Thumb) to the program counter itself. */ public int readPC() { - if (getThumbMode()) { - return get(ARM_Registers.PC) + 4; + int pc = get(ARM_Registers.PC); + + if ((pc & 0x1) == 1) { + return (pc & 0xFFFFFFFE) + 4; } else { - return get(ARM_Registers.PC) + 8; + return pc + 8; } } @@ -377,7 +379,7 @@ * Processor in thumb mode? */ public boolean getThumbMode() { - return thumbMode; + return thumbMode || ((get(ARM_Registers.PC) & 1) != 0); } /** Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-06-18 17:06:44 UTC (rev 133) @@ -28,7 +28,9 @@ ARM_Instructions.Instruction instr; if (registers.getThumbMode()) { - short instruction = (short)memory.loadInstruction16(getCurrentInstructionAddress()); + int instrAddr = getCurrentInstructionAddress() & 0xFFFFFFFE; + System.out.println("Thumb syscall at: " + instrAddr); + short instruction = (short)memory.loadInstruction16(instrAddr); instr = ARM_InstructionDecoder.Thumb.decode(instruction); } else { @@ -44,11 +46,11 @@ //Use a mask to let both calls start from the same address int sysCallNr = ((ARM_Instructions.SoftwareInterrupt)instr).getInterruptNumber(); - if (sysCallNr == 0x123456) { + if (sysCallNr == 0x123456 || sysCallNr == 0xab) { sysCalls.doSysCall(registers.get(0)); //simulate a proper return from syscalls - setCurrentInstructionAddress(getCurrentInstructionAddress() + 4); + setCurrentInstructionAddress(getCurrentInstructionAddress() + instr.size()); } else { //switch the operating mode to Supervisor Modified: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-06-18 17:06:44 UTC (rev 133) @@ -18,7 +18,7 @@ while (!ps.finished) { Interpreter.Instruction instruction = interpreter.decode(pc); - //System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); + System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); instruction.execute(); pc = instruction.getSuccessor(pc); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |