From: <mic...@us...> - 2007-06-14 17:19:15
|
Revision: 132 http://svn.sourceforge.net/pearcolator/?rev=132&view=rev Author: michael_baer Date: 2007-06-14 10:19:16 -0700 (Thu, 14 Jun 2007) Log Message: ----------- Moving further towards Thumb support Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/memory/AutoMappingMemory.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/loader/elf/ELF_File.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/DBT_Options.java 2007-06-14 17:19:16 UTC (rev 132) @@ -70,7 +70,7 @@ /** * Set this to true to translate only one instruction at a time. */ - public static boolean singleInstrTranslation = true; + public static boolean singleInstrTranslation = false; /** * Eliminate unneeded filling of register @@ -126,10 +126,12 @@ public final static int GID = 100; /** Stores the arguments given to the DBT by the user. These are NOT the arguments given to the executable. */ - private final static HashMap<String, String> dbtArguments = new HashMap<String, String>(); + private static HashMap<String, String> dbtArguments = null; /** Read and parse the command line arguments. */ public static void parseArguments(String[] args) { + + dbtArguments = new HashMap<String, String>(); try { ArrayList<String> remainingArguments = new ArrayList<String>(); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-14 17:19:16 UTC (rev 132) @@ -17,6 +17,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.SoftwareInterrupt; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Swap; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -40,11 +41,19 @@ * @return A disassembled ARM instruction. */ public final static DisassembledInstruction disassemble(int address, - ProcessSpace ps) { + ARM_ProcessSpace ps) { - int binaryInstruction = ps.memory.loadInstruction32(address); - Instruction decodedInstruction = ARM_InstructionDecoder.decode(binaryInstruction); + Instruction decodedInstruction; + if ((address & 0x1) == 1) { + short binaryInstruction = (short)ps.memory.loadInstruction16(address & 0xFFFFFFFE); + decodedInstruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction); + } + else { + int binaryInstruction = ps.memory.loadInstruction32(address); + decodedInstruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction); + } + DisassemblingVisitor disassembler = new DisassemblingVisitor(address); decodedInstruction.visit(disassembler); @@ -170,7 +179,7 @@ return String.format("r%d %s #%d", op.getRegister(), op.getShiftType(), op.getShiftAmount()); - case PcRelative: + case RegisterOffset: if (address != -1) return String.format("#0x%x", op.getOffset() + address + 8); else Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-14 17:19:16 UTC (rev 132) @@ -3,312 +3,527 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; /** - * This class decodes an ARM instruction and uses a user-supplied ARM_InstructionFactory to create a class - * that represents the given instruction. + * This class decodes an ARM or Thumb instruction and uses a user-supplied + * ARM_InstructionFactory to create a class that represents the given + * instruction. * - * The decoder first performs a pseudo-switch on bits 27-25 of the instruction. - * For performance reasons, the switch is implemented as an array lookup (using the {@link #prefixDecoders} array), - * with single {@link Decoder} classes implementing the cases. - * - * ARM has a very cluttered opcode map, which is why the decoding process does not look very tidy. - * However, the presented decoded scheme has been derived by producing all possible instructions and then - * letting a data mining tool (specifically: Weka) create a decision tree to decode the single - * instruction classes. This has two implications: - * <ol> - * <li>The decoder is correct (at least, when I didn't introduce any typos), as Weka verified an error rate of 0% for this decision tree.</li> - * <li>The decoder is reasonably fast, considering Weka tries to build a shallow decision tree.</li> + * ARM has a very cluttered opcode map, which is why the decoding process does + * not look very tidy. However, the presented decoded scheme has been derived by + * producing all possible instructions and then letting a data mining tool + * (specifically: Weka) create a decision tree to decode the single instruction + * classes. This has two implications: + * <ol> + * <li>The decoder is correct (at least, if I didn't introduce any typos), as + * Weka verified an error rate of 0% for this decision tree.</li> + * <li>The decoder is reasonably fast, considering Weka tries to build a + * shallow decision tree.</li> * </ol> * * @author Michael Baer - * + * */ public class ARM_InstructionDecoder { - /** - * This table is used to perform a lookup on bits 25-27 of an instruction. - * According to the result of this lookup, the {@link Decoder} instances within this - * array perform the subsequent instruction decoding. */ - private static Decoder[] prefixDecoders = { - new decoder_000(), new decoder_001(), - new decoder_010(), new decoder_011(), - new decoder_100(), new decoder_101(), - new decoder_110(), new decoder_111() - }; - - /** - * This static field caches the default {@link ARM_InstructionFactory} implementation, which is used by {@link #decode(int)}. - * It is being lazily initialized once it is used for the first time. */ + /** + * This static field caches the default {@link ARM_InstructionFactory} + * implementation, which is used by {@link #decode(int)}. It is being + * lazily initialized once it is used for the first time. + */ private static DefaultFactory _defaultFactory; - - /** - * This class performs additional instruction decoding, after bits 25-27 of an instruction have been - * determined. The class is basically just a way of substituting a switch by an array lookup+virtual method call. - * */ - private static abstract class Decoder { - abstract <T> T decode(int instr, ARM_InstructionFactory<T> factory); - } - - /** Decoder which assumes that bits 27-25 == 000. */ - private static class decoder_000 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + /** + * + * The decoder first performs a pseudo-switch on bits 27-25 of the + * instruction. For performance reasons, the switch is implemented as an array + * lookup (using the {@link #prefixDecoders} array), with single + * {@link Decoder} classes implementing the cases. + * + */ + public static class ARM32 { + /** + * This table is used to perform a lookup on bits 25-27 of an instruction. + * According to the result of this lookup, the {@link Decoder} instances + * within this array perform the subsequent instruction decoding. + */ + private static Decoder[] prefixDecoders = { new decoder_000(), + new decoder_001(), new decoder_010(), new decoder_011(), + new decoder_100(), new decoder_101(), new decoder_110(), + new decoder_111() }; + /** + * This class performs additional instruction decoding, after bits 25-27 of + * an instruction have been determined. The class is basically just a way of + * substituting a switch by an array lookup+virtual method call. + */ + private static abstract class Decoder { + abstract <T> T decode(int instr, ARM_InstructionFactory<T> factory); + } + + /** Decoder which assumes that bits 27-25 == 000. */ + private static class decoder_000 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } + + byte bits_7_4 = (byte) Utils.getBits(instr, 4, 7); + + 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 + return factory.createMoveFromStatusRegister(instr); + } + + if (((bits_7_4 & 0xD) == 1) && ((instr & 0x01F00000) == 0x01200000)) { + // bits 7-4 == 1 || bits 7-4 == 3 + // Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false + // && Utils.getBit(instr, 22) == false && Utils.getBit(instr, 21) == + // true && Utils.getBit(instr, 20) == false + return factory.createBranchExchange(instr); + } + + if ((bits_7_4 & 9) == 9) { + // bits7-4 = 1xx1 + if (bits_7_4 == 9) { + if (Utils.getBit(instr, 23)) { + return factory.createLongMultiply(instr); + } else { + if (Utils.getBit(instr, 24)) + return factory.createSwap(instr); + else + return factory.createIntMultiply(instr); + } + } else + return factory.createSingleDataTransfer(instr); + } + + return factory.createDataProcessing(instr); } - - byte bits_7_4 = (byte)Utils.getBits(instr, 4, 7); + } - 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 - return factory.createMoveFromStatusRegister(instr); + /** Decoder which assumes that bits 27-25 == 001. */ + private static class decoder_001 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } + + if (((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 + return factory.createUndefinedInstruction(instr); + } + + return factory.createDataProcessing(instr); } - - if (((bits_7_4 & 0xD) == 1) && ((instr & 0x01F00000) == 0x01200000)) { - //bits 7-4 == 1 || bits 7-4 == 3 - //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 22) == false && Utils.getBit(instr, 21) == true && Utils.getBit(instr, 20) == false - return factory.createBranchExchange(instr); + } + + /** Decoder which assumes that bits 27-25 == 010. */ + private static class decoder_010 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } else { + return factory.createSingleDataTransfer(instr); + } } - - if ((bits_7_4 & 9) == 9) { - //bits7-4 = 1xx1 - if (bits_7_4 == 9) { - if (Utils.getBit(instr, 23)) { - return factory.createLongMultiply(instr); - } - else { - if (Utils.getBit(instr, 24)) - return factory.createSwap(instr); - else - return factory.createIntMultiply(instr); - } + } + + /** Decoder which assumes that bits 27-25 == 011. */ + private static class decoder_011 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? or bit4==true + if ((instr & 0xF0000000) == 0xF0000000 || Utils.getBit(instr, 4)) { + return factory.createUndefinedInstruction(instr); + } else { + return factory.createSingleDataTransfer(instr); } - else - return factory.createSingleDataTransfer(instr); } - - return factory.createDataProcessing(instr); } - } - - /** Decoder which assumes that bits 27-25 == 001. */ - private static class decoder_001 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); - } - - if (((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 + /** Decoder which assumes that bits 27-25 == 100. */ + private static class decoder_100 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { return factory.createUndefinedInstruction(instr); + } + + return factory.createBlockDataTransfer(instr); } - - return factory.createDataProcessing(instr); } - } - - /** Decoder which assumes that bits 27-25 == 010. */ - private static class decoder_010 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + /** Decoder which assumes that bits 27-25 == 101. */ + private static class decoder_101 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createBranchExchange(instr); + } + + return factory.createBranch(instr); } - else { - return factory.createSingleDataTransfer(instr); + } + + /** Decoder which assumes that bits 27-25 == 110. */ + private static class decoder_110 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + return factory.createCoprocessorDataTransfer(instr); } } - } - - /** Decoder which assumes that bits 27-25 == 011. */ - private static class decoder_011 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? or bit4==true - if ((instr & 0xF0000000) == 0xF0000000 || Utils.getBit(instr, 4)) { - return factory.createUndefinedInstruction(instr); + /** Decoder which assumes that bits 27-25 == 111. */ + private static class decoder_111 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 24)) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } else { + return factory.createSoftwareInterrupt(instr); + } + } else { + if (Utils.getBit(instr, 4)) { + return factory.createCoprocessorRegisterTransfer(instr); + } else { + return factory.createCoprocessorDataProcessing(instr); + } + } } - else { - return factory.createSingleDataTransfer(instr); + } + + /** + * Decodes a given ARM instruction and returns an object representation of + * it. + * + * @param instruction + * A binary ARM instruction, that is to be decoded. + * @return A version of the instruction, which has been decoded into an + * instance of {@link Instruction}. Use the + * {@link Instruction#visit(ARM_InstructionVisitor)} method to + * further interact with the returned instance. + */ + public static Instruction decode(int instruction) { + if (_defaultFactory == null) + _defaultFactory = new DefaultFactory(); + + return decode(instruction, _defaultFactory); + } + + public static int fastpathCount = 0; + + /** + * Decodes a binary ARM instruction. This method will use the supplied + * {@link ARM_InstructionFactory} to create an object representation of the + * decoded instruction. + * + * @param <T> + * The return type depends on whatever the + * {@link ARM_InstructionFactory} actually creates. + * @param instruction + * A binary representation of the instruction that is to be + * decoded. + * @param factory + * A factory, that will create object instances of the instruction. + * @return An object representation of the decoded instruction. + */ + static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { + + if (ARM_Options.DATAPROCESSING_DECODER_FASTPATH) { + + // Check condition!=never? + if ((instruction & 0xF0000000) != 0xF0000000) { + + if ((instruction & 0x0F000000) == 0x02000000) { + fastpathCount++; + return factory.createDataProcessing(instruction); + } + } + + int bits_27_25 = Utils.getBits(instruction, 25, 27); + return prefixDecoders[bits_27_25].decode(instruction, factory); + } else { + int bits_27_25 = Utils.getBits(instruction, 25, 27); + return prefixDecoders[bits_27_25].decode(instruction, factory); } } } - /** Decoder which assumes that bits 27-25 == 100. */ - private static class decoder_100 extends Decoder { + /** + * The instruction decoder for Thumb instructions. It works similar to the ARM32 decoder and has + * also been created using the Weka datamining tool. + */ + public static class Thumb { + /** + * This class performs additional instruction decoding, after bits 12-15 of + * an instruction have been determined. The class is basically just a way of + * substituting a switch by an array lookup+virtual method call. + */ + private static abstract class Decoder { + abstract <T> T decode(short instr, ARM_InstructionFactory<T> factory); + } + + /** This table is used to perform a lookup on bits 12-15 of an instruction. + * According to the result of this lookup, the {@link Decoder} instances + * within this array perform the subsequent instruction decoding. + */ + private static Decoder[] prefixDecoders = { + new DataProcessing_Decoder(), new DataProcessing_Decoder(), + new DataProcessing_Decoder(), new DataProcessing_Decoder(), + new Decoder_0100(), new SingleDataTransfer_Decoder(), + new SingleDataTransfer_Decoder(), new SingleDataTransfer_Decoder(), + new SingleDataTransfer_Decoder(), new SingleDataTransfer_Decoder(), + new DataProcessing_Decoder(), new Decoder_1011(), + new BlockDataTransfer_Decoder(), new Decoder_1101(), + new Decoder_1110(), new Decoder_1111()}; + + private static class DataProcessing_Decoder extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + return factory.createDataProcessing(instr); } - - return factory.createBlockDataTransfer(instr); } - } - - /** Decoder which assumes that bits 27-25 == 101. */ - private static class decoder_101 extends Decoder { + + private static class SingleDataTransfer_Decoder extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createBranchExchange(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + return factory.createSingleDataTransfer(instr); } - - return factory.createBranch(instr); } - } - - /** Decoder which assumes that bits 27-25 == 110. */ - private static class decoder_110 extends Decoder { + + private static class BlockDataTransfer_Decoder extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - return factory.createCoprocessorDataTransfer(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + return factory.createBlockDataTransfer(instr); + } } - } - - /** Decoder which assumes that bits 27-25 == 111. */ - private static class decoder_111 extends Decoder { + + private static class Decoder_0100 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - if (Utils.getBit(instr, 24)) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + return factory.createSingleDataTransfer(instr); } else { - return factory.createSoftwareInterrupt(instr); + //bit8==bit9==bit10==1? + if ((instr & 0x70) == 0x70) + return factory.createBranchExchange(instr); + + return factory.createDataProcessing(instr); } } - else { - if (Utils.getBit(instr, 4)) { - return factory.createCoprocessorRegisterTransfer(instr); + } + + private static class Decoder_1011 extends Decoder { + + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 10)) { + return factory.createBlockDataTransfer(instr); } else { - return factory.createCoprocessorDataProcessing(instr); + return factory.createDataProcessing(instr); } } } - } - - /** - * Decodes a given ARM instruction and returns an object representation of it. - * @param instruction - * A binary ARM instruction, that is to be decoded. - * @return - * A version of the instruction, which has been decoded into an instance of {@link Instruction}. - * Use the {@link Instruction#visit(ARM_InstructionVisitor)} method to further interact with the - * returned instance. - */ - public static Instruction decode(int instruction) { - if (_defaultFactory == null) - _defaultFactory = new DefaultFactory(); - return decode(instruction, _defaultFactory); - } + private static class Decoder_1101 extends Decoder { - public static int fastpathCount = 0; - - /** - * Decodes a binary ARM instruction. This method will use the supplied {@link ARM_InstructionFactory} - * to create an object representation of the decoded instruction. - * @param <T> - * The return type depends on whatever the {@link ARM_InstructionFactory} actually creates. - * @param instruction - * A binary representation of the instruction that is to be decoded. - * @param factory - * A factory, that will create object instances of the instruction. - * @return - * An object representation of the decoded instruction. - */ - static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + return factory.createSingleDataTransfer(instr); + } + else { + //bit9==bit10==bit11==1? + if ((instr & 0xE0) == 0xE0) { + if (Utils.getBit(instr, 8)) + return factory.createSoftwareInterrupt(instr); + else + return factory.createUndefinedInstruction(instr); + } + + return factory.createBranch(instr); + } + } + } - if (ARM_Options.DATAPROCESSING_DECODER_FASTPATH) { - - //Check condition!=never? - if ((instruction & 0xF0000000) != 0xF0000000) { + private static class Decoder_1110 extends Decoder { - if ((instruction & 0x0F000000) == 0x02000000) { - fastpathCount++; - return factory.createDataProcessing(instruction); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + if (Utils.getBit(instr, 0)) + return factory.createUndefinedInstruction(instr); + else + return factory.createBranchExchange(instr); } + else { + return factory.createBranch(instr); + } } + } - int bits_27_25 = Utils.getBits(instruction, 25, 27); - return prefixDecoders[bits_27_25].decode(instruction, factory); + private static class Decoder_1111 extends Decoder { + + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + return factory.createBranch(instr); + } + else { + return factory.createDataProcessing(instr); + } + } } - else { - int bits_27_25 = Utils.getBits(instruction, 25, 27); - return prefixDecoders[bits_27_25].decode(instruction, factory); + + /** + * Decodes a binary Thumb instruction. This method will use the supplied + * {@link ARM_InstructionFactory} to create an object representation of the + * decoded instruction. + * + * @param <T> + * The return type depends on whatever the + * {@link ARM_InstructionFactory} actually creates. + * @param instruction + * A binary representation of the instruction that is to be + * decoded. + * @param factory + * A factory, that will create object instances of the instruction. + * @return An object representation of the decoded instruction. + */ + static <T> T decode(short instruction, ARM_InstructionFactory<T> factory) { + + int bits_12_15 = Utils.getBits(instruction, 12, 15); + return prefixDecoders[bits_12_15].decode(instruction, factory); } + + /** + * Decodes a given Thumb instruction and returns an object representation of + * it. + * + * @param instruction + * A binary ARM instruction, that is to be decoded. + * @return A version of the instruction, which has been decoded into an + * instance of {@link Instruction}. Use the + * {@link Instruction#visit(ARM_InstructionVisitor)} method to + * further interact with the returned instance. + */ + public static Instruction decode(short instruction) { + if (_defaultFactory == null) + _defaultFactory = new DefaultFactory(); + + return decode(instruction, _defaultFactory); + } } - + /** - * An interface to a factory class, which will create the actual object representations of the - * instruction classes decoded by {@link ARM_InstructionDecoder}. - * + * An interface to a factory class, which will create the actual object + * representations of the instruction classes decoded by + * {@link ARM_InstructionDecoder}. + * * @param <T> - * The type of the object representations, that shall be created when an ARM instruction is decoded. + * The type of the object representations, that shall be created when + * an ARM instruction is decoded. */ interface ARM_InstructionFactory<T> { T createDataProcessing(int instr); + T createSwap(int instr); + T createSingleDataTransfer(int instr); + T createBlockDataTransfer(int instr); + T createIntMultiply(int instr); + T createLongMultiply(int instr); + T createSoftwareInterrupt(int instr); + T createBranch(int instr); + T createBranchExchange(int instr); + T createCoprocessorDataTransfer(int instr); + T createCoprocessorDataProcessing(int instr); + T createCoprocessorRegisterTransfer(int instr); + T createMoveFromStatusRegister(int instr); + T createMoveToStatusRegister(int instr); + T createUndefinedInstruction(int instr); - + T createDataProcessing(short instr); + T createSwap(short instr); + T createSingleDataTransfer(short instr); + T createBlockDataTransfer(short instr); - T createshortMultiply(short instr); + + T createIntMultiply(short instr); + T createLongMultiply(short instr); - T createSoftwareshorterrupt(short instr); + + T createSoftwareInterrupt(short instr); + T createBranch(short instr); + T createBranchExchange(short instr); + T createCoprocessorDataTransfer(short instr); + T createCoprocessorDataProcessing(short instr); + T createCoprocessorRegisterTransfer(short instr); + T createMoveFromStatusRegister(short instr); + T createMoveToStatusRegister(short instr); + T createUndefinedInstruction(short instr); } - + /** - * A default implementation of the ARM instruction factory, which will create the - * appropriate classes from the {@link ARM_Instructions} namespace. + * A default implementation of the ARM instruction factory, which will create + * the appropriate classes from the {@link ARM_Instructions} namespace. */ - private static class DefaultFactory implements ARM_InstructionFactory<ARM_Instructions.Instruction> { + private static class DefaultFactory implements + ARM_InstructionFactory<ARM_Instructions.Instruction> { public Instruction createBlockDataTransfer(int instr) { return new BlockDataTransfer(instr); @@ -371,79 +586,63 @@ } public Instruction createBlockDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new BlockDataTransfer(instr); } public Instruction createBranch(short instr) { - // TODO Auto-generated method stub - return null; + return new Branch(instr); } public Instruction createBranchExchange(short instr) { - // TODO Auto-generated method stub - return null; + return new BranchExchange(instr); } public Instruction createCoprocessorDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support coprocessor instructions."); } public Instruction createCoprocessorDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support coprocessor instructions."); } public Instruction createCoprocessorRegisterTransfer(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support coprocessor instructions."); } public Instruction createDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; + return new DataProcessing(instr); } public Instruction createLongMultiply(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support long multiplications."); } public Instruction createMoveFromStatusRegister(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support status register transfers."); } public Instruction createMoveToStatusRegister(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support status register transfers."); } public Instruction createSingleDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new SingleDataTransfer(instr); } - public Instruction createSoftwareshorterrupt(short instr) { - // TODO Auto-generated method stub - return null; + public Instruction createSoftwareInterrupt(short instr) { + return new SoftwareInterrupt(instr); } public Instruction createSwap(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support SWAP instructions."); } public Instruction createUndefinedInstruction(short instr) { - // TODO Auto-generated method stub return null; } - public Instruction createshortMultiply(short instr) { - // TODO Auto-generated method stub - return null; + public Instruction createIntMultiply(short instr) { + return new IntMultiply(instr); } - } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-14 17:19:16 UTC (rev 132) @@ -2,6 +2,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper.ShiftType; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; /** * In the ARM decoder model, the decoding and usage (translating/interpreting/disassembling) of instructions @@ -149,7 +150,7 @@ /** Describes the type of the operand. */ public enum Type { Immediate, - PcRelative, + RegisterOffset, Register, ImmediateShiftedRegister, RegisterShiftedRegister, @@ -175,8 +176,8 @@ } /** Creates an operand wrapper representing an offset to the pc.*/ - public static OperandWrapper createPcRelative(int offset) { - return new PcRelativeOperand(offset); + public static OperandWrapper createRegisterOffset(byte register, int offset) { + return new RegisterOffsetOperand(register, offset); } public static OperandWrapper createRegisterShiftImmediate(byte register, ShiftType type, byte amount) { @@ -329,17 +330,19 @@ } } - protected static class PcRelativeOperand extends OperandWrapper { + protected static class RegisterOffsetOperand extends OperandWrapper { protected final int offset; + protected final byte register; - protected PcRelativeOperand(int offset) { + protected RegisterOffsetOperand(byte register, int offset) { this.offset = offset; + this.register = register; } @Override public byte getRegister() { - return 15; + return register; } @Override @@ -349,7 +352,7 @@ @Override public Type getType() { - return Type.PcRelative; + return Type.RegisterOffset; } } @@ -463,6 +466,46 @@ protected final OperandWrapper operand2; public DataProcessing(short instr) { + + if (Utils.getBits(instr, 12, 15) == 0xA) { + //add to SP or PC (load address) + opcode = Opcode.ADD; + updateConditionCodes = false; + Rd = (byte)Utils.getBits(instr, 8, 10); + Rn = (byte)(Utils.getBit(instr, 11) ? ARM_Registers.SP : ARM_Registers.PC); + operand2 = OperandWrapper.createImmediate(instr & 0xFF); + + return; + } + + if (Utils.getBits(instr, 12, 15) == 0xB) { + //add offset to SP + updateConditionCodes = false; + opcode = Utils.getBit(instr, 7) ? Opcode.SUB : Opcode.ADD; + Rd = (byte)ARM_Registers.SP; + Rn = (byte)ARM_Registers.SP; + operand2 = OperandWrapper.createImmediate(instr & 0x7F); + + return; + } + + if (Utils.getBits(instr, 14, 15) == 0x7) { + //first instruction of a long bl/blx + if (DBT.VerifyAssertions) DBT._assert(Utils.getBits(instr, 11, 12) == 2); + + //extract and sign-extend the offset + int offset = Utils.getBits(instr, 0, 10); + offset = Utils.signExtend(offset, 11) << 12; + operand2 = OperandWrapper.createImmediate(offset); + + opcode = Opcode.MOV; + Rd = ARM_Registers.LR; + updateConditionCodes = false; + Rn = 0; + + return; + } + if (Utils.getBits(instr, 13, 15) == 0) { //shift by immediate, add/subtract register or add/subtract immediate Rd = (byte)Utils.getBits(instr, 0, 2); @@ -506,99 +549,130 @@ opcode = Opcode.SUB; break; default: - throw new RuntimeException("Values other than 0-4 cannot be represented within 2 bits."); + throw new RuntimeException("Values other than 0-3 cannot be represented within 2 bits."); } } else { - Rd = (byte)Utils.getBits(instr, 0, 2); - byte finalRn = (byte)Utils.getBits(instr, 3, 5); - updateConditionCodes = true; - switch (Utils.getBits(instr, 6, 9)) { - case 0: - opcode = Opcode.AND; - operand2 = OperandWrapper.createRegister(Rd); - break; - case 1: - opcode = Opcode.EOR; - operand2 = OperandWrapper.createRegister(Rd); - break; + if (Utils.getBit(instr, 10)) { + //special data processing + Rd = (byte)(Utils.getBits(instr, 0, 2) + (Utils.getBit(instr, 7) ? 8 : 0)); + Rn = Rd; + operand2 = OperandWrapper.createRegister((byte)(Utils.getBits(instr, 3, 5) + (Utils.getBit(instr, 6) ? 8 : 0))); + updateConditionCodes = true; - case 2: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSL, finalRn); - break; + switch (Utils.getBits(instr, 8, 9)) { + case 0: + opcode = Opcode.ADD; + break; + + case 1: + opcode = Opcode.CMP; + break; + + case 2: + opcode = Opcode.MOV; + break; + + case 3: + throw new RuntimeException("This case is actually a BranchExchange."); + + default: + throw new RuntimeException("Only the values 0-3 can be represented within 2 bits."); + } + } + else { + //data processing-register + Rd = (byte)Utils.getBits(instr, 0, 2); + byte finalRn = (byte)Utils.getBits(instr, 3, 5); + updateConditionCodes = true; - case 3: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSR, finalRn); - break; + switch (Utils.getBits(instr, 6, 9)) { + case 0: + opcode = Opcode.AND; + operand2 = OperandWrapper.createRegister(Rd); + break; + case 1: + opcode = Opcode.EOR; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 2: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSL, finalRn); + break; + + case 3: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSR, finalRn); + break; + + case 4: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ASR, finalRn); + break; + + case 5: + opcode = Opcode.ADC; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 6: + opcode = Opcode.SBC; + operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; + break; + + case 7: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ROR, finalRn); + break; + + case 8: + opcode = Opcode.TST; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 9: + opcode = Opcode.RSB; + operand2 = OperandWrapper.createImmediate(0); + break; + + case 10: + opcode = Opcode.CMP; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 11: + opcode = Opcode.CMN; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 12: + opcode = Opcode.ORR; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 13: + throw new RuntimeException("This is actually a multiply instruction."); + + case 14: + opcode = Opcode.BIC; + operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; + break; + + case 15: + opcode = Opcode.MVN; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + default: + throw new RuntimeException("Only values 0-15 can be represented within 4 bits."); + } - case 4: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ASR, finalRn); - break; - - case 5: - opcode = Opcode.ADC; - operand2 = OperandWrapper.createRegister(Rd); - break; - - case 6: - opcode = Opcode.SBC; - operand2 = OperandWrapper.createRegister(finalRn); - finalRn = Rd; - break; - - case 7: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ROR, finalRn); - break; - - case 8: - opcode = Opcode.TST; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - case 9: - opcode = Opcode.RSB; - operand2 = OperandWrapper.createImmediate(0); - break; - - case 10: - opcode = Opcode.CMP; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - case 11: - opcode = Opcode.CMN; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - case 12: - opcode = Opcode.ORR; - operand2 = OperandWrapper.createRegister(Rd); - break; - - case 13: - throw new RuntimeException("This is actually a multiply instruction."); - - case 14: - opcode = Opcode.BIC; - operand2 = OperandWrapper.createRegister(finalRn); - finalRn = Rd; - break; - - case 15: - opcode = Opcode.MVN; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - default: - throw new RuntimeException("Only values 0-15 can be represented within 4 bits."); + Rn = finalRn; } - - Rn = finalRn; } } } @@ -692,6 +766,67 @@ /** @see #getRd() */ protected final byte Rd; + + public SingleDataTransfer(short instr) { + + writeBack = false; + preIndexing = true; + forceUserMode = false; + positiveOffset = true; + + if (Utils.getBits(instr, 11, 15) == 0x9 || + Utils.getBits(instr, 12, 15) == 0x9) { + //load from literal pool or stack load/store + Rd = (byte) Utils.getBits(instr, 8, 10); + offset = OperandWrapper.createImmediate(instr & 0xFF); + isLoad = Utils.getBit(instr, 11); + signExtend = false; + size = TransferSize.Word; + Rn = (byte)(Utils.getBit(instr, 15) ? ARM_Registers.SP : ARM_Registers.PC); + } + else { + //load/store register offset, load/store byte/word immediate offset or load/store halfword immediate offset + Rd = (byte)Utils.getBits(instr, 0, 2); + Rn = (byte)Utils.getBits(instr, 3, 5); + + if (Utils.getBits(instr, 13, 15) == 0x5) { + //load store register offset + offset = OperandWrapper.createRegister((byte)Utils.getBits(instr, 6, 8)); + + if (Utils.getBit(instr, 9)) { + //load store byte/halfword + signExtend = Utils.getBit(instr, 10); + isLoad = signExtend || Utils.getBit(instr, 11); + + if (!signExtend) + size = TransferSize.HalfWord; + else + size = Utils.getBit(instr, 11) ? TransferSize.HalfWord : TransferSize.Byte; + } + else { + //load store byte/word + size = Utils.getBit(instr, 10) ? TransferSize.Byte : TransferSize.Word; + isLoad = Utils.getBit(instr, 11); + signExtend = false; + } + } + else { + //load/store word/halfword/byte with immediate offset + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10)); + isLoad = Utils.getBit(instr, 11); + signExtend = false; + + if (Utils.getBit(instr, 13)) { + //transfer word/byte + size = Utils.getBit(instr, 12) ? TransferSize.Byte : TransferSize.Word; + } + else { + //transfer Half-word + size = TransferSize.HalfWord; + } + } + } + } public SingleDataTransfer(int instr) { super(instr); @@ -934,6 +1069,38 @@ /** Contains a set bit at position N if rN should be transferred using this instruction.*/ protected final int registerList; + + public BlockDataTransfer(short instr) { + forceUser = false; + writeBack = true; + isLoad = Utils.getBit(instr, 11); + incrementBase = postIndexing = isLoad; + + int regList = instr & 0xFF; + + if (Utils.getBit(instr, 14)) { + //PUSH / POP registers + baseRegister = ARM_Registers.SP; + + if (Utils.getBit(instr, 8)) { + //this is a procedure entry/return + if (isLoad) { + //procedure return, load pc + regList |= (1 << ARM_Registers.PC); + } + else { + //procedure entry, push lr + regList |= (1 << ARM_Registers.LR); + } + } + } + else { + //LDMIA/STMIA + baseRegister = (byte)Utils.getBits(instr, 8, 10); + } + + registerList = regList; + } public BlockDataTransfer(int instr) { super(instr); @@ -1026,6 +1193,23 @@ /** @see #getOffset() */ protected final int offset; + + public Branch(short instr) { + super (Utils.getBit(instr, 13) ? Condition.values()[Utils.getBits(instr, 8, 11)] : Condition.AL); + + if (Utils.getBit(instr, 13)) { + offset = instr & 0xFF; + link = false; + } + else { + offset = Utils.getBits(instr, 0, 10); + link = Utils.getBit(instr, 12); + + //only the second instruction of a long branch is actually a branch + if (DBT.VerifyAssertions && link) DBT._assert(Utils.getBit(instr, 11)); + } + + } public Branch(int instr) { super(instr); @@ -1057,6 +1241,19 @@ /** @see #link() */ protected final boolean link; + + public BranchExchange(short instr) { + + if (Utils.getBit(instr, 15)) { + link = true; + target = OperandWrapper.createRegisterOffset(ARM_Registers.LR, Utils.getBits(instr, 0, 10)); + } + else { + link = Utils.getBit(instr, 7); + int register = Utils.getBits(instr, 3, 6); + target = OperandWrapper.createRegister((byte)register); + } + } public BranchExchange(int instr) { super(Utils.getBit(instr, 27) ? 0xE0000000 : instr); @@ -1072,7 +1269,7 @@ if (Utils.getBit(instr, 24)) jumpTarget += 2; - target = OperandWrapper.createPcRelative(jumpTarget); + target = OperandWrapper.createRegisterOffset(ARM_Registers.PC, jumpTarget); } else { link = Utils.getBit(instr, 5); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-14 17:19:16 UTC (rev 132) @@ -40,10 +40,18 @@ /** Decodes the instruction at the given address.*/ public Instruction decode(int pc) { - - int binaryInstruction = ps.memory.loadInstruction32(pc); - ARM_Instruction instruction = ARM_InstructionDecoder.decode(binaryInstruction, instructionFactory); + ARM_Instruction instruction; + + if ((pc & 1) != 0) { + short binaryInstruction = (short)ps.memory.loadInstruction16(pc & 0xFFFFFFFE); + instruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction, instructionFactory); + } + else { + int binaryInstruction = ps.memory.loadInstruction32(pc); + instruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction, instructionFactory); + } + if (instruction.getCondition() != Condition.AL) { return new ConditionalDecorator(instruction); } @@ -56,7 +64,6 @@ return instructionFactory.toString(); } - private abstract static class ResolvedOperand { protected int value; @@ -99,11 +106,11 @@ int reg = operand.getRegister(); //mind the arm pc offset - value = regs.get(reg); + if (reg == ARM_Registers.PC) + value = regs.readPC(); + else + value = regs.get(reg); - if (reg == 15) - value += 8; - return; case RegisterShiftedRegister: @@ -111,10 +118,15 @@ value = resolveShift(regs, operand); return; - case PcRelative: - value = regs.get(ARM_Registers.PC) + 8 + operand.getOffset(); - break; + case RegisterOffset: + if (operand.getRegister() == ARM_Registers.PC) + value = regs.readPC(); + else + value =regs.get(operand.getRegister()); + value += operand.getOffset(); + return; + default: throw new RuntimeException("Unexpected wrapped operand type: " + operand.getType()); @@ -128,11 +140,11 @@ DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); - int value = regs.get(operand.getRegister()); - //consider the "usual" ARM program counter offset if (operand.getRegister() == ARM_Registers.PC) - value += 8; + value = regs.readPC(); + else + value = regs.get(operand.getRegister()); byte shiftAmount; @@ -213,11 +225,11 @@ int reg = operand.getRegister(); //mind the arm pc offset - value = regs.get(reg); + if (reg == ARM_Registers.PC) + value = regs.readPC(); + else + value = regs.get(reg); - if (reg == 15) - value += 8; - return; case RegisterShiftedRegister: @@ -225,7 +237,7 @@ value = resolveShift(regs, operand); return; - case PcRelative: + case RegisterOffset: throw new RuntimeException("This operand type does not produce a shifter carry out."); default: @@ -241,11 +253,13 @@ DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); - int value = regs.get(operand.getRegister()); + int value; //consider the "usual" ARM program counter offset if (operand.getRegister() == ARM_Registers.PC) - value += 8; + value = regs.readPC(); + else + value = regs.get(operand.getRegister()); byte shiftAmount; @@ -454,7 +468,7 @@ protected int resolveOperand1() { if (i.Rn == ARM_Registers.PC) { - return regs.get(i.Rn) + 8; + return regs.readPC(); } return regs.get(i.Rn); @@ -585,7 +599,7 @@ /** Sets the condition field for logical operations. */ protected final void setFlagsForLogicalOperator(int result) { - + if (i.updateConditionCodes) { if (i.Rd != 15) { regs.setFlags(result < 0, result == 0, shifterCarryOut); @@ -1038,7 +1052,7 @@ //also transfer the program counter, if requested so if (transferPC) { nextAddress += 4; - ps.memory.store32(nextAddress, regs.get(15) + 8); + ps.memory.store32(nextAddress, regs.readPC()); } } @@ -1096,14 +1110,14 @@ public void execute() { //if we're supposed to link, then write the previous address into the link register if (i.link) { - regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + 4); + regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + (regs.getThumbMode() ? 2 : 4)); if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + i.getOffset() + 8, regs.get(ARM_Registers.PC) + 4); + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), regs.get(ARM_Registers.PC) + 4); } else { if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + i.getOffset() + 8, BranchType.DIRECT_BRANCH); + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), BranchType.DIRECT_BRANCH); } } @@ -1128,8 +1142,8 @@ public void execute() { //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; @@ -1137,7 +1151,14 @@ int targetAddress; switch (i.target.getType()) { - case PcRelative: + case RegisterOffset: + int previousAddress; + + if (i.target.getRegister() == ARM_Registers.PC) + previousAddress = regs.readPC(); + else + previousAddress = regs.get(i.target.getRegister()); + targetAddress = previousAddress + i.target.getOffset(); thumb = true; break; @@ -1155,7 +1176,7 @@ //if we're supposed to link, then write the previous address into the link register if (i.link) { - regs.set(ARM_Registers.LR, previousAddress - 4); + regs.set(ARM_Registers.LR, regs.readPC() - (regs.getThumbMode() ? 2 : 4)); ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.CALL); } else { @@ -1173,7 +1194,7 @@ public int getSuccessor(int pc) { //if we're jumping relative to the PC, then we can predict the next instruction - if (i.target.getType() == OperandWrapper.Type.PcRelative) { + if (i.target.getType() == OperandWrapper.Type.RegisterOffset) { return pc + i.target.getOffset(); } else { //otherwise we can't predict it @@ -1421,11 +1442,13 @@ private int resolveAddress() { //acquire the base address - int base = regs.get(i.Rn); + int base; //take ARM's PC offset into account - if (i.Rn == 15) - base += 8; + if (i.Rn == ARM_Registers.PC) + base = regs.readPC(); + else + base = regs.get(i.Rn); //if we are not pre-indexing, then just use the base register for the memory access if (!i.preIndexing) @@ -1688,78 +1711,103 @@ } public ARM_Instruction createBlockDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr)); } public ARM_Instruction createBranch(short instr) { - // TODO Auto-generated method stub - return null; + return new Branch(new ARM_Instructions.Branch(instr)); } public ARM_Instruction createBranchExchange(short instr) { - // TODO Auto-generated method stub - return null; + return new BranchExchange(new ARM_Instructions.BranchExchange(instr)); } public ARM_Instruction createCoprocessorDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Instruction type not supported by thumb."); } public ARM_Instruction createCoprocess... [truncated message content] |