From: <cap...@us...> - 2007-04-13 11:12:08
|
Revision: 36 http://svn.sourceforge.net/pearcolator/?rev=36&view=rev Author: captain5050 Date: 2007-04-13 04:12:10 -0700 (Fri, 13 Apr 2007) Log Message: ----------- Build fixes :-( Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-04-13 10:45:30 UTC (rev 35) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-04-13 11:12:10 UTC (rev 36) @@ -179,7 +179,8 @@ @Override protected int translateInstruction(Laziness lazy, int pc) { - return ARM_InstructionDecoder.translateInstruction(this, - (ARM_ProcessSpace) ps, (ARM_Laziness) lazy, pc); + return 0xEBADC0DE; + //ARM_InstructionDecoder.translateInstruction(this, + // (ARM_ProcessSpace) ps, (ARM_Laziness) lazy, 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-13 10:45:30 UTC (rev 35) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-13 11:12:10 UTC (rev 36) @@ -9,6 +9,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.process.ProcessSpace; public class ARM_LinuxProcessSpace extends ARM_ProcessSpace implements LinuxSystemCallGenerator { @@ -104,4 +105,7 @@ return null; } + public ProcessSpace getProcessSpace() { + return this; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-20 22:55:51
|
Revision: 78 http://svn.sourceforge.net/pearcolator/?rev=78&view=rev Author: michael_baer Date: 2007-04-20 15:55:52 -0700 (Fri, 20 Apr 2007) Log Message: ----------- Fixed various bugs in ARM disassembler and 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_InstructionVisitor.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-20 22:55:52 UTC (rev 78) @@ -1,7 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction; -import org.binarytranslator.arch.arm.decoder.ARM_Instructions.BlockDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.MultipleDataTransfer; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Branch; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.BranchExchange; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.CoprocessorDataProcessing; @@ -188,11 +188,18 @@ String mnemonic = instr.getOpcode().name(); mnemonic += cond(instr); + String parameters; + + if (instr.getOpcode() == DataProcessing.Opcode.CMN || + instr.getOpcode() == DataProcessing.Opcode.CMP) { + //these functions don't use the destination register and always set the condition codes + setResult(String.format("%s r%s, %s", mnemonic, instr.getRn(), operand(instr.getOperand2()))); + return; + } + if (instr.updateConditionCodes()) mnemonic += 'S'; - String parameters; - // Filter instructions that only take one parameter if (instr.getOpcode() == DataProcessing.Opcode.MOV || instr.getOpcode() == DataProcessing.Opcode.MVN @@ -212,12 +219,22 @@ String address = "[r" + instr.getRn(); if (instr.preIndexing()) { - address += ", " + operand(instr.getOffset()) + "]"; + address += ", "; + + if (!instr.positiveOffset()) + address += '-'; + + address += operand(instr.getOffset()) + ']'; if (instr.writeBack()) address += '!'; } else { - address += "], " + operand(instr.getOffset()); + address += "], "; + + if (!instr.positiveOffset()) + address += '-'; + + address += operand(instr.getOffset()); } mnemonic += cond(instr); @@ -287,7 +304,7 @@ instr.getRd(), instr.getRm(), instr.getRn())); } - public void visit(BlockDataTransfer instr) { + public void visit(MultipleDataTransfer instr) { String mnemonic = instr.isLoad() ? "LDM" : "STM"; String baseRegister = "r" + instr.getBaseRegister(); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-04-20 22:55:52 UTC (rev 78) @@ -61,8 +61,8 @@ byte bits_7_4 = (byte)Utils.getBits(instr, 4, 7); - if (bits_7_4 == 0 && ((instr & 0x01900000) == 0x01100000)) { - //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 20) == true + if (bits_7_4 == 0 && ((instr & 0x01900000) == 0x01000000)) { + //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 20) == false if (Utils.getBit(instr, 21)) return factory.createMoveToStatusRegister(instr); else @@ -276,7 +276,7 @@ static class DefaultFactory implements ARM_InstructionFactory<ARM_Instructions.Instruction> { public Instruction createBlockDataTransfer(int instr) { - return new BlockDataTransfer(instr); + return new MultipleDataTransfer(instr); } public Instruction createBranch(int instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-04-20 22:55:52 UTC (rev 78) @@ -10,7 +10,7 @@ void visit(IntMultiply instr); void visit(LongMultiply instr); void visit(Swap instr); - void visit(BlockDataTransfer instr); + void visit(MultipleDataTransfer instr); void visit(SoftwareInterrupt instr); void visit(Branch instr); void visit(BranchExchange instr); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-20 22:55:52 UTC (rev 78) @@ -193,7 +193,7 @@ public static OperandWrapper decodeDataProcessingOperand(int instr) { if (Utils.getBit(instr, 25)) { //this is a right-rotated immediate value - byte shiftAmount = (byte)(Utils.getBits(instr, 8, 11) << 2); + byte shiftAmount = (byte)(Utils.getBits(instr, 8, 11) * 2); int value = instr & 0xFF; if (shiftAmount == 0) @@ -707,7 +707,7 @@ } /** Represents a LDM/STM instruction. */ - public static class BlockDataTransfer extends Instruction { + public static class MultipleDataTransfer extends Instruction { /** @see #postIndexing() */ protected final boolean postIndexing; @@ -730,10 +730,10 @@ /** Contains a set bit at position N if rN should be transferred using this instruction.*/ protected final int registerList; - public BlockDataTransfer(int instr) { + public MultipleDataTransfer(int instr) { super(instr); - postIndexing = Utils.getBit(instr, 24); + postIndexing = !Utils.getBit(instr, 24); incrementBase = Utils.getBit(instr, 23); forceUser = Utils.getBit(instr, 22); writeBack = Utils.getBit(instr, 21); @@ -820,7 +820,7 @@ public Branch(int instr) { super(instr); link = Utils.getBit(instr, 24); - offset = Utils.signExtend((instr & 0xFFF) << 2, 14); + offset = Utils.signExtend((instr & 0xFFFFFF) << 2, 26); } /** Should the current PC be put into the lr? */ Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-20 22:55:52 UTC (rev 78) @@ -68,8 +68,16 @@ } public void execute() { - if (isConditionTrue()) + if (isConditionTrue()) { conditionalInstruction.execute(); + + int nextInstruction = conditionalInstruction.getSuccessor(ps.getCurrentInstructionAddress()); + + if (nextInstruction != -1) + ps.setCurrentInstructionAddress(nextInstruction); + } + else + ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress()+4); } public int getSuccessor(int pc) { @@ -135,6 +143,11 @@ throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); } } + + @Override + public String toString() { + return conditionalInstruction.toString(); + } } /** A base class for all data processing interpreter instructions, including CLZ.*/ @@ -658,11 +671,11 @@ } /** Transfer multiple registers at once between the register bank and the memory. */ - private class BlockDataTransfer extends ARM_Instructions.BlockDataTransfer + private class BlockDataTransfer extends ARM_Instructions.MultipleDataTransfer implements ARM_Instruction { /** the lowest address that we're reading a register from / writing a register to */ - private final int startAddress; + private final int registerCount; /** An array that contains the registers to be transferd in ascending order. * The list is delimited by setting the entry after the last register index to -1. @@ -676,38 +689,40 @@ super(instr); transferPC = transferRegister(15); - int registerCount = 0; + int regCount = 0; for (int i = 0; i < 14; i++) if (transferRegister(i)) { - registersToTransfer[registerCount++] = i; + registersToTransfer[regCount++] = i; } - registersToTransfer[registerCount] = -1; + registersToTransfer[regCount] = -1; + + registerCount = regCount; + } + public void execute() { //build the address, which generally ignores the last two bits + int startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + if (!incrementBase) { if (postIndexing) { //post-indexing, backward reading - startAddress = regs.get(baseRegister) & 0xFFFFFFFC - - (registerCount + (transferPC ? -1 : 0)) * 4; + startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; } else { //pre-indexing, backward-reading - startAddress = regs.get(baseRegister) & 0xFFFFFFFC - - (registerCount + (transferPC ? 1 : 0)) * 4; + startAddress -= (registerCount + (transferPC ? 2 : 1)) * 4; } } else { if (postIndexing) { //post-indexing, forward reading - startAddress = regs.get(baseRegister) & 0xFFFFFFFC - 4; + startAddress -= 4; } else { //pre-indexing, forward reading - startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + //no need to adjust the start address + } } - } - - public void execute() { int nextAddress = startAddress; //are we supposed to load or store multiple registers? @@ -747,9 +762,22 @@ if (writeBack) { //write the last address we read from back to a register - //TODO: Check if we have to consider the different cases? - if (!incrementBase) - nextAddress = startAddress; + if (!incrementBase) { + //backward reading + if (postIndexing) { + //backward reading, post-indexing + nextAddress = startAddress; + } + else { + //backward reading, pre-indexing + nextAddress = startAddress + 4; + } + } + else { + //forward reading + if (postIndexing) + nextAddress += 4; + } regs.set(baseRegister, nextAddress); } @@ -954,32 +982,27 @@ //if we are not pre-indexing, then just use the base register for the memory access if (!preIndexing) return base; + + int addrOffset; switch (offset.getType()) { case Immediate: - if (positiveOffset) - return base + offset.getImmediate(); - else - return base - offset.getImmediate(); + addrOffset = offset.getImmediate(); + break; case Register: - int offsetRegister = regs.get(offset.getRegister()); + addrOffset = regs.get(offset.getRegister()); if (offset.getRegister() == ARM_Registers.PC) { - offsetRegister += 8; + addrOffset += 8; } + break; - if (positiveOffset) - return base + offsetRegister; - else - return base - offsetRegister; - case ImmediateShiftedRegister: + addrOffset = regs.get(offset.getRegister()); + if (offset.getRegister() == 15) - throw new RuntimeException( - "PC-relative memory accesses are not yet supported."); + addrOffset += 8; - int addrOffset = regs.get(offset.getRegister()); - switch (offset.getShiftType()) { case ASR: addrOffset = addrOffset >>> offset.getShiftAmount(); @@ -1008,6 +1031,7 @@ throw new RuntimeException("Unexpected shift type: " + offset.getShiftType()); } + break; case PcRelative: case RegisterShiftedRegister: @@ -1015,7 +1039,11 @@ throw new RuntimeException("Unexpected operand type: " + offset.getType()); } - + + if (positiveOffset) + return base + addrOffset; + else + return base - addrOffset; } public void execute() { 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-20 22:15:52 UTC (rev 77) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-04-20 22:55:52 UTC (rev 78) @@ -9,6 +9,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.loader.elf.ELF_Loader; import org.binarytranslator.generic.os.process.ProcessSpace; public class ARM_LinuxProcessSpace extends ARM_ProcessSpace implements @@ -51,13 +52,13 @@ this.brk = brk; // initialize the stack - int[] auxVector = { LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, - 0xffffe400, LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, - 0xffffe000, LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, - 0x78bfbff, LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, + int[] auxVector = {//LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO, 0xffffe400, + //LinuxStackInitializer.AuxiliaryVectorType.AT_SYSINFO_EHDR, 0xffffe000, + LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x78bfbff, + LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x64, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, 0xBADADD8E, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0xBAD2BAD2, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, ((ELF_Loader)loader).getProgramHeaderAddress(), + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, ((ELF_Loader)loader).elfHeader.getNumberOfProgramSegmentHeaders(), LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, pc, @@ -68,9 +69,10 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_EGID, DBT_Options.GID, LinuxStackInitializer.AuxiliaryVectorType.AT_SECURE, 0, - LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0 }; + //LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, LinuxStackInitializer.AuxiliaryVectorType.STACK_TOP - getPlatformString().length, + LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0}; - LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector); + registers.set(ARM_Registers.SP, LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector)); } public int getBrk() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-22 17:03:26
|
Revision: 81 http://svn.sourceforge.net/pearcolator/?rev=81&view=rev Author: michael_baer Date: 2007-04-22 10:03:27 -0700 (Sun, 22 Apr 2007) Log Message: ----------- Added support for the ARM Angel semihosting system calls. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java Added Paths: ----------- src/org/binarytranslator/arch/arm/os/abi/semihosting/ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-22 10:26:02 UTC (rev 80) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-04-22 17:03:27 UTC (rev 81) @@ -219,13 +219,20 @@ String address = "[r" + instr.getRn(); if (instr.preIndexing()) { - address += ", "; - if (!instr.positiveOffset()) - address += '-'; + OperandWrapper offset = instr.getOffset(); + if (offset.getType() != OperandWrapper.Type.Immediate || offset.getImmediate() != 0) { + + address += ", "; + + if (!instr.positiveOffset()) + address += '-'; + + address += operand(instr.getOffset()); + } + + address += ']'; - address += operand(instr.getOffset()) + ']'; - if (instr.writeBack()) address += '!'; } else { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-22 10:26:02 UTC (rev 80) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-04-22 17:03:27 UTC (rev 81) @@ -4,8 +4,8 @@ /** * In the ARM decoder model, the decoding and usage (translating/interpreting/disassembling) of instructions - * is strictly separated. This class provides a namespace for all decoder classes. A decoder works like a - * mask than can be put upon a binary instruction to look at the different fields within that instruction. + * is separated. This class provides a namespace for all decoder classes. A decoder works like a + * mask that can be put upon a binary instruction to look at the different fields within that instruction. * * Application might derive from these decoders to implement instruction-specific functionality. * Then, implement a version of the generic {@link ARM_InstructionFactory} interface, which returns Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-22 10:26:02 UTC (rev 80) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-22 17:03:27 UTC (rev 81) @@ -292,7 +292,13 @@ case Register: shifterCarryOut = regs.isCarrySet(); - return regs.get(operand2.getRegister()); + int reg = operand2.getRegister(); + + //mind the arm pc offset + if (reg == 15) + return regs.get(reg) + 8; + else + return regs.get(operand2.getRegister()); case RegisterShiftedRegister: case ImmediateShiftedRegister: @@ -1152,7 +1158,22 @@ return Condition.AL; } } + + private class DebugNopInstruction implements ARM_Instruction { + public Condition getCondition() { + return Condition.AL; + } + + public void execute() { + } + + public int getSuccessor(int pc) { + return pc+4; + } + + } + /** This class will create instances of the different interpreter instructions. It is being "controlled" by * the ARM_InstructionDecoder, which uses an abstract factory pattern to decode an instruction. */ private class InterpreterFactory implements @@ -1218,20 +1239,23 @@ public ARM_Instruction createCoprocessorDataProcessing(int instr) { //TODO: Implement coprocessor instructions - throw new RuntimeException( - "Coprocessor instructions are not yet supported."); + /*throw new RuntimeException( + "Coprocessor instructions are not yet supported.");*/ + return new DebugNopInstruction(); } public ARM_Instruction createCoprocessorDataTransfer(int instr) { // TODO: Implement coprocessor instructions - throw new RuntimeException( - "Coprocessor instructions are not yet supported."); + /*throw new RuntimeException( + "Coprocessor instructions are not yet supported.");*/ + return new DebugNopInstruction(); } public ARM_Instruction createCoprocessorRegisterTransfer(int instr) { // TODO: Implement coprocessor instructions - throw new RuntimeException( - "Coprocessor instructions are not yet supported."); + /*throw new RuntimeException( + "Coprocessor instructions are not yet supported.");*/ + return new DebugNopInstruction(); } public ARM_Instruction createIntMultiply(int instr) { Modified: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-22 10:26:02 UTC (rev 80) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-04-22 17:03:27 UTC (rev 81) @@ -21,6 +21,7 @@ systemCallTable[90] = new LinuxSystemCalls.SysMmap(); systemCallTable[122] = new LinuxSystemCalls.SysUname(); systemCallTable[146] = new LinuxSystemCalls.SysWriteV(); + systemCallTable[197] = new LinuxSystemCalls.SysFstat64(); systemCallTable[199] = new LinuxSystemCalls.SysGetEUID(); systemCallTable[200] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[201] = new LinuxSystemCalls.SysGetEUID(); Added: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-04-22 17:03:27 UTC (rev 81) @@ -0,0 +1,519 @@ +package org.binarytranslator.arch.arm.os.abi.semihosting; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.io.RandomAccessFile; +import java.util.HashMap; +import java.util.Map; + +import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; + +/** + * ARM Ltd. also defined a standard system call interface called Angel. + * It is usually used in small embedded environments and abstracts a number of basic system functions, + * among them + * + * <ul> + * <li>Character input / output + * <li>File access + * <li>Timer access + * </ul> + * + * This class implements the Angel system calls on Pearcolator. + * + * @author Michael Baer + */ +public class AngelSystemCalls { + + /** Angel calls requesting user input read it from this stream. */ + private final InputStream consoleInput = System.in; + + /** Angels calls that output characters to the console write it to this stream.*/ + private final PrintStream consoleOutput = System.out; + + /** The Processspace that we're operating on. */ + private final ARM_ProcessSpace ps; + + /** A mapping from file handles to open files. */ + private final Map<Integer, RandomAccessFile> files = new HashMap<Integer, RandomAccessFile>(); + + /** The directory in which temporary files are created. Note that the path is expected to end with a path delimiter.*/ + private final static String TEMP_FILE_DIR = "/tmp/"; + + /** The file handle that is distributed with the next call to {@link #addFile(RandomAccessFile)}*/ + private int nextFileHandle = 0; + + /** */ + private AngelSystemCall[] sysCalls; + + public AngelSystemCalls(ARM_ProcessSpace ps) { + this.ps = ps; + sysCalls = new AngelSystemCall[0x31]; + + sysCalls[0x1] = new Sys_Open(); + sysCalls[0x2] = new Sys_Close(); + sysCalls[0x3] = new Sys_WriteC(); + sysCalls[0x4] = new Sys_Write0(); + sysCalls[0x5] = new Sys_Write(); + sysCalls[0x6] = new Sys_Read(); + sysCalls[0x7] = new Sys_ReadC(); + sysCalls[0x8] = new Sys_IsError(); + sysCalls[0x9] = new Sys_IsTty(); + sysCalls[0xA] = new Sys_Seek(); + sysCalls[0xB] = null; //Angel docs don't say what this call is supposed to be... + sysCalls[0xC] = new Sys_Flen(); + sysCalls[0xD] = new Sys_TmpNam(); + sysCalls[0xE] = new Sys_Remove(); + sysCalls[0xF] = new Sys_Rename(); + sysCalls[0x10] = new Sys_Clock(); + sysCalls[0x11] = new Sys_Time(); + sysCalls[0x12] = new Sys_System(); + sysCalls[0x13] = new Sys_Errno(); + sysCalls[0x14] = null; //Another undefined call + sysCalls[0x15] = new Sys_Get_CmdLine(); + sysCalls[0x16] = new Sys_HeapInfo(); + sysCalls[0x30] = new Sys_Elapsed(); + sysCalls[0x31] = new Sys_TickFreq(); + } + + public void doSysCall(int callNum) { + try { + sysCalls[callNum].execute(); + } + catch (NullPointerException e) { + throw new RuntimeException("Not implemented angel call number: " + callNum); + } + catch (ArrayIndexOutOfBoundsException e) { + throw new RuntimeException("Invalid angel call number: " + callNum); + } + } + + /** Add a file to the open file table and return its handle. */ + private int addFile(RandomAccessFile file) { + int handle = nextFileHandle++; + files.put(handle, file); + return handle; + } + + /** Returns the file associated with an open file handle or null, if that file handle does not exist. */ + private RandomAccessFile getFile(int handle) { + return files.get(handle); + } + + private boolean closeFile(int handle) { + try { + RandomAccessFile file = files.get(handle); + file.close(); + return true; + } + catch (Exception e) { + return false; + } + finally { + files.remove(handle); + } + } + + abstract class AngelSystemCall { + public abstract void execute(); + + protected final void setReturn(int value) { + ps.registers.set(0, value); + } + + protected String readString(int ptrBuffer, int length) { + String s = ""; + + for (int i = 0; i < length; i++) { + s += (char)ps.memory.loadUnsigned8(ptrBuffer++); + } + + return s; + } + + protected void writeString(String text, int ptrBuffer) { + for (int i = 0; i < text.length(); i++) { + ps.memory.store8(ptrBuffer++, text.charAt(i)); + } + + ps.memory.store8(ptrBuffer, 0); + } + } + + class Sys_Open extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrBuffer = ps.memory.loadUnsigned8(ptrParamBlock); + int fileMode = ps.memory.loadUnsigned8(ptrParamBlock + 4); + int length = ps.memory.loadUnsigned8(ptrParamBlock + 8); + + String fileName = readString(ptrBuffer, length); + + try { + String openMode = (fileMode >= 4) ? "rw" : "w"; + RandomAccessFile file = new RandomAccessFile(fileName, openMode); + + //return the file's index within this table as a file handle + setReturn(addFile(file)); + + } catch (FileNotFoundException e) { + + //return with an error + setReturn(-1); + } + } + } + + class Sys_Close extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + + setReturn(closeFile(fileHandle) ? 0 : -1); + } + } + + class Sys_WriteC extends AngelSystemCall { + + @Override + public void execute() { + int ptrCharToOutput = ps.registers.get(1); + char output = (char)ps.memory.loadUnsigned8(ptrCharToOutput); + consoleOutput.print(output); + } + } + + class Sys_Write0 extends AngelSystemCall { + + @Override + public void execute() { + int ptrOutput = ps.registers.get(1); + + char output = (char)ps.memory.loadUnsigned8(ptrOutput++); + + while (output != 0) { + consoleOutput.print(output); + output = (char)ps.memory.loadUnsigned8(ptrOutput++); + } + } + } + + class Sys_Write extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + int ptrBuffer = ps.memory.load32(ptrParamBlock + 4); + int length = ps.memory.load32(ptrParamBlock + 8); + + try { + RandomAccessFile file = getFile(fileHandle); + + while (length != 0) { + file.writeByte(ps.memory.loadUnsigned8(ptrBuffer++)); + length--; + } + } + catch (Exception e) {} + + //return the number of chars that have not been written + setReturn(length); + } + } + + class Sys_Read extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + int ptrBuffer = ps.memory.load32(ptrParamBlock + 4); + int length = ps.memory.load32(ptrParamBlock + 8); + + RandomAccessFile file = getFile(fileHandle); + + //fail with EOF if the handle is invalid. Angel does not provide any facilities to + //notify about an invalid handle + if (file == null) { + setReturn(length); + return; + } + + int leftToRead = length; + while (leftToRead-- != 0) { + try { + ps.memory.store8(ptrBuffer++, file.readByte()); + } + catch (Exception e) { + //did we read any values at all? + if (leftToRead == length) { + setReturn(length); //no, then fail with eof + return; + } + } + } + + setReturn(length + leftToRead); //otherwise return that we partially filled the buffer + } + } + + class Sys_ReadC extends AngelSystemCall { + + @Override + public void execute() { + try { + int value = consoleInput.read(); + + if (value == -1) + throw new RuntimeException("Unable to read further characters from console"); + + setReturn(value); + } + catch (IOException e) { + throw new RuntimeException("Error while reading character from console.", e); + } + } + } + + class Sys_IsError extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int statusWord = ps.memory.load32(ptrParamBlock); + + setReturn(statusWord < 0 ? -1 : 0); + } + } + + class Sys_IsTty extends AngelSystemCall { + + @Override + public void execute() { + + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + + RandomAccessFile file = getFile(fileHandle); + + if (file != null) { + //TODO: Check if the file is an interactive device and return 1 in that case. + setReturn(0); + } + else { + setReturn(-1); + } + } + } + + class Sys_Seek extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + int absolutePosition = ps.memory.load32(ptrParamBlock + 4); + + RandomAccessFile file = getFile(fileHandle); + try { + file.seek(absolutePosition); + setReturn(0); + } catch (Exception e) { + setReturn(-1); + } + } + } + + class Sys_Flen extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int fileHandle = ps.memory.load32(ptrParamBlock); + + RandomAccessFile file = getFile(fileHandle); + + try { + setReturn((int)file.length()); + } + catch (Exception e) { + setReturn(-1); + } + } + } + + class Sys_TmpNam extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrBuffer = ps.memory.load32(ptrParamBlock); + int identifier = ps.memory.load32(ptrParamBlock + 4); + int bufferLength = ps.memory.load32(ptrParamBlock + 8); + + String tmpFile = TEMP_FILE_DIR + "angel_" + identifier + ".tmp"; + + //do we have enough buffer space to write the tmp file? + if (bufferLength < tmpFile.length() + 1) { + setReturn(-1); + return; + } + + //write the name tmpFile to the buffer + writeString(tmpFile, ptrBuffer); + setReturn(0); + } + } + + class Sys_Remove extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrBuffer = ps.memory.load32(ptrParamBlock); + int length = ps.memory.load32(ptrParamBlock + 4); + + String fileName = readString(ptrBuffer, length); + File f = new File(fileName); + + setReturn(f.delete() ? 0 : -1); + } + } + + class Sys_Rename extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrOldFile = ps.memory.load32(ptrParamBlock); + int oldLength = ps.memory.load32(ptrParamBlock + 4); + + int ptrNewFile = ps.memory.load32(ptrParamBlock + 8); + int newLength = ps.memory.load32(ptrParamBlock + 12); + + String oldFile = readString(ptrOldFile, oldLength); + String newFile = readString(ptrNewFile, newLength); + + File f = new File(oldFile); + boolean success = f.renameTo(new File(newFile)); + + setReturn(success ? 0 : -1); + } + } + + class Sys_Clock extends AngelSystemCall { + + private final long startClock = System.currentTimeMillis(); + + @Override + public void execute() { + setReturn((int)(System.currentTimeMillis() - startClock) / 10); + } + } + + class Sys_Time extends AngelSystemCall { + + @Override + public void execute() { + setReturn((int)(System.currentTimeMillis() * 1000)); + } + } + + class Sys_System extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrCommand = ps.memory.load32(ptrParamBlock); + int length = ps.memory.load32(ptrParamBlock + 4); + + String command = readString(ptrCommand, length); + + throw new RuntimeException("ARM Angel is supposed to execute command on host: " + command); + } + } + + class Sys_Errno extends AngelSystemCall { + + @Override + public void execute() { + setReturn(0); + } + } + + class Sys_Get_CmdLine extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + int ptrBuffer = ps.memory.load32(ptrParamBlock); + int length = ps.memory.load32(ptrParamBlock + 4); + + String cmdLine = DBT_Options.executableFile; + + if (cmdLine.contains(" ")) + cmdLine = '"' + cmdLine + '"'; + + for(String s : DBT_Options.executableArguments) { + if (s.contains(" ")) { + s = '"' + s + '"'; + } + + cmdLine += " " + s; + } + + if (length < cmdLine.length() + 1) { + setReturn(-1); + return; + } + + writeString(cmdLine, ptrBuffer); + ps.memory.store32(ptrParamBlock + 4, cmdLine.length() + 1); + setReturn(0); + } + } + + class Sys_HeapInfo extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + + //return that we couldn't calculate any of the requested heap size values + ps.memory.store32(ptrParamBlock, 0); + ps.memory.store32(ptrParamBlock + 4, 0); + ps.memory.store32(ptrParamBlock + 8, 0); + ps.memory.store32(ptrParamBlock + 12, 0); + } + } + + class Sys_Elapsed extends AngelSystemCall { + + @Override + public void execute() { + int ptrParamBlock = ps.registers.get(1); + long elapsedTime = System.nanoTime(); + + ps.memory.store32(ptrParamBlock, (int)elapsedTime); + ps.memory.store32(ptrParamBlock + 4, (int)(elapsedTime >> 32)); + setReturn(0); + } + } + + class Sys_TickFreq extends AngelSystemCall { + + @Override + public void execute() { + setReturn(1000000000); //Return that ticks are measured in nanoseconds + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-30 18:00:11
|
Revision: 100 http://svn.sourceforge.net/pearcolator/?rev=100&view=rev Author: michael_baer Date: 2007-04-30 11:00:12 -0700 (Mon, 30 Apr 2007) Log Message: ----------- - Initial version of an ARM translator Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-04-30 17:59:37 UTC (rev 99) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-04-30 18:00:12 UTC (rev 100) @@ -10,6 +10,8 @@ import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_FieldReference; import org.jikesrvm.classloader.VM_MemberReference; +import org.jikesrvm.classloader.VM_Method; +import org.jikesrvm.classloader.VM_MethodReference; import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.ir.*; @@ -133,6 +135,27 @@ regUsed[r] = true; return new OPT_RegisterOperand(regMap[r], VM_TypeReference.Int); } + + public OPT_RegisterOperand getCarryFlag() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + + public OPT_RegisterOperand getZeroFlag() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + + public OPT_RegisterOperand getNegativeFlag() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + + public OPT_RegisterOperand getOverflowFlag() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + @Override protected OPT_Register[] getUnusedRegisters() { @@ -183,4 +206,41 @@ //ARM_InstructionDecoder.translateInstruction(this, // (ARM_ProcessSpace) ps, (ARM_Laziness) lazy, pc); } + + /** + * Adds code to the current block that will rotate <code>rotatedOperand</code> by + * <code>rotation</code> and stores the rotated integer into <code>result</code>. + * @param result + * The register into which the rotated value is stored. + * @param rotatedOperand + * The operand which is to be rotated. + * @param rotation + * The amount of rotation that is to be applied to the operand. + */ + public void appendRotateRight(OPT_RegisterOperand result, OPT_Operand rotatedOperand, OPT_Operand rotation) { + VM_TypeReference IntegerType = VM_TypeReference + .findOrCreate(Integer.class); + + VM_MethodReference rotateRightMethodRef = VM_MemberReference + .findOrCreate(IntegerType, + VM_Atom.findOrCreateAsciiAtom("rotateRight"), + VM_Atom.findOrCreateAsciiAtom("(II)I")).asMethodReference(); + + VM_Method rotateRightMethod = rotateRightMethodRef.resolve(); + + OPT_Instruction s = Call.create(CALL, null, null, null, null, 2); + OPT_MethodOperand methOp = OPT_MethodOperand + .STATIC(rotateRightMethod); + + Call.setParam(s, 1, rotatedOperand); + Call.setParam(s, 2, rotation); + Call.setResult(s, result); + Call.setGuard(s, new OPT_TrueGuardOperand()); + Call.setMethod(s, methOp); + Call.setAddress(s, new OPT_AddressConstantOperand(rotateRightMethod + .getOffset())); + + appendInstructionToCurrentBlock(s); + } + } Added: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-04-30 18:00:12 UTC (rev 100) @@ -0,0 +1,1730 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.DBT; +import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; +import org.jikesrvm.classloader.VM_Atom; +import org.jikesrvm.classloader.VM_MemberReference; +import org.jikesrvm.classloader.VM_Method; +import org.jikesrvm.classloader.VM_MethodReference; +import org.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.compilers.opt.ir.*; + +/** + */ +public class ARM_Translator implements OPT_Operators { + + /** The process space that we're interpreting.*/ + protected final ARM_ProcessSpace ps; + + protected final ARM2IR arm2ir; + + protected ARM_Laziness lazy; + + protected int pc; + + /** A "quick" pointer to the ARM registers within the process space*/ + protected final ARM_Registers regs = null; + + public ARM_Translator(ARM_ProcessSpace ps, ARM2IR arm2ir) { + this.ps = ps; + this.arm2ir = arm2ir; + } + + + private abstract static class ResolvedOperand { + + protected OPT_Operand value; + + protected ARM_Translator translator; + + public static ResolvedOperand resolveWithShifterCarryOut( + ARM_Translator translator, OperandWrapper operand) { + throw new RuntimeException("Not yet implemented"); + } + + public static OPT_Operand resolve(ARM_Translator translator, + OperandWrapper operand) { + ResolvedOperand result = new ResolvedOperand_WithoutShifterCarryOut( + translator, operand); + return result.getValue(); + } + + public final OPT_Operand getValue() { + return value; + } + + public abstract OPT_Operand getShifterCarryOut(); + + protected OPT_RegisterOperand getTempInt() { + return translator.arm2ir.getTempInt(0); + } + + protected OPT_RegisterOperand getTempValidation() { + return translator.arm2ir.getGenerationContext().temps + .makeTempValidation(); + } + + private static class ResolvedOperand_WithoutShifterCarryOut extends + ResolvedOperand { + + private ResolvedOperand_WithoutShifterCarryOut(ARM_Translator translator, + OperandWrapper operand) { + this.translator = translator; + _resolve(operand); + } + + public OPT_Operand getShifterCarryOut() { + throw new RuntimeException( + "This class does not provide a shifter carry out value."); + } + + private void _resolve(OperandWrapper operand) { + + switch (operand.getType()) { + case Immediate: + value = new OPT_IntConstantOperand(operand.getImmediate()); + return; + + case Register: + int reg = operand.getRegister(); + + if (reg == 15) { + // mind the ARM pc offset + value = new OPT_IntConstantOperand(translator.pc + 8); + return; + } + + value = translator.arm2ir.getRegister(reg); + return; + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + value = resolveShift(operand); + return; + + case PcRelative: + value = new OPT_IntConstantOperand(translator.pc + 8 + + operand.getOffset()); + return; + + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand.getType()); + } + } + + /** + * If the given OperandWrapper involves shifting a register, then this + * function will decoder the shift and set the result of the barrel + * shifter accordingly. + */ + private final OPT_Operand resolveShift(OperandWrapper operand) { + if (DBT.VerifyAssertions) + DBT + ._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister + || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); + + // consider the "usual" ARM program counter offset + OPT_Operand shiftedOperand; + if (operand.getRegister() == 15) + shiftedOperand = new OPT_IntConstantOperand(translator.pc + 8); + else + shiftedOperand = translator.arm2ir.getRegister(operand.getRegister()); + + OPT_Operand shiftAmount; + + if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) { + // the amount of shift is a constant + shiftAmount = new OPT_IntConstantOperand(operand.getShiftAmount()); + } else { + // the amount of shifting is determined by a register + shiftAmount = translator.arm2ir.getRegister(operand + .getShiftingRegister()); + } + + OPT_BasicBlock currentBlock = translator.arm2ir.getCurrentBlock(); + OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); + + OPT_BasicBlock ifBlock; + OPT_BasicBlock elseBlock; + + OPT_RegisterOperand resultRegister = getTempInt(); + + switch (operand.getShiftType()) { + case ASR: + /* + * if (shiftAmout >= 32) { value = shiftedOperand >> 31; else value = + * shiftedOperand >> shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, + new OPT_IntConstantOperand(31))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, shiftAmount)); + + return resultRegister; + + case LSL: + /* + * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand << + * shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + + return resultRegister; + + case LSR: + + /* + * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand >>> + * shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + + return resultRegister; + + case ROR: + /* + * return Integer.rotateRight(value, shiftAmount); + */ + translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); + return resultRegister; + + case RRE: + /* + * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; + * else return resultRegister >> 1; + */ + + // resultRegister = resultRegister >> 1 + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_AND_ACC, resultRegister, new OPT_IntConstantOperand( + 0x80000000))); + + return resultRegister; + + default: + throw new RuntimeException("Unexpected shift type: " + + operand.getShiftType()); + } + } + } + } + + /** All ARM interpreter instructions implement this interface. */ + private interface ARM_Instruction { + /** Returns the condition, under which the given instruction will be executed. */ + Condition getCondition(); + + /** performs the actual translation.*/ + void translate(); + } + + /** All ARM instructions that are supposed to be executed conditionally + * are decorated with this decorator. + * The decorator takes care of checking the individual condition and depending on it, executing the + * instruction (or not). The instruction classes itself do not check any conditions. */ + private final class ConditionalDecorator implements ARM_Instruction { + + protected final ARM_Instruction conditionalInstruction; + + /** Decorates an ARM interpreter instruction, by making it execute conditionally. */ + protected ConditionalDecorator(ARM_Instruction i) { + conditionalInstruction = i; + } + + public void translate() { + throw new RuntimeException("Not yet implemented"); + } + + public Condition getCondition() { + return conditionalInstruction.getCondition(); + } + + /** Return true if the condition required by the conditional instruction is fulfilled, false otherwise.*/ + private boolean isConditionTrue() { + switch (conditionalInstruction.getCondition()) { + case AL: + throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator."); + + case CC: + return !regs.isCarrySet(); + + case CS: + return regs.isCarrySet(); + + case EQ: + return regs.isZeroSet(); + + case GE: + return regs.isNegativeSet() == regs.isOverflowSet(); + + case GT: + return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); + + case HI: + return regs.isCarrySet() && !regs.isZeroSet(); + + case LE: + return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); + + case LS: + return !regs.isCarrySet() || regs.isZeroSet(); + + case LT: + return regs.isNegativeSet() != regs.isOverflowSet(); + + case MI: + return regs.isNegativeSet(); + + case NE: + return !regs.isZeroSet(); + + case NV: + return false; + + case PL: + return !regs.isNegativeSet(); + + case VC: + return !regs.isOverflowSet(); + + case VS: + return regs.isOverflowSet(); + + default: + throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); + } + } + + @Override + public String toString() { + return conditionalInstruction.toString(); + } + } + + /** A base class for all data processing interpreter instructions, including CLZ.*/ + private abstract class DataProcessing extends ARM_Instructions.DataProcessing + implements ARM_Instruction { + + protected DataProcessing(int instr) { + super(instr); + } + + /** Returns the value of operand 1 of the data processing instruction. This is always a register value. */ + protected OPT_Operand resolveOperand1() { + + if (Rn == ARM_Registers.PC) { + return new OPT_IntConstantOperand(pc + 8); + } + + return arm2ir.getRegister(Rn); + } + + /** Returns the value of the rhs-operand of the data processing instruction. */ + protected OPT_Operand resolveOperand2() { + return ResolvedOperand.resolve(ARM_Translator.this, operand2); + } + + /** Returns teh register into which the result of a data processing operation shall be stored. */ + protected OPT_RegisterOperand getResultRegister() { + return arm2ir.getRegister(Rd); + } + + /** Sets the result of an operation. */ + protected void setResult(OPT_RegisterOperand result) { + if (Rd == 15) { + //TODO: This is a jump, handle it accordingly + throw new RuntimeException("Not yet implemented"); + } + } + + public abstract void translate(); + + /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ + protected final void setFlagsForAdd(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + + if (updateConditionCodes) { + if (Rd != 15) { + + //set the carry flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.CARRY_FROM_ADD(), new OPT_BranchProfileOperand())); + + //set the overflow flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } + else { + //TODO: Implement this + regs.restoreSPSR2CPSR(); + throw new RuntimeException("Not yet implemented"); + } + } + } + + /** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/ + protected final void setFlagsForSub(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + + if (updateConditionCodes) { + if (Rd != 15) { + //set the carry flag to not(Borrow) + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); + + //set the overflow flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } + else { + //TODO: Implement this + regs.restoreSPSR2CPSR(); + throw new RuntimeException("Not yet implemented"); + } + } + } + + public int getSuccessor(int pc) { + if (Rd != 15) + return pc + 4; + else + return -1; + } + } + + private abstract class DataProcessing_Logical extends DataProcessing { + + /** Most data processing instructions may set the carry flag according to the barrel shifter's carry + * out value. The (supposed) value of the barrel shifter is stored within this variable. */ + protected OPT_Operand shifterCarryOut; + + protected DataProcessing_Logical(int instr) { + super(instr); + } + + /** + * Returns the value of the rhs-operand of the data processing instruction. + * This function also retrieves a value for the shifter carry out, which may be set when resolving + * the 2nd operand.*/ + protected OPT_Operand resolveOperand2() { + ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveWithShifterCarryOut(ARM_Translator.this, operand2); + shifterCarryOut = resolvedOperand2.getShifterCarryOut(); + return resolvedOperand2.getValue(); + } + + /** Sets the condition field for logical operations. */ + protected final void setFlagsForLogicalOperator(OPT_Operand result) { + + if (updateConditionCodes) { + if (Rd != 15) { + //TODO: Find an equivalent for BOOLEAN_MOVE + arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), shifterCarryOut)); + arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + + } else { + //TODO: Implement this + regs.restoreSPSR2CPSR(); + throw new RuntimeException("Not yet implemented"); + } + } + } + } + + /** Binary and. <code>Rd = op1 & op2 </code>.*/ + private final class DataProcessing_And extends DataProcessing_Logical { + + protected DataProcessing_And(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, resolveOperand1(), resolveOperand2())); + + setFlagsForLogicalOperator(result); + setResult(result); + } + } + + /** Exclusive or. <code>Rd = op1 ^ op2 </code>.*/ + private final class DataProcessing_Eor extends DataProcessing_Logical { + + protected DataProcessing_Eor(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_XOR, result, resolveOperand1(), resolveOperand2())); + + setFlagsForLogicalOperator(result); + setResult(result); + } + } + + /** Add. <code>Rd = op1 + op2 </code>.*/ + private final class DataProcessing_Add extends DataProcessing { + + public DataProcessing_Add(int instr) { + super(instr); + } + + public void translate() { + + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); + + setFlagsForAdd(result, operand1, operand2); + setResult(result); + } + } + + /** Subtract. <code>Rd = op1 - op2 </code>.*/ + private final class DataProcessing_Sub extends DataProcessing { + + public DataProcessing_Sub(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); + + setFlagsForSub(result, operand1, operand2); + setResult(result); + } + } + + /** Reverse subtract. <code>Rd = op2 - op1</code>.*/ + private final class DataProcessing_Rsb extends DataProcessing { + + protected DataProcessing_Rsb(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand2, operand1)); + + setFlagsForSub(result, operand2, operand1); + setResult(result); + } + } + + /** Add with carry. <code>Rd = op1 + op2 + CARRY</code>. + * If the carry flag is set, the instruction will add 1 to one of the operands (whichever operands would + * not cause an overflow). Then, the normal add-routine is being invoked. */ + private final class DataProcessing_Adc extends DataProcessing { + + protected DataProcessing_Adc(int instr) { + super(instr); + } + + @Override + public void translate() { + + throw new RuntimeException("Not yet implemented"); + + /* + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + OPT_RegisterOperand long_op1 = arm2ir.getTempLong(0); + OPT_RegisterOperand long_op2 = arm2ir.getTempLong(1); + OPT_RegisterOperand long_result = arm2ir.getTempLong(2); + OPT_RegisterOperand long_tmp = arm2ir.getTempLong(3); + + //convert the operands to longs. Be careful to treat them as unsigned ints during the conversion + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, long_op1, operand1)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_op1, long_op1, new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, long_op2, operand2)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_op2, long_op2, new OPT_LongConstantOperand(0xFFFFFFFF))); + + //perform the actual addition + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_ADD, long_result, long_op1, long_op2)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_ADD, long_result, long_result, new OPT_LongConstantOperand(1))); + arm2ir.appendInstructionToCurrentBlock(Unary.create(LONG_2INT, result, long_result)); + + //set the carry flag if the upper 32 bit of the result are != 0 + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_tmp, long_result, new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), long_tmp, new OPT_LongConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), OPT_BranchProfileOperand.unlikely())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + + //commit the result + setResult(result);*/ + } + } + + /** Subtract with carry. <code>Rd = op1 - op2 + CARRY</code>.*/ + private class DataProcessing_Sbc extends DataProcessing { + + protected DataProcessing_Sbc(int instr) { + super(instr); + } + + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + + /* + if (!regs.isCarrySet()) { + if (operand1 != Integer.MIN_VALUE) { + operand1--; + } else if (operand2 != Integer.MIN_VALUE) { + operand2--; + } else { + //TODO: Remove this exception, when the correct behavior has been verified. + throw new RuntimeException("I'm interested in finding a case where this occurs, so this exception is sooner or later going to 'notify' me.."); + //regs.setFlags(operand1 > 0, operand1 != 0, true, true); + //return; + } + } + + int result = operand1 - operand2; + + regs.set(Rd, result); + setFlagsForSub(operand1, operand2);*/ + } + } + + /** Reserve subtract with carry. <code>Rd = -op1 + op2 + CARRY</code>.*/ + private final class DataProcessing_Rsc extends DataProcessing_Sbc { + + protected DataProcessing_Rsc(int instr) { + super(instr); + } + + @Override + protected OPT_Operand resolveOperand1() { + return super.resolveOperand2(); + } + + @Override + protected OPT_Operand resolveOperand2() { + return super.resolveOperand1(); + } + } + + /** Set the flags according to the logical-and of two values. + * <code>Flags = op1 & op2</code>*/ + private final class DataProcessing_Tst extends DataProcessing_Logical { + + protected DataProcessing_Tst(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, resolveOperand1(), resolveOperand2())); + setFlagsForLogicalOperator(result); + } + } + + /** Sets the flags according to the exclusive-or of two values. + * <code>Flags = op1 ^ op2</code> */ + private final class DataProcessing_Teq extends DataProcessing_Logical { + + protected DataProcessing_Teq(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_XOR, result, resolveOperand1(), resolveOperand2())); + setFlagsForLogicalOperator(result); + } + } + + /** Set the flags according to the comparison of two values. + * <code>Flags = op1 - op2</code> */ + private final class DataProcessing_Cmp extends DataProcessing { + + protected DataProcessing_Cmp(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); + setFlagsForSub(result, operand1, operand2); + } + } + + /** Set the flags according to the comparison of two values, negating the 2nd value on the way. + * <code>Flags = op1 + op2</code>. */ + private final class DataProcessing_Cmn extends DataProcessing { + + protected DataProcessing_Cmn(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); + setFlagsForAdd(result, operand1, operand2); + } + } + + /** Binary or. <code>Rd = op1 | op2</code>. */ + private final class DataProcessing_Orr extends DataProcessing_Logical { + + protected DataProcessing_Orr(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_OR, result, operand1, operand2)); + setFlagsForLogicalOperator(result); + setResult(result); + } + } + + private final class DataProcessing_Mov extends DataProcessing_Logical { + + protected DataProcessing_Mov(int instr) { + super(instr); + } + + @Override + /** Moves a value into a register .*/ + public void translate() { + OPT_Operand operand = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand)); + + setResult(result); + setFlagsForLogicalOperator(result); + } + } + + /** Bit clear. Clear bits in a register by a mask given by a second operand. + * <code>Rd = op1 & (~op2)</code>.*/ + private final class DataProcessing_Bic extends DataProcessing_Logical { + + protected DataProcessing_Bic(int instr) { + super(instr); + } + + @Override + /** Clear bits in a register by a mask given by a second operand. */ + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_NOT, tmp, operand2)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, operand1, tmp)); + setFlagsForLogicalOperator(result); + setResult(result); + } + } + + /** Move and negate. Moves an integer between two registers, negating it on the way. + * <code>Rd = -op2</code>.*/ + private final class DataProcessing_Mvn extends DataProcessing_Logical { + + protected DataProcessing_Mvn(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_RegisterOperand result = getResultRegister(); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_NOT, result, resolveOperand2())); + setFlagsForLogicalOperator(result); + } + } + + /** Count the number of leading zeros in an integer. + * <code>Rd = Number_Of_Leading_Zeroes(op2) </code> */ + private final class DataProcessing_Clz extends DataProcessing { + + protected DataProcessing_Clz(int instr) { + super(instr); + } + + @Override + public void translate() { + + OPT_RegisterOperand result = getResultRegister(); + + VM_TypeReference IntegerType = VM_TypeReference + .findOrCreate(Integer.class); + + VM_MethodReference clzMethodRef = VM_MemberReference + .findOrCreate(IntegerType, + VM_Atom.findOrCreateAsciiAtom("numberOfLeadingZeros"), + VM_Atom.findOrCreateAsciiAtom("(I)I")).asMethodReference(); + + VM_Method clzMethod = clzMethodRef.resolve(); + + OPT_Instruction s = Call.create(CALL, null, null, null, null, 1); + OPT_MethodOperand methOp = OPT_MethodOperand.STATIC(clzMethod); + + Call.setParam(s, 1, resolveOperand2()); + Call.setResult(s, result); + Call.setGuard(s, new OPT_TrueGuardOperand()); + Call.setMethod(s, methOp); + Call.setAddress(s, new OPT_AddressConstantOperand(clzMethod + .getOffset())); + + arm2ir.appendInstructionToCurrentBlock(s); + setResult(result); + } + } + + /** Swap a register and a memory value. + * TODO: At the moment, Pearcolator does not support any way of locking the memory. However, once it does + * any other memory accesses should be pending until the swap instruction succeeds.*/ + private final class Swap extends ARM_Instructions.Swap implements + ARM_Instruction { + + public Swap(int instr) { + super(instr); + } + + public void translate() { + OPT_Operand memAddr = arm2ir.getRegister(Rn); + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + OPT_RegisterOperand result = arm2ir.getRegister(Rd); + + //swap exchanges the value of a memory address with the value in a register + if (!swapByte) { + ps.memory.translateLoad32(memAddr, tmp); + ps.memory.translateStore32(memAddr, arm2ir.getRegister(Rm)); + + //according to the ARM architecture reference, the value loaded from a memory address is rotated + //by the number of ones in the first two bits of the address + OPT_RegisterOperand rotation = arm2ir.getTempInt(1); + + //rotation = (memAddr & 0x3) * 8 + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, rotation, memAddr, new OPT_IntConstantOperand(0x3))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHL, rotation, rotation, new OPT_IntConstantOperand(3))); + arm2ir.appendRotateRight(result, tmp, rotation); + } + else { + ps.memory.translateLoadUnsigned8(memAddr, tmp); + ps.memory.translateStore8(memAddr, arm2ir.getRegister(Rm)); + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, tmp)); + } + } + + 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; + } + } + + /** Transfer multiple registers at once between the register bank and the memory. */ + private final class BlockDataTransfer extends ARM_Instructions.MultipleDataTransfer + implements ARM_Instruction { + + /** the lowest address that we're reading a register from / writing a register to */ + private final int registerCount; + + /** An array that contains the registers to be transferd in ascending order. + * The list is delimited by setting the entry after the last register index to -1. + * The PC is not included in this list, if it shall be transferred. */ + private final int[] registersToTransfer = new int[16]; + + /** True if the PC should be transferred to, false otherwise. */ + private final boolean transferPC; + + public BlockDataTransfer(int instr) { + super(instr); + + transferPC = transferRegister(15); + int regCount = 0; + + for (int i = 0; i <= 14; i++) + if (transferRegister(i)) { + registersToTransfer[regCount++] = i; + } + + registersToTransfer[regCount] = -1; + registerCount = regCount; + } + + public void translate() { + //build the address, which generally ignores the last two bits + OPT_RegisterOperand startAddress = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, startAddress, arm2ir.getRegister(baseRegister), new OPT_IntConstantOperand(0xFFFFFFFC))); + + if (!incrementBase) { + if (postIndexing) { + //post-indexing, backward reading + //startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; + OPT_Operand offset = new OPT_IntConstantOperand((registerCount + (transferPC ? 1 : 0)) * 4); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, startAddress, startAddress, offset)); + } else { + //pre-indexing, backward-reading + //startAddress -= (registerCount + (transferPC ? 2 : 1)) * 4 + OPT_Operand offset = new OPT_IntConstantOperand((registerCount + (transferPC ? 2 : 1)) * 4); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, startAddress, startAddress, offset)); + } + } else { + if (postIndexing) { + //post-indexing, forward reading + //startAddress -= 4; + OPT_Operand offset = new OPT_IntConstantOperand(4); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, startAddress, startAddress, offset)); + } else { + //pre-indexing, forward reading + //no need to adjust the start address + } + } + + OPT_RegisterOperand nextAddress = arm2ir.getTempInt(1); + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, nextAddress, startAddress)); + + //TODO: implement + OperatingMode previousMode = ps.registers.getOperatingMode(); + + //if we should transfer the user mode registers... + if (forceUser) { + //... then change the current register map, but do NOT change the current processor mode + ps.registers.switchOperatingMode(OperatingMode.USR); + ps.registers.setOperatingModeWithoutRegisterLayout(previousMode); + + //TODO: implement + throw new RuntimeException("Not yet implemented"); + } + + //are we supposed to load or store multiple registers? + if (isLoad) { + int nextReg = 0; + + while (registersToTransfer[nextReg] != -1) { + //nextAddress += 4; + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); + + OPT_RegisterOperand target = arm2ir.getRegister(registersToTransfer[nextReg++]); + ps.memory.translateLoad32(nextAddress, target); + } + + //if we also transferred the program counter + if (transferPC) { + //nextAddress += 4; + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); + + OPT_RegisterOperand target = arm2ir.getRegister(ARM_Registers.PC); + ps.memory.translateLoad32(nextAddress, target); + + //TODO: Use the first bit of (target) before the following instruction to determine if we should be in thumb mode... + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, target, target, new OPT_IntConstantOperand(0xFFFFFFFE))); + + throw new RuntimeException("Not yet implemented"); + /* + if (forceUser) { + //when we are transferring the PC with a forced-user transfer, then we also want to + //restore the CPSR from the SPSR. + //However, at the moment our register layout is different from our operating mode. + //Therefore, sync both first by switching the operating mode to user (which is what our register layout + //is anyway). + regs.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); + regs.restoreSPSR2CPSR(); + + if (regs.getThumbMode()) + newpc = newpc & 0xFFFFFFFE; + else + newpc = newpc & 0xFFFFFFFC; + + regs.set(ARM_Registers.PC, newpc); + //there is no write-back for this instruction. + return; + } + else { + //shall we switch to thumb mode + regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); + regs.setThumbMode((newpc & 0x1) != 0); + }*/ + } + } else { + int nextReg = 0; + + while (registersToTransfer[nextReg] != -1) { + //nextAddress += 4; + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); + ps.memory.translateStore32(nextAddress, arm2ir.getRegister(registersToTransfer[nextReg++])); + } + + //also transfer the program counter, if requested so + if (transferPC) { + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); + ps.memory.translateStore32(nextAddress, new OPT_IntConstantOperand(pc + 8)); + } + } + + //restore the register layout, if we were transferring the user mode registers + if (forceUser) { + //TODO: Implement.... + ps.registers.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); + ps.registers.switchOperatingMode(previousMode); + } + + if (writeBack) { + OPT_RegisterOperand writeBackTarget = arm2ir.getRegister(baseRegister); + + //write the last address we read from back to a register + if (!incrementBase) { + //backward reading + if (postIndexing) { + //backward reading, post-indexing + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, writeBackTarget, startAddress)); + } + else { + //backward reading, pre-indexing + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, writeBackTarget, startAddress, new OPT_IntConstantOperand(4))); + } + } + else { + //forward reading + if (postIndexing) { + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, writeBackTarget, nextAddress, new OPT_IntConstantOperand(4))); + } + else { + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, writeBackTarget, nextAddress)); + } + } + } + } + + public int getSuccessor(int pc) { + //if we're loading values into the PC, then we can't tell where this instruction will be going + if (isLoad && transferPC) + return -1; + else + return pc + 4; + } + } + + /** Branch to another instruction address. */ + private final class Branch extends ARM_Instructions.Branch implements + ARM_Instruction { + + public Branch(int instr) { + super(instr); + } + + public void translate() { + + //if we're supposed to link, then write the previous address into the link register + if (link) { + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); + } + + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc+8 + getOffset())); + } + + public int getSuccessor(int pc) { + return pc + getOffset() + 8; + } + } + + /** Branch to another instruction address and switch between ARM32 and Thumb code on the way.*/ + private final class BranchExchange extends ARM_Instructions.BranchExchange + implements ARM_Instruction { + + public BranchExchange(int instr) { + super(instr); + } + + public void translate() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + + /* + //remember the previous address + int previousAddress = regs.get(ARM_Registers.PC) + 8; + + //are we supposed to jump to thumb (thumb=true) or ARM32 (thumb=false)? + boolean thumb; + + //the address of the instruction we're jumping to + int targetAddress; + + switch (target.getType()) { + 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; + } + } + } + + /** Multiply two integers into a register, possibly adding the value of a third register on the way. */ + private final class IntMultiply extends ARM_Instructions.IntMultiply implements + ARM_Instruction { + + protected IntMultiply(int instr) { + super(instr); + } + + public void translate() { + //get the two operands + //we don't need to consider that any operand might be the PC, because the ARM + //Ref. manual specifies the usage of the PC has undefined results in this operation + OPT_Operand operand1 = arm2ir.getRegister(Rm); + OPT_Operand operand2 = arm2ir.getRegister(Rs); + OPT_RegisterOperand result = arm2ir.getRegister(Rd); + + //calculate the result + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_MUL, result, operand1, operand2)); + + if (accumulate) { + OPT_Operand operand3 = arm2ir.getRegister(Rn); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, result, operand3)); + } + + if (updateConditionCodes) { + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } + } + + public int getSuccessor(int pc) { + return pc + 4; + } + } + + /** Multiply two longs into a register, possibly adding the value of a third register on the way. */ + private final class LongMultiply extends ARM_Instructions.LongMultiply implements + ARM_Instruction { + + protected LongMultiply(int instr) { + super(instr); + } + + public void translate() { + //get the two operands + //we don't need to consider that any operand might be the PC, because the ARM + //Ref. manual specifies the usage of the PC has undefined results in this operation + + OPT_RegisterOperand operand1 = arm2ir.getTempLong(0); + OPT_RegisterOperand operand2 = arm2ir.getTempLong(1); + OPT_RegisterOperand result = arm2ir.getTempLong(2); + + //fill the two operands + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, operand1, arm2ir.getRegister(Rm))); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, operand2, arm2ir.getRegister(Rs))); + + if (unsigned) { + //treat the original ints as unsigned, so get rid of the signs for the longs + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, operand1, operand1, new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, operand2, operand2, new OPT_LongConstantOperand(0xFFFFFFFF))); + } + + //multiply the two operands + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_MUL, result, operand1, operand2)); + + if (accumulate) { + //treat the accum. value as an unsigned value + OPT_Operand operand3 = arm2ir.getRegister(getRdLow()); + OPT_RegisterOperand tmp = arm2ir.getTempLong(0); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, tmp, operand3)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, tmp, tmp, new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_ADD, result, result, tmp)); + + operand3 = arm2ir.getRegister(getRdHigh()); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, tmp, operand3)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_SHL, tmp, tmp, new OPT_IntConstantOperand(32))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, result, operand3)); + } + + if (updateConditionCodes) { + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_LONG, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_LONG, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } + } + + public int getSuccessor(int pc) { + return pc + 4; + } + } + + /** Move the value of the program status register into a register. */ + private final class MoveFromStatusRegister extends + ARM_Instructions.MoveFromStatusRegister implements + ARM_Instruction { + + public MoveFromStatusRegister(int instr) { + super(instr); + } + + public void translate() { + + throw new RuntimeException("Not yet implemented"); + /* + //do we have to transfer the saved or the current PSR? + if (transferSavedPSR) { + regs.set(Rd, regs.getSPSR()); + } + else { + regs.set(Rd, regs.getCPSR()); + }*/ + } + + public int getSuccessor(int pc) { + //Rd should never be the PC, so we can safely predict the next instruction + return pc + 4; + } + } + + private final class MoveToStatusRegister extends + ARM_Instructions.MoveToStatusRegister implements + ARM_Instruction { + + public MoveToStatusRegister(int instr) { + super(instr); + } + + public void translate() { + + //TODO: implement + throw new RuntimeException("Not yet implemented"); + + /* + //this variable is going to receive the new psr, which we will set + int new_psr = ResolvedOperand.resolve(regs, sourceOperand); + + //are we currently in a privileged mode? + boolean inPrivilegedMode = (regs.getOperatingMode() != ARM_Registers.OperatingMode.USR); + + //this variable receives the psr that we're replacing + int old_psr; + + //get the currect value for old_psr + if (transferSavedPSR) { + //if the current mode does not have a SPSR, then do nothing + if (inPrivilegedMode && regs.getOperatingMode() != ARM_Registers.OperatingMode.SYS) + return; + + old_psr = regs.getSPSR(); + } + else { + old_psr = regs.getCPSR(); + } + */ + + //create a new CPSR value according to what pieces of the CPSR we are actually required to set + /*if (!transferControl || !inPrivilegedMode) { + new_psr &= 0xFFFFFF00; + new_psr |= (old_psr & 0xFF); + } + + if (!transferExtension || !inPrivilegedMode) { + new_psr &= 0xFFFF00FF; + new_psr |= (old_psr & 0xFF00); + } + + if (!transferStatus || !inPrivilegedMode) { + new_psr &= 0xFF00FFFF; + new_psr |= (old_psr & 0xFF0000); + } + + if (!transferFlags) { + new_psr &= 0x00FFFFFF; + new_psr |= (old_psr & 0xFF000000); + } + + if (transferSavedPSR) + regs.setSPSR(new_psr); + else + regs.setCPSR(new_psr);*/ + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + /** Invoke a software interrupt. */ + private final class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt + implements ARM_Instruction { + + public SoftwareInterrupt(int instr) { + super(instr); + } + + public void translate() { + arm2ir.plantSystemCall(lazy, pc); + } + + public int getSuccessor(int pc) { + return -1; + } + } + + /** Transfers a single data item (either a byte, half-byte or word) between a register and memory. + * This operation can either be a load from or a store to memory. */ + private final class SingleDataTransfer extends ARM_Instructions.SingleDataTransfer + implements ARM_Instruction { + + public SingleDataTransfer(int instr) { + super(instr); + } + + /** Resolves the offset, which is (when post-indexing is not used) to be added to the + * base address to create the final address. */ + private OPT_Operand resolveOffset() { + OPT_Operand positiveOffset = ResolvedOperand.resolve(ARM_Translator.this, offset); + + if (this.positiveOffset) { + return positiveOffset; + } + else { + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_NEG, tmp, positiveOffset)); + return tmp; + } + } + + /** Resolves the address of the memory slot, that is involved in the transfer. */ + private OPT_Operand resolveAddress() { + + OPT_Operand base; + + //acquire the base address + if (Rn == 15) + base = new OPT_IntConstantOperand(pc + 8); + else + base = arm2ir.getRegister(Rn); + + //if we are not pre-indexing, then just use the base register for the memory access + if (!preIndexing) + return base; + + //add the offset to the base register + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, base, resolveOffset())); + return tmp; + } + + public void translate() { + //should we simulate a user-mode memory access? If yes, store the current mode and fake a switch + //to user mode. + OperatingMode previousMode = null; + if (forceUserMode) { + //TODO: implement + previousMode = ps.registers.getOperatingMode(); + ps.registers.setOperatingModeWithoutRegisterLayout(ARM_Registers.OperatingMode.USR); + + throw new RuntimeException("Not yet implemented"); + } + + //get the address of the memory, that we're supposed access + OPT_Operand address = resolveAddress(); + + if (isLoad) { + //we are loading a value from memory. Load it into this variable. + OPT_RegisterOperand value = arm2ir.getRegister(Rd); + + switch (size) { + + case Word: + ps.memory.translateLoad32(address, value); + + //according to the ARM reference, the last two bits cause the value to be right-rotated + OPT_RegisterOperand rotation = arm2ir.getTempInt(0); + + //rotation = (address & 0x3) * 8 + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, rotation, address, new OPT_IntConstantOperand(0x3))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHL, rotation, rotation, new OPT_... [truncated message content] |
From: <mic...@us...> - 2007-05-16 18:15:50
|
Revision: 118 http://svn.sourceforge.net/pearcolator/?rev=118&view=rev Author: michael_baer Date: 2007-05-16 11:15:51 -0700 (Wed, 16 May 2007) Log Message: ----------- First ARM DBT version that runs Dhrystone Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-16 18:14:22 UTC (rev 117) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-16 18:15:51 UTC (rev 118) @@ -426,4 +426,20 @@ appendInstructionToCurrentBlock(s); } + protected void appendBitTest(OPT_RegisterOperand target, OPT_Operand wordToTest, OPT_Operand bit) { + if (DBT.VerifyAssertions) DBT._assert(wordToTest != target && bit != target); + + appendInstructionToCurrentBlock(Binary.create(OPT_Operators.INT_SHL, target, new OPT_IntConstantOperand(1), bit)); + appendInstructionToCurrentBlock(Binary.create(OPT_Operators.INT_AND, target, wordToTest, target)); + appendInstructionToCurrentBlock(BooleanCmp.create(OPT_Operators.BOOLEAN_CMP_INT, target, target, new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand())); + } + + protected void appendBitTest(OPT_RegisterOperand target, OPT_Operand wordToTest, int bit) { + if (DBT.VerifyAssertions) DBT._assert(wordToTest != target); + if (DBT.VerifyAssertions) DBT._assert(bit <= 31 && bit >= 0); + + appendInstructionToCurrentBlock(Binary.create(OPT_Operators.INT_AND, target, wordToTest, new OPT_IntConstantOperand(1 << bit))); + appendInstructionToCurrentBlock(BooleanCmp.create(OPT_Operators.BOOLEAN_CMP_INT, target, target, new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand())); + } + } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-16 18:14:22 UTC (rev 117) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-16 18:15:51 UTC (rev 118) @@ -654,7 +654,7 @@ } } - /** Subtract with carry. <code>Rd = op1 - op2 + CARRY</code>.*/ + /** Subtract with carry. <code>Rd = op1 - op2 - NOT(CARRY)</code>.*/ private class DataProcessing_Sbc extends DataProcessing { protected DataProcessing_Sbc(int instr) { @@ -668,8 +668,8 @@ if (!regs.isCarrySet()) { if (operand1 != Integer.MIN_VALUE) { operand1--; - } else if (operand2 != Integer.MIN_VALUE) { - operand2--; + } else if (operand2 != Integer.MAX_VALUE) { + operand2++; } else { //TODO: Remove this exception, when the correct behavior has been verified. throw new RuntimeException("I'm interested in finding a case where this occurs, so this exception is sooner or later going to 'notify' me.."); @@ -686,7 +686,7 @@ } } - /** Reserve subtract with carry. <code>Rd = -op1 + op2 + CARRY</code>.*/ + /** Reserve subtract with carry. <code>Rd = -op1 + op2 - NOT(CARRY)</code>.*/ private final class DataProcessing_Rsc extends DataProcessing_Sbc { protected DataProcessing_Rsc(int instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-16 18:14:22 UTC (rev 117) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-16 18:15:51 UTC (rev 118) @@ -78,8 +78,7 @@ return call; } - - + private abstract static class ResolvedOperand { protected OPT_Operand value; @@ -155,8 +154,7 @@ */ private final OPT_Operand resolveShift(OperandWrapper operand) { if (DBT.VerifyAssertions) - DBT - ._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister + DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); // consider the "usual" ARM program counter offset @@ -173,29 +171,72 @@ shiftAmount = new OPT_IntConstantOperand(operand.getShiftAmount()); } else { // the amount of shifting is determined by a register - shiftAmount = translator.arm2ir.getRegister(operand - .getShiftingRegister()); + shiftAmount = translator.arm2ir.getRegister(operand.getShiftingRegister()); + OPT_RegisterOperand shiftAmountAsByte = translator.arm2ir.getTempInt(7); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, shiftAmountAsByte, shiftAmount, new OPT_IntConstantOperand(0xFF))); + shiftAmount = shiftAmountAsByte; } OPT_RegisterOperand resultRegister = translator.arm2ir.getTempInt(9); + OPT_RegisterOperand validation = translator.arm2ir.getTempValidation(0); + + OPT_BasicBlock nextBlock = translator.arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); + OPT_BasicBlock block1, block2; switch (operand.getShiftType()) { case ASR: /* * shiftedOperand >> shiftAmount; */ + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + //current block + curBlock.deleteNormalOut(); + curBlock.insertOut(block1); + curBlock.insertOut(block2); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + + //block 1 - normal case + translator.arm2ir.setCurrentBlock(block1); + block1.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 2 - shift >= 32 + translator.arm2ir.setCurrentBlock(block2); + block2.insertOut(nextBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHR, resultRegister, shiftedOperand, shiftAmount)); + INT_SHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(31))); + break; - return resultRegister; - case LSL: /* * value = shiftedOperand << shiftAmount; */ - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHL, resultRegister, shiftedOperand, shiftAmount)); - return resultRegister; + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + + //current block + curBlock.deleteNormalOut(); + curBlock.insertOut(block1); + curBlock.insertOut(block2); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + + //block 1 - normal case + translator.arm2ir.setCurrentBlock(block1); + block1.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + + //block 2 - shift >= 32 + translator.arm2ir.setCurrentBlock(block2); + block2.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + break; case LSR: @@ -203,57 +244,63 @@ * value = shiftedOperand >>> shiftAmount; */ - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + + //current block + curBlock.deleteNormalOut(); + curBlock.insertOut(block1); + curBlock.insertOut(block2); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + + //block 1 - normal case + translator.arm2ir.setCurrentBlock(block1); + block1.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 2 - shift >= 32 + translator.arm2ir.setCurrentBlock(block2); + block2.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + break; - return resultRegister; - case ROR: /* * return Integer.rotateRight(value, shiftAmount); */ translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); - return resultRegister; + break; case RRX: /* * result = shiftedOperand >>> 1; * if (regs.isCarrySet()) result |= 0x80000000; */ - - // resultRegister = shiftedOperand >>> 1 - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); - - //conditionally, set resultRegister = resultRegister | 0x80000000; - OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); - OPT_BasicBlock nextBlock = translator.arm2ir.createBlockAfterCurrent(); - OPT_BasicBlock block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - //Current block + // Current block + curBlock.deleteNormalOut(); + curBlock.insertOut(nextBlock); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), - new OPT_IntConstantOperand(1), OPT_ConditionOperand - .EQUAL(), block1.makeJumpTarget(), - new OPT_BranchProfileOperand())); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand())); //Block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_OR, resultRegister, resultRegister, new OPT_IntConstantOperand(0x80000000))); + break; - translator.arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create( - INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); - - translator.arm2ir.setCurrentBlock(nextBlock); - translator.arm2ir.setNextBlock(translator.arm2ir.createBlockAfterCurrent()); - return resultRegister; - default: throw new RuntimeException("Unexpected shift type: " + operand.getShiftType()); } + + translator.arm2ir.setCurrentBlock(nextBlock); + return resultRegister; } } @@ -337,8 +384,10 @@ shiftAmount = new OPT_IntConstantOperand(operand.getShiftAmount()); } else { // the amount of shifting is determined by a register - shiftAmount = translator.arm2ir.getRegister(operand - .getShiftingRegister()); + shiftAmount = translator.arm2ir.getRegister(operand.getShiftingRegister()); + OPT_RegisterOperand shiftAmountAsByte = translator.arm2ir.getTempInt(7); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, shiftAmountAsByte, shiftAmount, new OPT_IntConstantOperand(0xFF))); + shiftAmount = shiftAmountAsByte; } OPT_RegisterOperand resultRegister = translator.arm2ir.getTempInt(8); @@ -347,136 +396,186 @@ OPT_BasicBlock nextBlock = translator.arm2ir.createBlockAfterCurrent(); OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); - OPT_BasicBlock block1, block2, block3; + OPT_BasicBlock block1, block2, block3, block4, block5, block6; switch (operand.getShiftType()) { case ASR: - /* - * shiftedOperand >> shiftAmount; - * - * if (shiftAmount != 0) { - * shiftAmount = MIN(shiftAmount, 32); - * carry = shiftedOperand[shiftAmount] - * } - */ - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHR, resultRegister, shiftedOperand, shiftAmount)); - + block4 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block3 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); //current block + curBlock.deleteNormalOut(); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + curBlock.insertOut(block4); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block4.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 1 + //block 1 - shift != 0 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 2 + //block 2 - shift < 32 && shift != 0 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, shiftAmount, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount) ); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1)) ); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); - //block 3 + //block 3 - shift >= 32 translator.arm2ir.setCurrentBlock(block3); block3.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, new OPT_IntConstantOperand(32), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 31); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_MUL, resultRegister, getShifterCarryOutTarget(), new OPT_IntConstantOperand(-1)) ); //creates either 0xFFFFFFFF if the bit is set, or 0 otherwise + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); - + //block 4 - shift == 0 + translator.arm2ir.setCurrentBlock(block4); + block4.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case LSL: /* * value = shiftedOperand << shiftAmount; */ - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHL, resultRegister, shiftedOperand, shiftAmount)); - + block6 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block5 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block4 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block3 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); //current block + curBlock.deleteNormalOut(); + curBlock.insertOut(block6); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block6.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 1 + //block 1 - shift != 0 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 2 + //block 2 - Shift != 0 && Shift < 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock( Binary.create(INT_SUB, tmp, new OPT_IntConstantOperand(32), shiftAmount) ); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, tmp, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, tmp, new OPT_IntConstantOperand(32), shiftAmount) ); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); - //block 3 + //block 3 - Shift >= 32 translator.arm2ir.setCurrentBlock(block3); - block3.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock( Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); - + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.EQUAL(), block5.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + block3.insertOut(block4); + block3.insertOut(block5); + + //block 4 - Shift > 32 + translator.arm2ir.setCurrentBlock(block4); + block4.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 5 - Shift == 32 + translator.arm2ir.setCurrentBlock(block5); + block5.insertOut(nextBlock); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 0); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 6 - shift == 0 + translator.arm2ir.setCurrentBlock(block6); + block6.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case LSR: /* * value = shiftedOperand >>> shiftAmount; - */ - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_USHR, resultRegister, shiftedOperand, shiftAmount)); - + block6 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block5 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block4 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block3 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); //current block + curBlock.deleteNormalOut(); + curBlock.insertOut(block6); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block6.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 1 + //block 1 - shift != 0 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 2 + //block 2 - Shift != 0 && Shift < 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, shiftAmount, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1))); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); - //block 3 + //block 3 - Shift >= 32 translator.arm2ir.setCurrentBlock(block3); - block3.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock( Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); - + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.EQUAL(), block5.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + block3.insertOut(block4); + block3.insertOut(block5); + + //block 4 - Shift > 32 + translator.arm2ir.setCurrentBlock(block4); + block4.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 5 - Shift == 32 + translator.arm2ir.setCurrentBlock(block5); + block5.insertOut(nextBlock); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 31); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 6 - shift == 0 + translator.arm2ir.setCurrentBlock(block6); + block6.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case ROR: /* * return Integer.rotateRight(value, shiftAmount); */ - translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); - + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); //current block + curBlock.deleteNormalOut(); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + curBlock.insertOut(block2); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock( Binary.create(INT_SUB, tmp, shiftAmount, new OPT_IntConstantOperand(1)) ); - translator.arm2ir.appendInstructionToCurrentBlock( Binary.create(INT_AND, tmp, shiftAmount, new OPT_IntConstantOperand(0x1F)) ); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, tmp, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1)) ); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, tmp, tmp, new OPT_IntConstantOperand(0x1F)) ); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + //block 2 + translator.arm2ir.setCurrentBlock(block2); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case RRX: @@ -484,30 +583,23 @@ * value = shiftedOperand >>> 1; * if (regs.isCarrySet()) value |= 0x80000000; */ - - // resultRegister = shiftedOperand >>> 1 - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, new OPT_IntConstantOperand(1), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); - - //conditionally, set resultRegister = resultRegister | 0x80000000; block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - //Current block + //Current Block + curBlock.deleteNormalOut(); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), - new OPT_IntConstantOperand(1), OPT_ConditionOperand - .EQUAL(), block1.makeJumpTarget(), - new OPT_BranchProfileOperand())); + curBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand())); //Block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - - translator.arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create( - INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_OR, resultRegister, resultRegister, new OPT_IntConstantOperand(0x80000000))); + //nextBlock + translator.arm2ir.setCurrentBlock(nextBlock); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 0); break; default: @@ -516,7 +608,6 @@ } translator.arm2ir.setCurrentBlock(nextBlock); - translator.arm2ir.setNextBlock( translator.arm2ir.createBlockAfterCurrent() ); return resultRegister; } } @@ -1030,24 +1121,22 @@ OPT_BasicBlock addWithCarry = arm2ir.createBlockAfterCurrentNotInCFG(); //Is the carry set at all? if not, just jump to addWithoutCarry - arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand1)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand())); arm2ir.getCurrentBlock().insertOut(addWithCarry); //Yes, the carry flag is set. Pre-increase the result by one to account for the carry. arm2ir.setCurrentBlock(addWithCarry); - arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_ADD_ACC, result, new OPT_IntConstantOperand(1))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, result, new OPT_IntConstantOperand(1))); addWithCarry.insertOut(addWithoutCarry); //Finally, add the second operands to the result - arm2ir.setCurrentBlock(addWithoutCarry); - arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_ADD_ACC, result, operand2)); - + arm2ir.setCurrentBlock(addWithoutCarry); setAddResult(result, operand1, operand2); } } - /** Subtract with carry. <code>Rd = op1 - op2 + CARRY</code>.*/ + /** Subtract with carry. <code>Rd = op1 - op2 - NOT(CARRY)</code>.*/ private class DataProcessing_Sbc extends DataProcessing { protected DataProcessing_Sbc(int instr) { @@ -1063,24 +1152,22 @@ OPT_BasicBlock subWithCarry = arm2ir.createBlockAfterCurrentNotInCFG(); //Is the carry set? if yes, just jump to subWithoutCarry - arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand1)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), subWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand())); arm2ir.getCurrentBlock().insertOut(subWithCarry); //No, the carry flag is not set. That means, we have to use the carry within the subtraction (weird arm logic). arm2ir.setCurrentBlock(subWithCarry); - arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_SUB_ACC, result, new OPT_IntConstantOperand(1))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, result, new OPT_IntConstantOperand(1))); subWithCarry.insertOut(subWithoutCarry); //Finally, subtract the second operands from the result arm2ir.setCurrentBlock(subWithoutCarry); - arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_SUB_ACC, result, operand2)); - setSubResult(result, operand1, operand2); } } - /** Reserve subtract with carry. <code>Rd = -op1 + op2 + CARRY</code>.*/ + /** Reserve subtract with carry. <code>Rd = -op1 + op2 - NOT(CARRY)</code>.*/ private final class DataProcessing_Rsc extends DataProcessing_Sbc { protected DataProcessing_Rsc(int instr) { Modified: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java 2007-05-16 18:14:22 UTC (rev 117) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java 2007-05-16 18:15:51 UTC (rev 118) @@ -15,7 +15,7 @@ protected ReadableFile openCpuInfo() { String output = ""; - output += "Processor : XScale-IOP80321 rev 2 (v5l)\n"; + output += "Processor : XScale-IOP80321 rev 2 (v5l)\n"; output += "BogoMIPS : 599.65\n"; output += "Features : swp half thumb fastmult edsp\n"; output += "\n"; Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-05-16 18:14:22 UTC (rev 117) +++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-05-16 18:15:51 UTC (rev 118) @@ -143,7 +143,7 @@ private String previousInputLine = null; public void close() { - throw new RuntimeException("The stdin and stdout are not closeable."); + throw new RuntimeException("Stdin and stdout are not closeable."); } public int getLength() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-08-24 17:08:32
|
Revision: 172 http://pearcolator.svn.sourceforge.net/pearcolator/?rev=172&view=rev Author: michael_baer Date: 2007-08-24 10:08:31 -0700 (Fri, 24 Aug 2007) Log Message: ----------- - Fixed a bug where a parameter that is only one char would not be parsed correctly - Fixed a bug that I recently introduced on loads with negative offset and writeback - various smaller fixes Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Options.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-21 16:12:27 UTC (rev 171) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-24 17:08:31 UTC (rev 172) @@ -556,28 +556,13 @@ return super.inlineBranchInstruction(targetPc, jump); case DynamicJumps: - if (jump.type == BranchType.INDIRECT_BRANCH) - return true; - else - return super.inlineBranchInstruction(targetPc, jump); + return jump.type == BranchType.INDIRECT_BRANCH; - case FunctionCalls: - if (jump.type == BranchType.CALL) - return true; - else - return super.inlineBranchInstruction(targetPc, jump); + case DirectBranches: + return jump.type == BranchType.DIRECT_BRANCH; - case FunctionReturns: - if (jump.type == BranchType.CALL) - return true; - else - return super.inlineBranchInstruction(targetPc, jump); - case Functions: - if (jump.type == BranchType.CALL || jump.type == BranchType.RETURN) - return true; - else - return super.inlineBranchInstruction(targetPc, jump); + return jump.type == BranchType.CALL || jump.type == BranchType.RETURN; case All: return true; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-08-21 16:12:27 UTC (rev 171) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-08-24 17:08:31 UTC (rev 172) @@ -248,7 +248,8 @@ if (instr.writeBack()) address += '!'; - } else { + } + else { address += "], "; if (!instr.positiveOffset()) Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-08-21 16:12:27 UTC (rev 171) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-08-24 17:08:31 UTC (rev 172) @@ -368,10 +368,12 @@ <T> T decode(short instr, ARM_InstructionFactory<T> factory) { //bit9==bit10==bit11==1? if ((instr & 0x0E00) == 0x0E00) { - if (Utils.getBit(instr, 8)) + if (Utils.getBit(instr, 8)) { return factory.createSoftwareInterrupt(instr); - else + } + else { return factory.createUndefinedInstruction(instr); + } } return factory.createBranch(instr); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-21 16:12:27 UTC (rev 171) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-24 17:08:31 UTC (rev 172) @@ -11,8 +11,7 @@ NoInlining, Default, Functions, - FunctionCalls, - FunctionReturns, + DirectBranches, DynamicJumps, All, } @@ -40,7 +39,6 @@ /** Sets the memory model that ARM shall use. */ public static MemoryModel memoryModel = MemoryModel.IntAddressed; - public static void parseOption(String key, String value) { if (key.equalsIgnoreCase("optimizeByProfiling")) { optimizeTranslationByProfiling = Boolean.parseBoolean(value); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-21 16:12:27 UTC (rev 171) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-24 17:08:31 UTC (rev 172) @@ -8,7 +8,6 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; -import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_MemberReference; @@ -2205,7 +2204,7 @@ return positiveOffset; } else { - OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + OPT_RegisterOperand tmp = arm2ir.getTempInt(1); arm2ir.appendInstruction(Unary.create(INT_NEG, tmp, positiveOffset)); return tmp.copy(); } @@ -2241,26 +2240,14 @@ } public void translate() { - //should we simulate a user-mode memory access? If yes, store the current mode and fake a switch - //to user mode. - - //stores the current operating mode - OPT_RegisterOperand currentOperatingMode = null; - + //should we simulate a user-mode memory access? If yes, handle this using the interpreter if (i.forceUserMode) { - OPT_Instruction call_getOperatingMode = createCallToRegisters("getOperatingMode", "()A", 0); - currentOperatingMode = arm2ir.getTempOperatingMode(); - - Call.setResult(call_getOperatingMode, currentOperatingMode); - arm2ir.appendCustomCall(call_getOperatingMode); - - OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1); - Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, arm2ir.getTempOperatingMode(OperatingMode.USR)); - - arm2ir.appendCustomCall(call_setOperatingModeWithoutRegisterLayout); + arm2ir.appendInterpretedInstruction(pc, lazy); + arm2ir.appendTraceExit(lazy, arm2ir.getRegister(ARM_Registers.PC)); + return; } - //get the address of the memory, that we're supposed access + //get the address of the memory, that we're supposed to access OPT_Operand address = resolveAddress(); if (i.isLoad) { @@ -2275,10 +2262,6 @@ //according to the ARM reference, the last two bits cause the value to be right-rotated OPT_RegisterOperand rotation = arm2ir.getTempInt(1); - - //make sure that we're not loosing the address due to the shifting - OPT_RegisterOperand adrCopy = arm2ir.getTempInt(0); - arm2ir.appendInstruction(Move.create(INT_MOVE, adrCopy, address.copy())); //rotation = (address & 0x3) * 8 arm2ir.appendInstruction(Binary.create(INT_AND, rotation, address.copy(), new OPT_IntConstantOperand(0x3))); @@ -2299,9 +2282,6 @@ //continue with the remainder of the instruction arm2ir.setCurrentBlock(remainderBlock); - - //allow further usage of the memory address - address = adrCopy; break; case HalfWord: @@ -2345,13 +2325,6 @@ throw new RuntimeException("Unexpected memory size: " + i.size); } } - - //if we were writing in user mode, then switch back to our previous operating mode - if (i.forceUserMode) { - OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1); - Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, currentOperatingMode); - arm2ir.appendCustomCall(call_setOperatingModeWithoutRegisterLayout); - } //should the memory address, which we accessed, be written back into a register? //This is used for continuous memory accesses Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-21 16:12:27 UTC (rev 171) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-24 17:08:31 UTC (rev 172) @@ -58,7 +58,6 @@ if (registers.getThumbMode()) { int instrAddr = getCurrentInstructionAddress() & 0xFFFFFFFE; - System.out.println("Thumb syscall at: " + instrAddr); short instruction = (short)memory.loadInstruction16(instrAddr); instr = ARM_InstructionDecoder.Thumb.decode(instruction); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-11 17:38:06
|
Revision: 113 http://svn.sourceforge.net/pearcolator/?rev=113&view=rev Author: michael_baer Date: 2007-05-11 10:38:08 -0700 (Fri, 11 May 2007) Log Message: ----------- - Loads of bugfixes concerning the ARM DBT Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-11 17:37:08 UTC (rev 112) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-11 17:38:08 UTC (rev 113) @@ -209,6 +209,7 @@ //first resolve the current lazy state (i.e. calculate the values of registers that are not yet resolved) resolveLaziness(lazyState); + spillAllFlags(); } private void spillAllFlags() { @@ -236,6 +237,13 @@ //get an operand that contains a reference to the current ps.registers field. OPT_RegisterOperand ps_registersOp = getArmRegistersReference(); + + if (carryFlag == null) { + carryFlag = gc.temps.getReg(VM_TypeReference.Boolean); + negativeFlag = gc.temps.getReg(VM_TypeReference.Boolean); + zeroFlag = gc.temps.getReg(VM_TypeReference.Boolean); + overflowFlag = gc.temps.getReg(VM_TypeReference.Boolean); + } //get the carry flag OPT_RegisterOperand flag = new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); @@ -364,12 +372,34 @@ @Override protected int translateInstruction(Laziness lazy, int pc) { System.out.println("Translating address: 0x" + Integer.toHexString(pc)); - System.out.println("Instruction: " + ARM_Disassembler.disassemble(pc, ps)); + System.out.println("Instruction: " + ARM_Disassembler.disassemble(pc, ps).asString()); - return translator.translateInstruction(pc, (ARM_Laziness)lazy); + OPT_BasicBlock curBlock = getCurrentBlock(); + + int nextAddr = translator.translateInstruction(pc, (ARM_Laziness)lazy); + + if (nextAddr == -1) { + printNextBlocks(curBlock, 5); + } + + return nextAddr; } /** + * Prints the given BasicBlock and the <code>count</code> blocks following it in code order. + * @param block + * @param count + */ + private void printNextBlocks(OPT_BasicBlock block, int count) { + do + { + block.printExtended(); + block = block.nextBasicBlockInCodeOrder(); + } + while (block != null && count-- > 0); + } + + /** * Adds code to the current block that will rotate <code>rotatedOperand</code> by * <code>rotation</code> and stores the rotated integer into <code>result</code>. * @param result @@ -394,8 +424,8 @@ OPT_MethodOperand methOp = OPT_MethodOperand .STATIC(rotateRightMethod); - Call.setParam(s, 1, rotatedOperand); - Call.setParam(s, 2, rotation); + Call.setParam(s, 0, rotatedOperand); + Call.setParam(s, 1, rotation); Call.setResult(s, result); Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-05-11 17:37:08 UTC (rev 112) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-05-11 17:38:08 UTC (rev 113) @@ -84,6 +84,11 @@ public String asString() { return instruction; } + + @Override + public String toString() { + return asString(); + } /** @see DisassembledInstruction#getSuccessor(int) */ public int getSuccessor(int pc) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-11 17:37:08 UTC (rev 112) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-11 17:38:08 UTC (rev 113) @@ -107,12 +107,7 @@ protected OPT_RegisterOperand getTempInt() { return translator.arm2ir.getTempInt(0); } - - protected OPT_RegisterOperand getTempValidation() { - return translator.arm2ir.getGenerationContext().temps - .makeTempValidation(); - } - + private static class ResolvedOperand_WithoutShifterCarryOut extends ResolvedOperand { @@ -243,7 +238,7 @@ //Current block curBlock.insertOut(block1); translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, getTempValidation(), translator.arm2ir.getCarryFlag(), + INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand .EQUAL(), block1.makeJumpTarget(), new OPT_BranchProfileOperand())); @@ -361,8 +356,7 @@ OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); OPT_BasicBlock block1, block2, block3; - OPT_RegisterOperand validation1 = translator.arm2ir.getTempValidation(9); - OPT_RegisterOperand validation2 = translator.arm2ir.getTempValidation(8); + OPT_RegisterOperand validation = translator.arm2ir.getTempValidation(0); OPT_RegisterOperand tmp = translator.arm2ir.getTempInt(9); @@ -385,13 +379,13 @@ //current block curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation2, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 2 translator.arm2ir.setCurrentBlock(block2); @@ -419,13 +413,13 @@ //current block curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation2, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 2 translator.arm2ir.setCurrentBlock(block2); @@ -455,13 +449,13 @@ //current block curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation2, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 2 translator.arm2ir.setCurrentBlock(block2); @@ -485,7 +479,7 @@ //current block curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); @@ -513,7 +507,7 @@ //Current block curBlock.insertOut(block1); translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, getTempValidation(), translator.arm2ir.getCarryFlag(), + INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand .EQUAL(), block1.makeJumpTarget(), new OPT_BranchProfileOperand())); @@ -537,22 +531,6 @@ return resultRegister; } } - - - - - - - - - - - - - - - - } /** All ARM interpreter instructions implement this interface. */ @@ -591,11 +569,21 @@ public void translate() { //conditionals are implemented easily: if the condition does not hold, then just //jump to the block following the conditional instruction - OPT_BasicBlock nextInstruction = arm2ir.getNextBlock(); + OPT_BasicBlock nextInstruction; + OPT_BasicBlock condBlock; + + if (getSuccessor(pc) != -1) { + nextInstruction = arm2ir.getNextBlock(); + condBlock = arm2ir.createBlockAfterCurrent(); + condBlock.insertOut(nextInstruction); + } + else { + nextInstruction = arm2ir.createBlockAfterCurrent(); + condBlock = arm2ir.createBlockAfterCurrent(); + } + arm2ir.getCurrentBlock().insertOut(nextInstruction); - OPT_BasicBlock currentInstruction = arm2ir.createBlockAfterCurrent(); - switch (conditionalInstruction.getCondition()) { case AL: throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator."); @@ -675,7 +663,13 @@ throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); } - arm2ir.setCurrentBlock(currentInstruction); + arm2ir.setCurrentBlock(condBlock); + conditionalInstruction.translate(); + + if (getSuccessor(pc) == -1) { + arm2ir.setCurrentBlock(nextInstruction); + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc+4)); + } } private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand operand, OPT_ConditionOperand condition) { @@ -685,31 +679,31 @@ private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand lhs, OPT_ConditionOperand condition, OPT_Operand rhs) { condition = condition.flipCode(); - arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(9), lhs, rhs, condition, nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), lhs, rhs, condition, nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_HI(OPT_BasicBlock nextInstruction) { //return regs.isCarrySet() && !regs.isZeroSet(); OPT_Operand carry = arm2ir.getCarryFlag(); OPT_Operand zero = arm2ir.getCarryFlag(); - OPT_RegisterOperand result = arm2ir.getTempValidation(9); + OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, carry, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_LS(OPT_BasicBlock nextInstruction) { //return !regs.isCarrySet() || regs.isZeroSet(); OPT_Operand carry = arm2ir.getCarryFlag(); OPT_Operand zero = arm2ir.getCarryFlag(); - OPT_RegisterOperand result = arm2ir.getTempValidation(9); + OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, carry, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_GT(OPT_BasicBlock nextInstruction) { @@ -717,12 +711,12 @@ OPT_Operand negative = arm2ir.getNegativeFlag(); OPT_Operand overflow = arm2ir.getOverflowFlag(); OPT_Operand zero = arm2ir.getCarryFlag(); - OPT_RegisterOperand result = arm2ir.getTempValidation(9); + OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, negative, overflow, OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_LE(OPT_BasicBlock nextInstruction) { @@ -730,12 +724,12 @@ OPT_Operand negative = arm2ir.getNegativeFlag(); OPT_Operand overflow = arm2ir.getOverflowFlag(); OPT_Operand zero = arm2ir.getCarryFlag(); - OPT_RegisterOperand result = arm2ir.getTempValidation(9); + OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, negative, overflow, OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } @@ -774,7 +768,8 @@ /** Returns the register into which the result of a data processing operation shall be stored. */ protected OPT_RegisterOperand getResultRegister() { - return arm2ir.getRegister(Rd); + //return arm2ir.getRegister(Rd); + return arm2ir.getGenerationContext().temps.makeTempInt(); } public abstract void translate(); @@ -792,6 +787,8 @@ } } + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + if (Rd == 15) arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } @@ -836,6 +833,8 @@ } } + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + if (Rd == 15) arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } @@ -908,6 +907,8 @@ } } + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + if (Rd == 15) arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } @@ -1439,20 +1440,18 @@ //nextAddress += 4; arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); - OPT_RegisterOperand target = arm2ir.getRegister(ARM_Registers.PC); - ps.memory.translateLoad32(nextAddress, target); + OPT_RegisterOperand regPC = arm2ir.getRegister(ARM_Registers.PC); + ps.memory.translateLoad32(nextAddress, regPC); - //TODO: Use the first bit of (target) before the following instruction to determine if we should be in thumb mode... - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, target, target, new OPT_IntConstantOperand(0xFFFFFFFE))); - - throw new RuntimeException("Not yet implemented"); - /* if (forceUser) { //when we are transferring the PC with a forced-user transfer, then we also want to //restore the CPSR from the SPSR. //However, at the moment our register layout is different from our operating mode. //Therefore, sync both first by switching the operating mode to user (which is what our register layout //is anyway). + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + /* regs.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); regs.restoreSPSR2CPSR(); @@ -1463,13 +1462,37 @@ regs.set(ARM_Registers.PC, newpc); //there is no write-back for this instruction. - return; + return;*/ } else { - //shall we switch to thumb mode - regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); - regs.setThumbMode((newpc & 0x1) != 0); - }*/ + //first translate the register write back + translateWriteback(startAddress, nextAddress); + + //shall we switch to thumb mode? + /*OPT_BasicBlock finishInstruction = arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock switchToARMBlock = arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock switchToThumbBlock = arm2ir.createBlockAfterCurrentNotInCFG(); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), regPC, new OPT_IntConstantOperand(1), OPT_ConditionOperand.BIT_TEST(), switchToThumbBlock.makeJumpTarget(), OPT_BranchProfileOperand.never())); + arm2ir.getCurrentBlock().insertOut(switchToThumbBlock); + + //Yes, switch to thumb mode + arm2ir.setCurrentBlock(switchToThumbBlock); + switchToThumbBlock.insertOut(finishInstruction); + OPT_Instruction call_setThumbMode = createCallToRegisters("setThumbMode", "(Z)V", 1); + Call.setParam(call_setThumbMode, 1, new OPT_IntConstantOperand(1)); + arm2ir.appendInstructionToCurrentBlock(call_setThumbMode); + + //No, don't switch to thumb mode + arm2ir.setCurrentBlock(switchToARMBlock); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, regPC, regPC, new OPT_IntConstantOperand(0xFFFFFFFE))); + OPT_Instruction call_setArmMode = createCallToRegisters("setThumbMode", "(Z)V", 1); + Call.setParam(call_setArmMode, 1, new OPT_IntConstantOperand(0)); + arm2ir.appendInstructionToCurrentBlock(call_setArmMode); + + arm2ir.setCurrentBlock(finishInstruction);*/ + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, regPC); + } + return; } } else { int nextReg = 0; @@ -1492,8 +1515,13 @@ //TODO: Implement.... ps.registers.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); ps.registers.switchOperatingMode(previousMode); + throw new RuntimeException("Not yet implemented"); } + translateWriteback(startAddress, nextAddress); + } + + private void translateWriteback(OPT_RegisterOperand startAddress, OPT_RegisterOperand nextAddress) { if (writeBack) { OPT_RegisterOperand writeBackTarget = arm2ir.getRegister(baseRegister); @@ -1520,6 +1548,7 @@ } } } + public int getSuccessor(int pc) { //if we're loading values into the PC, then we can't tell where this instruction will be going @@ -1838,6 +1867,7 @@ public void translate() { arm2ir.plantSystemCall(lazy, pc); + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, arm2ir.getRegister(ARM_Registers.PC)); } public int getSuccessor(int pc) { @@ -1994,6 +2024,11 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, writeBackTarget, address, resolvedOffset)); } } + + if (isLoad && Rd == ARM_Registers.PC) { + //we are actually loading to the program counter here + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, arm2ir.getRegister(Rd)); + } } public int getSuccessor(int pc) { Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-11 17:37:08 UTC (rev 112) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-11 17:38:08 UTC (rev 113) @@ -3,6 +3,7 @@ import java.io.IOException; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.decoder.ARM2IR; +import org.binarytranslator.arch.arm.decoder.ARM_Disassembler; import org.binarytranslator.arch.arm.decoder.ARM_Interpreter; import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; @@ -95,7 +96,7 @@ */ @Uninterruptible public String disassembleInstruction(int pc) { - return "TODO"; + return ARM_Disassembler.disassemble(pc, this).asString(); } /** Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-05-11 17:37:08 UTC (rev 112) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-05-11 17:38:08 UTC (rev 113) @@ -433,4 +433,29 @@ public boolean isNegativeSet() { return flagNegative; } + + /** Returns a string representation of the values in the ARM registers. */ + @Override + public String toString() { + + StringBuilder result = new StringBuilder(); + for (int i = 0; i < regs.length; i++) { + result.append('r'); + result.append(i); + result.append(": x"); + result.append(Integer.toHexString(regs[i])); + result.append(", "); + } + + result.append("C:"); + result.append(flagCarry ? '1' : '0'); + result.append(", Z:"); + result.append(flagZero ? '1' : '0'); + result.append(", N:"); + result.append(flagNegative ? '1' : '0'); + result.append(", O:"); + result.append(flagOverflow ? '1' : '0'); + + return result.toString(); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |