From: <mic...@us...> - 2007-06-13 16:35:33
|
Revision: 131 http://svn.sourceforge.net/pearcolator/?rev=131&view=rev Author: michael_baer Date: 2007-06-13 09:35:34 -0700 (Wed, 13 Jun 2007) Log Message: ----------- Moving towards Thumb support... 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_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/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/decoder/CountingInstructionFactory.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-06-13 16:35:34 UTC (rev 131) @@ -3,7 +3,6 @@ import java.util.ArrayList; import org.binarytranslator.DBT; -import org.binarytranslator.DBT_Options; 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; @@ -24,15 +23,19 @@ private OPT_Register regMap[] = new OPT_Register[16]; /** The ARM carry flag. */ + private boolean carryUsed; private OPT_Register carryFlag; /** The ARM zero flag. */ + private boolean zeroUsed; private OPT_Register zeroFlag; /** The ARM negative flag. */ + private boolean negativeUsed; private OPT_Register negativeFlag; /** The ARM overflow flag. */ + private boolean overflowUsed; private OPT_Register overflowFlag; /** Set to true for each register that is in use during the current trace */ @@ -215,22 +218,31 @@ private void spillAllFlags() { OPT_RegisterOperand ps_registersOp = getArmRegistersReference(); + OPT_RegisterOperand flag; //store the carry flag - OPT_RegisterOperand flag = new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); - appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_carryFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_carryFlag_Fref), new OPT_TrueGuardOperand()) ); + if (carryUsed) { + flag = new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); + appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_carryFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_carryFlag_Fref), new OPT_TrueGuardOperand()) ); + } //store the negative flag - flag = new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean); - appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_negativeFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_negativeFlag_Fref), new OPT_TrueGuardOperand()) ); + if (negativeUsed) { + flag = new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean); + appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_negativeFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_negativeFlag_Fref), new OPT_TrueGuardOperand()) ); + } //store the zero flag - flag = new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean); - appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_zeroFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_zeroFlag_Fref), new OPT_TrueGuardOperand()) ); + if (zeroUsed) { + flag = new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean); + appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_zeroFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_zeroFlag_Fref), new OPT_TrueGuardOperand()) ); + } //store the overflow flag - flag = new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean); - appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_overflowFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_overflowFlag_Fref), new OPT_TrueGuardOperand()) ); + if (overflowUsed) { + flag = new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean); + appendInstruction(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_overflowFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_overflowFlag_Fref), new OPT_TrueGuardOperand()) ); + } } public void fillAllFlags() { @@ -308,18 +320,22 @@ } public OPT_RegisterOperand getCarryFlag() { + carryUsed = true; return new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); } public OPT_RegisterOperand getZeroFlag() { + zeroUsed = true; return new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean); } public OPT_RegisterOperand getNegativeFlag() { + negativeUsed = true; return new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean); } public OPT_RegisterOperand getOverflowFlag() { + overflowUsed = true; return new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean); } @@ -328,11 +344,24 @@ ArrayList<OPT_Register> unusedRegisters = new ArrayList<OPT_Register>(); - for (int i = 0; i < regUsed.length; i++) + for (int i = 0; i < regUsed.length; i++) { if (!regUsed[i]) { unusedRegisters.add(regMap[i]); } + } + if (!carryUsed) + unusedRegisters.add(carryFlag); + + if (!negativeUsed) + unusedRegisters.add(negativeFlag); + + if (!overflowUsed) + unusedRegisters.add(overflowFlag); + + if (!zeroUsed) + unusedRegisters.add(zeroFlag); + return unusedRegisters.toArray(new OPT_Register[unusedRegisters.size()]); } @@ -345,6 +374,15 @@ public void resolveLaziness(Laziness laziness) { //NO-OP, as we're not using laziness at the moment } + + @Override + public void appendSystemCall(Laziness lazy) { + super.appendSystemCall(lazy); + + //ARM system calls may change all registers + for (int i = 0; i < 15; i++) + regUsed[i] = true; + } @Override protected void spillAllRegisters() { @@ -353,10 +391,8 @@ OPT_RegisterOperand ps_registers_regsOp = new OPT_RegisterOperand( ps_registers_regs, registers_regs_Tref); for (int i = 0; i < regMap.length; i++) { - // We can save spills if the trace has no syscalls and the register was - // never used - if ((DBT_Options.singleInstrTranslation == false) - || (regUsed[i] == true)) { + // We can save spills if the register was never used + if (regUsed[i] == true) { appendInstruction(AStore.create(INT_ASTORE, new OPT_RegisterOperand(regMap[i], VM_TypeReference.Int), ps_registers_regsOp.copyRO(), new OPT_IntConstantOperand(i), Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-13 16:35:34 UTC (rev 131) @@ -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.MultipleDataTransfer; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.BlockDataTransfer; 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; @@ -320,7 +320,7 @@ instr.getRd(), instr.getRm(), instr.getRn())); } - public void visit(MultipleDataTransfer instr) { + public void visit(BlockDataTransfer 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-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-13 16:35:34 UTC (rev 131) @@ -286,6 +286,22 @@ 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 createLongMultiply(short instr); + T createSoftwareshorterrupt(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); } /** @@ -295,7 +311,7 @@ private static class DefaultFactory implements ARM_InstructionFactory<ARM_Instructions.Instruction> { public Instruction createBlockDataTransfer(int instr) { - return new MultipleDataTransfer(instr); + return new BlockDataTransfer(instr); } public Instruction createBranch(int instr) { @@ -353,6 +369,81 @@ public Instruction createUndefinedInstruction(int instr) { return null; } + + public Instruction createBlockDataTransfer(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createBranch(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createBranchExchange(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createCoprocessorDataProcessing(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createCoprocessorDataTransfer(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createCoprocessorRegisterTransfer(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createDataProcessing(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createLongMultiply(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createMoveFromStatusRegister(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createMoveToStatusRegister(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createSingleDataTransfer(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createSoftwareshorterrupt(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createSwap(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createUndefinedInstruction(short instr) { + // TODO Auto-generated method stub + return null; + } + + public Instruction createshortMultiply(short instr) { + // TODO Auto-generated method stub + return null; + } } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-06-13 16:35:34 UTC (rev 131) @@ -10,7 +10,7 @@ void visit(IntMultiply instr); void visit(LongMultiply instr); void visit(Swap instr); - void visit(MultipleDataTransfer instr); + void visit(BlockDataTransfer 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-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-13 16:35:34 UTC (rev 131) @@ -1,6 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.DBT; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper.ShiftType; /** * In the ARM decoder model, the decoding and usage (translating/interpreting/disassembling) of instructions @@ -26,6 +27,14 @@ /** @see #getCondition() */ protected final Condition condition; + + private Instruction () { + this.condition = Condition.AL; + } + + private Instruction (Condition condition) { + this.condition = condition; + } private Instruction(int instr) { condition = Condition.values()[(instr & 0xF0000000) >>> 28]; @@ -45,52 +54,6 @@ public abstract void visit(ARM_InstructionVisitor visitor); } - /** Base class for most instructions that use two registers. */ - private abstract static class TwoRegistersTemplate extends Instruction { - - /** @see #getRn() */ - protected final byte Rn; - - /** @see #getRd() */ - protected final byte Rd; - - public TwoRegistersTemplate(int instr) { - super(instr); - - Rd = (byte) Utils.getBits(instr, 12, 15); - Rn = (byte) Utils.getBits(instr, 16, 19); - } - - /** Returns the number of the operation's destination register, starting from 0.*/ - public final byte getRd() { - return Rd; - } - - /** Returns the number of the operation's first operand register, starting from 0.*/ - public final byte getRn() { - return Rn; - } - } - - /** Base class for most instructions that use three registers. */ - private abstract static class ThreeRegistersTemplate extends - TwoRegistersTemplate { - - /** @see #getRm() */ - protected final byte Rm; - - public ThreeRegistersTemplate(int instr) { - super(instr); - - Rm = (byte) Utils.getBits(instr, 0, 3); - } - - /** Returns the number of the second operand register, starting from 0.*/ - public final byte getRm() { - return Rm; - } - } - /** Base class for multiply operations. */ protected abstract static class MultiplyTemplate extends Instruction { @@ -216,6 +179,14 @@ return new PcRelativeOperand(offset); } + public static OperandWrapper createRegisterShiftImmediate(byte register, ShiftType type, byte amount) { + return new RegisterShiftImmediateOperand(register, type, amount); + } + + public static OperandWrapper createRegisterShiftRegister(byte register, ShiftType type, byte reg2) { + return new RegisterShiftRegisterOperand(register, type, reg2); + } + public static OperandWrapper decodeDataProcessingOperand(int instr) { if (Utils.getBit(instr, 25)) { //this is a right-rotated immediate value @@ -467,7 +438,7 @@ } /** Represents a Data Processing instruction. */ - public static class DataProcessing extends TwoRegistersTemplate { + public final static class DataProcessing extends Instruction { /** A list of possible DataProcessing operations. The list is orded in ascendingly, with the * first opcode corresponding to opcode 0 (zero) in the opcode field of an ARM data processing @@ -475,7 +446,13 @@ public enum Opcode { AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN, CLZ } + + /** @see #getRn() */ + protected final byte Rn; + /** @see #getRd() */ + protected final byte Rd; + /** @see #hasSetConditionCodes() */ protected final boolean updateConditionCodes; @@ -484,14 +461,153 @@ /** @see #getOperand2() */ protected final OperandWrapper operand2; + + public DataProcessing(short instr) { + if (Utils.getBits(instr, 13, 15) == 0) { + //shift by immediate, add/subtract register or add/subtract immediate + Rd = (byte)Utils.getBits(instr, 0, 2); + Rn = (byte)Utils.getBits(instr, 3, 5); + updateConditionCodes = true; + + if (Utils.getBits(instr, 11, 12) == 0) { + //shift by immediate + opcode = Opcode.MOV; + ShiftType type = ShiftType.values()[Utils.getBits(instr, 11, 12)]; + operand2 = OperandWrapper.createRegisterShiftImmediate(Rn, type, (byte)Utils.getBits(instr, 6, 10)); + } + else { + //add/subtract register or add/subtract immediate + opcode = Utils.getBit(instr, 9) ? Opcode.SUB : Opcode.ADD; + if (Utils.getBit(instr, 10)) + operand2 = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 8)); + else + operand2 = OperandWrapper.createRegister((byte)Utils.getBits(instr, 6, 8)); + } + } + else { + if (Utils.getBit(instr, 13)) { + //Move, Compare, Add, Subtract immediate + Rd = (byte)Utils.getBits(instr, 8, 10); + Rn = Rd; + operand2 = OperandWrapper.createImmediate(instr & 0xFF); + updateConditionCodes = true; + + switch (Utils.getBits(instr, 11, 12)) { + case 0: + opcode = Opcode.MOV; + break; + case 1: + opcode = Opcode.CMP; + break; + case 2: + opcode = Opcode.ADD; + break; + case 3: + opcode = Opcode.SUB; + break; + default: + throw new RuntimeException("Values other than 0-4 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; + + 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; - /** @see #getRd() */ - protected final byte Rd; + 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; + } + } + } public DataProcessing(int instr) { super(instr); Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); updateConditionCodes = Utils.getBit(instr, 20); @@ -525,11 +641,21 @@ public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); } + + /** Returns the number of the operation's destination register, starting from 0.*/ + public final byte getRd() { + return Rd; + } + + /** Returns the number of the operation's first operand register, starting from 0.*/ + public final byte getRn() { + return Rn; + } } /** Represents a LDR/SDR instruction. */ - public static class SingleDataTransfer extends - TwoRegistersTemplate { + public final static class SingleDataTransfer extends + Instruction { public enum TransferSize { Byte, @@ -561,8 +687,17 @@ /** @see #getOffset() */ protected final OperandWrapper offset; + /** @see #getRn() */ + protected final byte Rn; + + /** @see #getRd() */ + protected final byte Rd; + public SingleDataTransfer(int instr) { super(instr); + + Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); preIndexing = Utils.getBit(instr, 24); positiveOffset = Utils.getBit(instr, 23); @@ -620,6 +755,16 @@ if (DBT.VerifyAssertions) DBT._assert(Rd != Rn || !writeBack); } + /** Returns the number of the operation's destination register, starting from 0.*/ + public final byte getRd() { + return Rd; + } + + /** Returns the number of the operation's first operand register, starting from 0.*/ + public final byte getRn() { + return Rn; + } + /** Returns true, if this memory access shall be treated as if it had been done in user mode. */ public final boolean forceUserMode() { return forceUserMode; @@ -667,7 +812,7 @@ } /** Represents a normal (not long) multiply instruction. */ - public static class IntMultiply extends MultiplyTemplate { + public final static class IntMultiply extends MultiplyTemplate { protected IntMultiply(int instr) { super(instr); @@ -682,7 +827,7 @@ } /** Represents a long multiply instruction. */ - public static class LongMultiply extends MultiplyTemplate { + public final static class LongMultiply extends MultiplyTemplate { /** @see #isUnsigned() */ protected final boolean unsigned; @@ -717,13 +862,27 @@ } /** Represents a SWP/SWPB instruction. */ - public static class Swap extends ThreeRegistersTemplate { + public final static class Swap extends Instruction { /** @see #swapByte() */ protected final boolean swapByte; + + /** @see #getRm() */ + protected final byte Rm; + + /** @see #getRn() */ + protected final byte Rn; + /** @see #getRd() */ + protected final byte Rd; + public Swap(int instr) { super(instr); + + Rd = (byte) Utils.getBits(instr, 12, 15); + Rn = (byte) Utils.getBits(instr, 16, 19); + + Rm = (byte) Utils.getBits(instr, 0, 3); swapByte = Utils.getBit(instr, 22); } @@ -731,15 +890,29 @@ public final boolean swapByte() { return swapByte; } + + /** Returns the number of the second operand register, starting from 0.*/ + public final byte getRm() { + return Rm; + } + + /** Returns the number of the operation's destination register, starting from 0.*/ + public final byte getRd() { + return Rd; + } - @Override + /** Returns the number of the operation's first operand register, starting from 0.*/ + public final byte getRn() { + return Rn; + } + public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); } } /** Represents a LDM/STM instruction. */ - public static class MultipleDataTransfer extends Instruction { + public final static class BlockDataTransfer extends Instruction { /** @see #postIndexing() */ protected final boolean postIndexing; @@ -762,7 +935,7 @@ /** Contains a set bit at position N if rN should be transferred using this instruction.*/ protected final int registerList; - public MultipleDataTransfer(int instr) { + public BlockDataTransfer(int instr) { super(instr); postIndexing = !Utils.getBit(instr, 24); @@ -819,10 +992,15 @@ } /** Represents a SWI instruction*/ - public static class SoftwareInterrupt extends Instruction { + public final static class SoftwareInterrupt extends Instruction { /** @see #getInterruptNumber() */ protected final int interruptNumber; + + public SoftwareInterrupt(short instr) { + super(Condition.AL); + interruptNumber = instr & 0xFF; + } public SoftwareInterrupt(int instr) { super(instr); @@ -872,7 +1050,7 @@ } /** Represents a BX instruction set */ - public static class BranchExchange extends Instruction { + public final static class BranchExchange extends Instruction { /** @see #target() */ protected final OperandWrapper target; @@ -919,7 +1097,7 @@ } /** Represents a LDC/STC instruction. */ - public static class CoprocessorDataTransfer extends CoprocessorTemplate { + public final static class CoprocessorDataTransfer extends CoprocessorTemplate { /** @see #getOffset() */ protected final int offset; @@ -1004,7 +1182,7 @@ } /** Represents a CDP instruction. */ - public static class CoprocessorDataProcessing extends CoprocessorTemplate { + public final static class CoprocessorDataProcessing extends CoprocessorTemplate { /** @see #getOpcode() */ protected final byte opcode; @@ -1055,7 +1233,7 @@ } /** Represents a MRC/MCR instruction. */ - public static class CoprocessorRegisterTransfer extends CoprocessorTemplate { + public final static class CoprocessorRegisterTransfer extends CoprocessorTemplate { /** @see #getOpcode() */ protected final byte opcode; @@ -1115,7 +1293,7 @@ } /** Represents a MRS instruction. */ - public static class MoveFromStatusRegister extends Instruction { + public final static class MoveFromStatusRegister extends Instruction { /** @see #getRd() */ protected final byte Rd; @@ -1149,7 +1327,7 @@ } /** Represents a MSR instruction. */ - public static class MoveToStatusRegister extends Instruction { + public final static class MoveToStatusRegister extends Instruction { /** @see #transferControlField() */ protected final boolean transferControl; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-11 16:00:28 UTC (rev 130) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-13 16:35:34 UTC (rev 131) @@ -35,7 +35,7 @@ public ARM_Interpreter(ARM_ProcessSpace ps) { this.ps = ps; this.regs = ps.registers; - instructionFactory = new CountingInstructionFactory<ARM_Instruction>(new InterpreterFactory()); + instructionFactory = new InterpreterFactory(); //new CountingInstructionFactory<ARM_Instruction>( } /** Decodes the instruction at the given address.*/ @@ -340,7 +340,6 @@ /** All ARM interpreter instructions implement this interface. */ private interface ARM_Instruction extends Interpreter.Instruction { - /** Returns the condition, under which the given instruction will be executed. */ Condition getCondition(); } @@ -351,10 +350,12 @@ private final class ConditionalDecorator implements Interpreter.Instruction { protected final ARM_Instruction conditionalInstruction; + private final Condition condition; /** Decorates an ARM interpreter instruction, by making it execute conditionally. */ protected ConditionalDecorator(ARM_Instruction i) { conditionalInstruction = i; + this.condition = i.getCondition(); } public void execute() { @@ -380,7 +381,7 @@ /** Return true if the condition required by the conditional instruction is fulfilled, false otherwise.*/ private boolean isConditionTrue() { - switch (conditionalInstruction.getCondition()) { + switch (condition) { case AL: throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator."); @@ -430,7 +431,7 @@ return regs.isOverflowSet(); default: - throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); + throw new RuntimeException("Unexpected condition code: " + condition); } } @@ -441,26 +442,27 @@ } /** A base class for all data processing interpreter instructions, including CLZ.*/ - private abstract class DataProcessing extends ARM_Instructions.DataProcessing - implements ARM_Instruction { + private abstract class DataProcessing implements ARM_Instruction { + + protected final ARM_Instructions.DataProcessing i; - protected DataProcessing(int instr) { - super(instr); + protected DataProcessing(ARM_Instructions.DataProcessing instr) { + i = instr; } /** Returns the value of operand 1 of the data processing instruction. This is always a register value. */ protected int resolveOperand1() { - if (Rn == ARM_Registers.PC) { - return regs.get(Rn) + 8; + if (i.Rn == ARM_Registers.PC) { + return regs.get(i.Rn) + 8; } - return regs.get(Rn); + return regs.get(i.Rn); } /** Returns the value of the rhs-operand of the data processing instruction. */ protected int resolveOperand2() { - return ResolvedOperand.resolve(regs, operand2); + return ResolvedOperand.resolve(regs, i.operand2); } public abstract void execute(); @@ -474,11 +476,11 @@ protected final void setAddResult(int lhs, int rhs) { setFlagsForAdd(lhs, rhs); - if (DBT_Options.profileDuringInterpretation && Rd == 15) { + if (DBT_Options.profileDuringInterpretation && i.Rd == 15) { ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs + rhs, BranchType.INDIRECT_BRANCH); } - regs.set(Rd, lhs + rhs); + regs.set(i.Rd, lhs + rhs); } /** @@ -490,18 +492,18 @@ protected final void setSubResult(int lhs, int rhs) { setFlagsForSub(lhs, rhs); - if (DBT_Options.profileDuringInterpretation && Rd == 15) { + if (DBT_Options.profileDuringInterpretation && i.Rd == 15) { ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs - rhs, BranchType.INDIRECT_BRANCH); } - regs.set(Rd, lhs - rhs); + regs.set(i.Rd, lhs - rhs); } /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ protected final void setFlagsForAdd(int lhs, int rhs) { - if (updateConditionCodes) { - if (Rd != 15) { + if (i.updateConditionCodes) { + if (i.Rd != 15) { int result = lhs + rhs; boolean carry = Utils.unsignedAddOverflow(lhs, rhs); boolean overflow = Utils.signedAddOverflow(lhs, rhs); @@ -516,8 +518,8 @@ /** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/ protected final void setFlagsForSub(int lhs, int rhs) { - if (updateConditionCodes) { - if (Rd != 15) { + if (i.updateConditionCodes) { + if (i.Rd != 15) { int result = lhs - rhs; boolean carry = !Utils.unsignedSubOverflow(lhs, rhs); boolean overflow = Utils.signedSubOverflow(lhs, rhs); @@ -528,9 +530,13 @@ } } } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { - if (Rd != 15) + if (i.Rd != 15) return pc + 4; else return -1; @@ -543,7 +549,7 @@ * out value. The value of the barrel shifter is stored within this variable. */ protected boolean shifterCarryOut; - protected DataProcessing_Logical(int instr) { + protected DataProcessing_Logical(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -552,8 +558,8 @@ * the condition codes are to be modified by this function (because otherwise it won't be used anyway).*/ protected int resolveOperand2() { - if (updateConditionCodes) { - ResolvedOperand operand = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); + if (i.updateConditionCodes) { + ResolvedOperand operand = ResolvedOperand.resolveWithShifterCarryOut(regs, i.operand2); shifterCarryOut = operand.getShifterCarryOut(); return operand.getValue(); } @@ -566,22 +572,22 @@ * is set, also sets the flags accordingly. */ protected final void setLogicalResult(int result) { - if (DBT_Options.profileDuringInterpretation && Rd == 15) { - if (getOpcode() == Opcode.MOV && operand2.getType() == OperandWrapper.Type.Register && operand2.getRegister() == ARM_Registers.LR) + if (DBT_Options.profileDuringInterpretation && i.Rd == 15) { + if (i.getOpcode() == Opcode.MOV && i.operand2.getType() == OperandWrapper.Type.Register && i.operand2.getRegister() == ARM_Registers.LR) ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), result); else ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); } - regs.set(Rd, result); + regs.set(i.Rd, result); setFlagsForLogicalOperator(result); } /** Sets the condition field for logical operations. */ protected final void setFlagsForLogicalOperator(int result) { - if (updateConditionCodes) { - if (Rd != 15) { + if (i.updateConditionCodes) { + if (i.Rd != 15) { regs.setFlags(result < 0, result == 0, shifterCarryOut); } else { regs.restoreSPSR2CPSR(); @@ -593,7 +599,7 @@ /** Binary and. <code>Rd = op1 & op2 </code>.*/ private final class DataProcessing_And extends DataProcessing_Logical { - protected DataProcessing_And(int instr) { + protected DataProcessing_And(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -607,7 +613,7 @@ /** Exclusive or. <code>Rd = op1 ^ op2 </code>.*/ private final class DataProcessing_Eor extends DataProcessing_Logical { - protected DataProcessing_Eor(int instr) { + protected DataProcessing_Eor(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -621,7 +627,7 @@ /** Add. <code>Rd = op1 + op2 </code>.*/ private final class DataProcessing_Add extends DataProcessing { - public DataProcessing_Add(int instr) { + public DataProcessing_Add(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -636,7 +642,7 @@ /** Subtract. <code>Rd = op1 - op2 </code>.*/ private final class DataProcessing_Sub extends DataProcessing { - public DataProcessing_Sub(int instr) { + public DataProcessing_Sub(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -651,7 +657,7 @@ /** Reverse subtract. <code>Rd = op2 - op1</code>.*/ private final class DataProcessing_Rsb extends DataProcessing { - protected DataProcessing_Rsb(int instr) { + protected DataProcessing_Rsb(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -668,7 +674,7 @@ * not cause an overflow). Then, the normal add-routine is being invoked. */ private final class DataProcessing_Adc extends DataProcessing { - protected DataProcessing_Adc(int instr) { + protected DataProcessing_Adc(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -686,7 +692,7 @@ regs.setFlags(true, true, true, true); //set the result to any of the operands - regs.set(Rd, operand1); + regs.set(i.Rd, operand1); return; } } @@ -698,7 +704,7 @@ /** Subtract with carry. <code>Rd = op1 - op2 - NOT(CARRY)</code>.*/ private class DataProcessing_Sbc extends DataProcessing { - protected DataProcessing_Sbc(int instr) { + protected DataProcessing_Sbc(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -727,7 +733,7 @@ /** Reserve subtract with carry. <code>Rd = -op1 + op2 - NOT(CARRY)</code>.*/ private final class DataProcessing_Rsc extends DataProcessing_Sbc { - protected DataProcessing_Rsc(int instr) { + protected DataProcessing_Rsc(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -746,7 +752,7 @@ * <code>Flags = op1 & op2</code>*/ private final class DataProcessing_Tst extends DataProcessing_Logical { - protected DataProcessing_Tst(int instr) { + protected DataProcessing_Tst(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -760,7 +766,7 @@ * <code>Flags = op1 ^ op2</code> */ private final class DataProcessing_Teq extends DataProcessing_Logical { - protected DataProcessing_Teq(int instr) { + protected DataProcessing_Teq(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -774,7 +780,7 @@ * <code>Flags = op1 - op2</code> */ private final class DataProcessing_Cmp extends DataProcessing { - protected DataProcessing_Cmp(int instr) { + protected DataProcessing_Cmp(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -788,7 +794,7 @@ * <code>Flags = op1 + op2</code>. */ private final class DataProcessing_Cmn extends DataProcessing { - protected DataProcessing_Cmn(int instr) { + protected DataProcessing_Cmn(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -801,7 +807,7 @@ /** Binary or. <code>Rd = op1 | op2</code>. */ private final class DataProcessing_Orr extends DataProcessing_Logical { - protected DataProcessing_Orr(int instr) { + protected DataProcessing_Orr(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -814,7 +820,7 @@ private final class DataProcessing_Mov extends DataProcessing_Logical { - protected DataProcessing_Mov(int instr) { + protected DataProcessing_Mov(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -830,7 +836,7 @@ * <code>Rd = op1 & (~op2)</code>.*/ private final class DataProcessing_Bic extends DataProcessing_Logical { - protected DataProcessing_Bic(int instr) { + protected DataProcessing_Bic(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -846,7 +852,7 @@ * <code>Rd = ~op2</code>.*/ private final class DataProcessing_Mvn extends DataProcessing_Logical { - protected DataProcessing_Mvn(int instr) { + protected DataProcessing_Mvn(ARM_Instructions.DataProcessing instr) { super(instr); } @@ -861,43 +867,48 @@ * <code>Rd = Number_Of_Leading_Zeroes(op2) </code> */ private final class DataProcessing_Clz extends DataProcessing { - protected DataProcessing_Clz(int instr) { + protected DataProcessing_Clz(ARM_Instructions.DataProcessing instr) { super(instr); } @Override public void execute() { int result = Integer.numberOfLeadingZeros(resolveOperand2()); - regs.set(Rd, result); + regs.set(i.Rd, 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 { + private final class Swap implements ARM_Instruction { + + private final ARM_Instructions.Swap i; - public Swap(int instr) { - super(instr); + public Swap(ARM_Instructions.Swap instr) { + i = instr; } + + public Condition getCondition() { + return i.condition; + } public void execute() { - int memAddr = regs.get(Rn); + int memAddr = regs.get(i.Rn); //swap exchanges the value of a memory address with the value in a register - if (!swapByte) { + if (!i.swapByte) { int tmp = ps.memory.load32(memAddr); - ps.memory.store32(memAddr, regs.get(Rm)); + ps.memory.store32(memAddr, regs.get(i.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 - regs.set(Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); + regs.set(i.Rd, Integer.rotateRight(tmp, (memAddr & 0x3) * 8)); } else { int tmp = ps.memory.loadUnsigned8(memAddr); - ps.memory.store8(memAddr, regs.get(Rm)); - regs.set(Rd, tmp); + ps.memory.store8(memAddr, regs.get(i.Rm)); + regs.set(i.Rd, tmp); } } @@ -909,8 +920,10 @@ } /** Transfer multiple registers at once between the register bank and the memory. */ - private final class BlockDataTransfer extends ARM_Instructions.MultipleDataTransfer + private final class BlockDataTransfer implements ARM_Instruction { + + private final ARM_Instructions.BlockDataTransfer i; /** the lowest address that we're reading a register from / writing a register to */ private final int registerCount; @@ -923,14 +936,14 @@ /** True if the PC should be transferred to, false otherwise. */ private final boolean transferPC; - public BlockDataTransfer(int instr) { - super(instr); + public BlockDataTransfer(ARM_Instructions.BlockDataTransfer instr) { + i = instr; - transferPC = transferRegister(15); + transferPC = i.transferRegister(15); int regCount = 0; for (int i = 0; i <= 14; i++) - if (transferRegister(i)) { + if (this.i.transferRegister(i)) { registersToTransfer[regCount++] = i; } @@ -941,10 +954,10 @@ public void execute() { //build the address, which generally ignores the last two bits - int startAddress = regs.get(baseRegister) & 0xFFFFFFFC; + int startAddress = regs.get(i.baseRegister) & 0xFFFFFFFC; - if (!incrementBase) { - if (postIndexing) { + if (!i.incrementBase) { + if (i.postIndexing) { //post-indexing, backward reading startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; } else { @@ -952,7 +965,7 @@ startAddress -= (registerCount + (transferPC ? 2 : 1)) * 4; } } else { - if (postIndexing) { + if (i.postIndexing) { //post-indexing, forward reading startAddress -= 4; } else { @@ -965,14 +978,14 @@ OperatingMode previousMode = ps.registers.getOperatingMode(); //if we should transfer the user mode registers... - if (forceUser) { + if (i.forceUser) { //... then change the current register map, but do NOT change the current processor mode ps.registers.switchOperatingMode(OperatingMode.USR); ps.registers.setOperatingModeWithoutRegisterLayout(previousMode); } //are we supposed to load or store multiple registers? - if (isLoad) { + if (i.isLoad) { int nextReg = 0; while (registersToTransfer[nextReg] != -1) { @@ -989,7 +1002,7 @@ if (DBT_Options.profileDuringInterpretation) ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), newpc); - if (forceUser) { + if (i.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. @@ -1030,16 +1043,16 @@ } //restore the register layout, if we were transferring the user mode registers - if (forceUser) { + if (i.forceUser) { ps.registers.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); ps.registers.switchOperatingMode(previousMode); } - if (writeBack) { + if (i.writeBack) { //write the last address we read from back to a register - if (!incrementBase) { + if (!i.incrementBase) { //backward reading - if (postIndexing) { + if (i.postIndexing) { //backward reading, post-indexing nextAddress = startAddress; } @@ -1050,17 +1063,21 @@ } else { //forward reading - if (postIndexing) + if (i.postIndexing) nextAddress += 4; } - regs.set(baseRegister, nextAddress); + regs.set(i.baseRegister, nextAddress); } } + public Condition getCondition() { + return i.condition; + } + 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) + if (i.isLoad && transferPC) return -1; else return pc + 4; @@ -1068,38 +1085,45 @@ } /** Branch to another instruction address. */ - private final class Branch extends ARM_Instructions.Branch implements - ARM_Instruction { + private final class Branch implements ARM_Instruction { + + private final ARM_Instructions.Branch i; - public Branch(int instr) { - super(instr); + public Branch(ARM_Instructions.Branch instr) { + i = instr; } public void execute() { //if we're supposed to link, then write the previous address into the link register - if (link) { + if (i.link) { regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + 4); if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + getOffset() + 8, regs.get(ARM_Registers.PC) + 4); + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + i.getOffset() + 8, regs.get(ARM_Registers.PC) + 4); } else { if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + getOffset() + 8, BranchType.DIRECT_BRANCH); + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + i.getOffset() + 8, BranchType.DIRECT_BRANCH); } } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { - return pc + getOffset() + 8; + return pc + i.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 + private final class BranchExchange implements ARM_Instruction { + + private final ARM_Instructions.BranchExchange i; - public BranchExchange(int instr) { - super(instr); + public BranchExchange(ARM_Instructions.BranchExchange instr) { + i = instr; } public void execute() { @@ -1112,42 +1136,45 @@ //the address of the instruction we're jumping to int targetAddress; - switch (target.getType()) { + switch (i.target.getType()) { case PcRelative: - targetAddress = previousAddress + target.getOffset(); + targetAddress = previousAddress + i.target.getOffset(); thumb = true; break; case Register: - targetAddress = regs.get(target.getRegister()); + targetAddress = regs.get(i.target.getRegister()); thumb = (targetAddress & 0x1) != 0; targetAddress = targetAddress & 0xFFFFFFFE; break; default: throw new RuntimeException("Unexpected Operand type: " - + target.getType()); + + i.target.getType()); } //if we're supposed to link, then write the previous address into the link register - if (link) { + if (i.link) { regs.set(ARM_Registers.LR, previousAddress - 4); ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.CALL); } else { ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.DIRECT_BRANCH); } - //jump to the new address regs.set(ARM_Registers.PC, targetAddress); regs.setThumbMode(thumb); } + + public Condition getCondition() { + return i.condition; + } 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(); + if (i.target.getType() == OperandWrapper.Type.PcRelative) { + return pc + i.target.getOffset(); } else { //otherwise we can't predict it return -1; @@ -1156,34 +1183,40 @@ } /** 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 + private final class IntMultiply implements ARM_Instruction { + + private final ARM_Instructions.IntMultiply i; - protected IntMultiply(int instr) { - super(instr); + protected IntMultiply(ARM_Instructions.IntMultiply instr) { + i = instr; } public void execute() { //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 - int operand1 = regs.get(Rm); - int operand2 = regs.get(Rs); + int operand1 = regs.get(i.Rm); + int operand2 = regs.get(i.Rs); //calculate the result int result = operand1 * operand2; - if (accumulate) { - result += regs.get(Rn); + if (i.accumulate) { + result += regs.get(i.Rn); } //and finally, update the register map - regs.set(Rd, result); + regs.set(i.Rd, result); - if (updateConditionCodes) { + if (i.updateConditionCodes) { regs.setFlags(result < 0, result == 0); } } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { return pc + 4; @@ -1191,11 +1224,13 @@ } /** 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 + private final class LongMultiply implements ARM_Instruction { + + private final ARM_Instructions.LongMultiply i; - protected LongMultiply(int instr) { - super(instr); + protected LongMultiply(ARM_Instructions.LongMultiply instr) { + i = instr; } public void execute() { @@ -1204,11 +1239,11 @@ // 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 - long operand1 = regs.get(Rm); - long operand2 = regs.get(Rs); + long operand1 = regs.get(i.Rm); + long operand2 = regs.get(i.Rs); //get rid of the signs, if we're supposed to do unsigned multiplication - if (unsigned) { + if (i.unsigned) { operand1 = operand1 & 0xFFFFFFFF; operand2 = operand2 & 0xFFFFFFFF; } @@ -1216,23 +1251,27 @@ // calculate the result long result = operand1 * operand2; - if (accumulate) { + if (i.accumulate) { //treat the register as an unsigned value - long operand = regs.get(getRdLow()); + long operand = regs.get(i.getRdLow()); operand &= 0xFFFFFFFF; result += operand; - result += regs.get(getRdHigh()) << 32; + result += regs.get(i.getRdHigh()) << 32; } // and finally, update the register map - regs.set(getRdLow(), (int) result); - regs.set(getRdHigh(), (int) (result >>> 32)); + regs.set(i.getRdLow(), (int) result); + regs.set(i.getRdHigh(), (int) (result >>> 32)); - if (updateConditionCodes) { + if (i.updateConditionCodes) { regs.setFlags(result < 0, result == 0); } } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { return pc + 4; @@ -1240,24 +1279,28 @@ } /** Move the value of the program status register into a register. */ - private final class MoveFromStatusRegister extends - ARM_Instructions.MoveFromStatusRegister implements - ARM_Instruction { + private final class MoveFromStatusRegister implements ARM_Instruction { + + private final ARM_Instructions.MoveFromStatusRegister i; - public MoveFromStatusRegister(int instr) { - super(instr); + public MoveFromStatusRegister(ARM_Instructions.MoveFromStatusRegister instr) { + i = instr; } public void execute() { //do we have to transfer the saved or the current PSR? - if (transferSavedPSR) { - regs.set(Rd, regs.getSPSR()); + if (i.transferSavedPSR) { + regs.set(i.Rd, regs.getSPSR()); } else { - regs.set(Rd, regs.getCPSR()); + regs.set(i.Rd, regs.getCPSR()); } } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { //Rd should never be the PC, so we can safely predict the next instruction @@ -1265,17 +1308,17 @@ } } - private final class MoveToStatusRegister extends - ARM_Instructions.MoveToStatusRegister implements - ARM_Instruction { + private final class MoveToStatusRegister implements ARM_Instruction { + + private final ARM_Instructions.MoveToStatusRegister i; - public MoveToStatusRegister(int instr) { - super(instr); + public MoveToStatusRegister(ARM_Instructions.MoveToStatusRegister instr) { + i = instr; } public void execute() { //this variable is going to receive the new psr, which we will set - int new_psr = ResolvedOperand.resolve(regs, sourceOperand); + int new_psr = ResolvedOperand.resolve(regs, i.sourceOperand); //are we currently in a privileged mode? boolean inPrivilegedMode = (regs.getOperatingMode() != ARM_Registers.OperatingMode.USR); @@ -1284,7 +1327,7 @@ int old_psr; //get the currect value for old_psr - if (transferSavedPSR) { + if (i.transferSavedPSR) { //if the current mode does not have a SPSR, then do nothing if (inPrivilegedMode && regs.getOperatingMode() != ARM_Registers.OperatingMode.SYS) return; @@ -1296,31 +1339,35 @@ } //create a new CPSR value according to what pieces of the CPSR we are actually required to set - if (!transferControl || !inPrivilegedMode) { + if (!i.transferControl || !inPrivilegedMode) { new_psr &= 0xFFFFFF00; new_psr |= (old_psr & 0xFF); } - if (!transferExtension || !inPrivilegedMode) { + if (!i.transferExtension || !inPrivilegedMode) { new_psr &= 0xFFFF00FF; new_psr |= (old_psr & 0xFF00); } - if (!transferStatus || !inPrivilegedMode) { + if (!i.transferStatus || !inPrivilegedMode) { new_psr &= 0xFF00FFFF; new_psr |= (old_psr & 0xFF0000); } - if (!transferFlags) { + if (!i.transferFlags) { new_psr &= 0x00FFFFFF; new_psr |= (old_psr & 0xFF000000); } - if (transferSavedPSR) + if (i.transferSavedPSR) regs.setSPSR(new_psr); else regs.setCPSR(new_psr); } + + public Condition getCondition() { + return i.condition; + } public int getSuccessor(int pc) { return pc+4; @@ -1328,38 +1375,43 @@ } /** Invoke a software interrupt. */ - private final class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt - implements ARM_Instruction { + private final class SoftwareInterrupt implements ARM_Instruction { + + private final ARM_Instructions.SoftwareInterrupt i; - public SoftwareInterrupt(int instr) { - super(instr); + public SoftwareInterrupt(ARM_Instructions.SoftwareInterrupt instr) { + i = instr; } public void execute() { ps.doSysCall(); } + + public Condition getCondition() { + return i.condition; + } 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 { + private final class SingleDataTransfer implements ARM_Instruction { + + private final ARM_Instructions.SingleDataTransfer i; - public SingleDataTransfer(int instr) { - super(instr); + public SingleDataTransfer(ARM_Instructions.SingleDataTransfer instr) { + i = 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 int resolveOffset() { - int addrOffset = ResolvedOperand.resolve(regs, offset); + int addrOffset = ResolvedOperand.resolve(regs, i.offset); - if (positiveOffset) + if (i.positiveOffset) return addrOffset; else return -1 * addrOffset; @@ -1369,14 +1421,14 @@ private int resolveAddress() { //acquire the base address - int base = regs.get(Rn); + int base = regs.get(i.Rn); //take ARM's PC offset into account - if (Rn == 15) + if (i.Rn == 15) base += 8; //if we a... [truncated message content] |