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