From: <mic...@us...> - 2007-04-29 13:34:09
|
Revision: 97 http://svn.sourceforge.net/pearcolator/?rev=97&view=rev Author: michael_baer Date: 2007-04-29 06:34:10 -0700 (Sun, 29 Apr 2007) Log Message: ----------- - Not calculating the "barrel shifter carry out" if it is not needed - Fixed bug with register-shifted operands when the shift amount is >= 32 Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-28 16:18:58 UTC (rev 96) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-29 13:34:10 UTC (rev 97) @@ -132,7 +132,7 @@ if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) shiftAmount = operand.getShiftAmount(); else { - shiftAmount = (byte) (regs.get(operand.getShiftingRegister()) & 0xF); + shiftAmount = (byte) (regs.get(operand.getShiftingRegister())); } switch (operand.getShiftType()) { @@ -245,7 +245,7 @@ if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) shiftAmount = operand.getShiftAmount(); else { - shiftAmount = (byte) (regs.get(operand.getShiftingRegister()) & 0xF); + shiftAmount = (byte) (regs.get(operand.getShiftingRegister())); } switch (operand.getShiftType()) { @@ -437,18 +437,10 @@ private abstract class DataProcessing extends ARM_Instructions.DataProcessing implements ARM_Instruction { - /** Most data processing instructions may set the carry flag according to the barrel shifter's carry - * out value. The (supposed) value of the barrel shifter is stored within this variable. */ - protected boolean shifterCarryOut; - protected DataProcessing(int instr) { super(instr); } - /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift - * and set the result of the barrel shifter accordingly. */ - - /** Returns the value of operand 1 of the data processing instruction. This is always a register value. * However, deriving classes may alter this behavior, for example to return a negative register * value for a RSB instruction. */ @@ -463,25 +455,11 @@ /** Returns the value of the rhs-operand of the data processing instruction. */ protected int resolveOperand2() { - ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); - shifterCarryOut = resolvedOperand2.getShifterCarryOut(); - return resolvedOperand2.getValue(); + return ResolvedOperand.resolve(regs, operand2); } public abstract void execute(); - /** Sets the condition field for logical operations. */ - protected final void setFlagsForLogicalOperator(int result) { - - if (updateConditionCodes) { - if (Rd != 15) { - regs.setFlags(result < 0, result == 0, shifterCarryOut); - } else { - regs.restoreSPSR2CPSR(); - } - } - } - /** 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) { @@ -521,9 +499,40 @@ return -1; } } + + private abstract class DataProcessing_Logical extends DataProcessing { + + /** Most data processing instructions may set the carry flag according to the barrel shifter's carry + * out value. The value of the barrel shifter is stored within this variable. */ + protected boolean shifterCarryOut; + protected DataProcessing_Logical(int instr) { + super(instr); + } + + /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift + * and set the result of the barrel shifter accordingly. */ + protected int resolveOperand2() { + ResolvedOperand operand = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); + shifterCarryOut = operand.getShifterCarryOut(); + return operand.getValue(); + } + + /** Sets the condition field for logical operations. */ + protected final void setFlagsForLogicalOperator(int result) { + + if (updateConditionCodes) { + if (Rd != 15) { + regs.setFlags(result < 0, result == 0, shifterCarryOut); + } else { + regs.restoreSPSR2CPSR(); + } + } + } + } + /** Binary and. <code>Rd = op1 & op2 </code>.*/ - private final class DataProcessing_And extends DataProcessing { + private final class DataProcessing_And extends DataProcessing_Logical { protected DataProcessing_And(int instr) { super(instr); @@ -538,7 +547,7 @@ } /** Exclusive or. <code>Rd = op1 ^ op2 </code>.*/ - private final class DataProcessing_Eor extends DataProcessing { + private final class DataProcessing_Eor extends DataProcessing_Logical { protected DataProcessing_Eor(int instr) { super(instr); @@ -688,7 +697,7 @@ /** Set the flags according to the logical-and of two values. * <code>Flags = op1 & op2</code>*/ - private final class DataProcessing_Tst extends DataProcessing { + private final class DataProcessing_Tst extends DataProcessing_Logical { protected DataProcessing_Tst(int instr) { super(instr); @@ -702,7 +711,7 @@ /** Sets the flags according to the exclusive-or of two values. * <code>Flags = op1 ^ op2</code> */ - private final class DataProcessing_Teq extends DataProcessing { + private final class DataProcessing_Teq extends DataProcessing_Logical { protected DataProcessing_Teq(int instr) { super(instr); @@ -743,7 +752,7 @@ } /** Binary or. <code>Rd = op1 | op2</code>. */ - private final class DataProcessing_Orr extends DataProcessing { + private final class DataProcessing_Orr extends DataProcessing_Logical { protected DataProcessing_Orr(int instr) { super(instr); @@ -757,7 +766,7 @@ } } - private final class DataProcessing_Mov extends DataProcessing { + private final class DataProcessing_Mov extends DataProcessing_Logical { protected DataProcessing_Mov(int instr) { super(instr); @@ -774,7 +783,7 @@ /** Bit clear. Clear bits in a register by a mask given by a second operand. * <code>Rd = op1 & (~op2)</code>.*/ - private final class DataProcessing_Bic extends DataProcessing { + private final class DataProcessing_Bic extends DataProcessing_Logical { protected DataProcessing_Bic(int instr) { super(instr); @@ -791,7 +800,7 @@ /** Move and negate. Moves an integer between two registers, negating it on the way. * <code>Rd = -op2</code>.*/ - private final class DataProcessing_Mvn extends DataProcessing { + private final class DataProcessing_Mvn extends DataProcessing_Logical { protected DataProcessing_Mvn(int instr) { super(instr); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-30 17:59:35
|
Revision: 99 http://svn.sourceforge.net/pearcolator/?rev=99&view=rev Author: michael_baer Date: 2007-04-30 10:59:37 -0700 (Mon, 30 Apr 2007) Log Message: ----------- - Fixed bugs - Removed support of using the PC as an argument where the ARM Ref. manual specifies that using the PC with this opcode yields an undefined result - Added support for long multiplication instructions Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-30 13:24:05 UTC (rev 98) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-30 17:59:37 UTC (rev 99) @@ -441,9 +441,7 @@ super(instr); } - /** Returns the value of operand 1 of the data processing instruction. This is always a register value. - * However, deriving classes may alter this behavior, for example to return a negative register - * value for a RSB instruction. */ + /** 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) { @@ -635,6 +633,9 @@ operand2++; } else { regs.setFlags(operand1 > 0, operand1 != 0, true, true); + + //set the result to any of the operands + regs.set(Rd, operand1); return; } } @@ -666,6 +667,7 @@ //TODO: Remove this exception, when the correct behavior has been verified. throw new RuntimeException("I'm interested in finding a case where this occurs, so this exception is sooner or later going to 'notify' me.."); //regs.setFlags(operand1 > 0, operand1 != 0, true, true); + //regs.set(Rd, operand1); //return; } } @@ -843,7 +845,7 @@ int memAddr = regs.get(Rn); //swap exchanges the value of a memory address with the value in a register - if (swapByte) { + if (!swapByte) { int tmp = ps.memory.load32(memAddr); ps.memory.store32(memAddr, regs.get(Rm)); @@ -853,8 +855,8 @@ } else { int tmp = ps.memory.loadUnsigned8(memAddr); - ps.memory.store8(memAddr, regs.get(Rm) & 0xFF); - regs.set(Rm, tmp); + ps.memory.store8(memAddr, regs.get(Rm)); + regs.set(Rd, tmp); } } @@ -942,7 +944,6 @@ if (transferPC) { nextAddress += 4; int newpc = ps.memory.load32(nextAddress); - regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); if (forceUser) { //when we are transferring the PC with a forced-user transfer, then we also want to @@ -953,11 +954,18 @@ regs.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); regs.restoreSPSR2CPSR(); + if (regs.getThumbMode()) + newpc = newpc & 0xFFFFFFFE; + else + newpc = newpc & 0xFFFFFFFC; + + regs.set(ARM_Registers.PC, newpc); //there is no write-back for this instruction. return; } else { //shall we switch to thumb mode + regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); regs.setThumbMode((newpc & 0x1) != 0); } } @@ -1024,12 +1032,9 @@ } public void execute() { - //remember the previous address, taking ARM's register offset into account - int previousAddress = regs.get(ARM_Registers.PC); - //if we're supposed to link, then write the previous address into the link register if (link) - regs.set(ARM_Registers.LR, previousAddress + 4); + regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + 4); } public int getSuccessor(int pc) { @@ -1102,25 +1107,16 @@ 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); - //if any of the operands is the PC, consider ARM's PC offset - if (Rm == ARM_Registers.PC) - operand1 += 8; - - if (Rs == ARM_Registers.PC) - operand2 += 8; - //calculate the result - int result = regs.get(Rm) * regs.get(Rs); + int result = operand1 * operand2; if (accumulate) { result += regs.get(Rn); - - //also consider ARM's PC offset when adding the accumulate register - if (Rn == ARM_Registers.PC) - result += 8; } //and finally, update the register map @@ -1132,13 +1128,59 @@ } public int getSuccessor(int pc) { - if (Rd != ARM_Registers.PC) - return pc + 4; - else - return -1; + return pc + 4; } } + + /** Multiply two longs into a register, possibly adding the value of a third register on the way. */ + private final class LongMultiply extends ARM_Instructions.LongMultiply implements + ARM_Instruction { + protected LongMultiply(int instr) { + super(instr); + } + + public void 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 + long operand1 = regs.get(Rm); + long operand2 = regs.get(Rs); + + //get rid of the signs, if we're supposed to do unsigned multiplication + if (unsigned) { + operand1 = operand1 & 0xFFFFFFFF; + operand2 = operand2 & 0xFFFFFFFF; + } + + // calculate the result + long result = operand1 * operand2; + + if (accumulate) { + //treat the register as an unsigned value + long operand = regs.get(getRdLow()); + operand &= 0xFFFFFFFF; + result += operand; + + result += regs.get(getRdHigh()) << 32; + } + + // and finally, update the register map + regs.set(getRdLow(), (int) result); + regs.set(getRdHigh(), (int) (result >>> 32)); + + if (updateConditionCodes) { + regs.setFlags(result < 0, result == 0); + } + } + + public int getSuccessor(int pc) { + return pc + 4; + } + } + /** Move the value of the program status register into a register. */ private final class MoveFromStatusRegister extends ARM_Instructions.MoveFromStatusRegister implements @@ -1338,11 +1380,11 @@ break; case HalfWord: - ps.memory.store16(address, value & 0xFFFF); + ps.memory.store16(address, value); break; case Byte: - ps.memory.store8(address, value & 0xFF); + ps.memory.store8(address, value); break; default: @@ -1500,8 +1542,7 @@ } public ARM_Instruction createLongMultiply(int instr) { - //TODO: Implement multiplications with longs - throw new RuntimeException("Long Multiplications are not yet supported."); + return new LongMultiply(instr); } public ARM_Instruction createMoveFromStatusRegister(int instr) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-02 18:23:53
|
Revision: 101 http://svn.sourceforge.net/pearcolator/?rev=101&view=rev Author: michael_baer Date: 2007-05-02 11:23:53 -0700 (Wed, 02 May 2007) Log Message: ----------- - Fixed bug in RRE - Reduced evaluation of barrel-shifter even further - Small javadoc correction Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-30 18:00:12 UTC (rev 100) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-02 18:23:53 UTC (rev 101) @@ -166,7 +166,7 @@ if (regs.isCarrySet()) return (value >> 1) | 0x80000000; else - return value >> 1; + return value >>> 1; default: throw new RuntimeException("Unexpected shift type: " @@ -321,7 +321,7 @@ if (regs.isCarrySet()) return (value >> 1) | 0x80000000; else - return value >> 1; + return value >>> 1; default: throw new RuntimeException("Unexpected shift type: " @@ -509,11 +509,18 @@ } /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift - * and set the result of the barrel shifter accordingly. */ + * and set the result of the barrel shifter accordingly. However, the shifter carry out is only calculated, when + * the condition codes are to be modified by this function (because otherwise it won't be used anyway).*/ protected int resolveOperand2() { - ResolvedOperand operand = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); - shifterCarryOut = operand.getShifterCarryOut(); - return operand.getValue(); + + if (updateConditionCodes) { + ResolvedOperand operand = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); + shifterCarryOut = operand.getShifterCarryOut(); + return operand.getValue(); + } + else { + return super.resolveOperand2(); + } } /** Sets the condition field for logical operations. */ @@ -801,7 +808,7 @@ } /** Move and negate. Moves an integer between two registers, negating it on the way. - * <code>Rd = -op2</code>.*/ + * <code>Rd = ~op2</code>.*/ private final class DataProcessing_Mvn extends DataProcessing_Logical { protected DataProcessing_Mvn(int instr) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-21 17:27:53
|
Revision: 140 http://svn.sourceforge.net/pearcolator/?rev=140&view=rev Author: michael_baer Date: 2007-06-21 10:27:50 -0700 (Thu, 21 Jun 2007) Log Message: ----------- - Replaced constant 15 with symbolical ARM_Registers.PC in a few cases where that was missing. - Storing intermediate results within the instruction class for BlockTransfer instructions Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-20 13:53:32 UTC (rev 139) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-21 17:27:50 UTC (rev 140) @@ -465,8 +465,12 @@ protected final ARM_Instructions.DataProcessing i; + /** If this bit is set, a special way of reading the program counter is enabled, that is only needed for a single Thumb instruction *sigh*. */ + private final boolean specialThumbPcMode; + protected DataProcessing(ARM_Instructions.DataProcessing instr) { i = instr; + specialThumbPcMode = i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD && i.operand2.getType() == OperandWrapper.Type.Immediate; } @Override @@ -481,7 +485,7 @@ int value = regs.readPC(); //this is a very special instruction encoding that demands that the PC is read with an ARM32 mask. - if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD && i.operand2.getType() == OperandWrapper.Type.Immediate) + if (specialThumbPcMode) value = value & 0xFFFFFFFC; return value; @@ -545,7 +549,7 @@ protected final void setFlagsForAdd(int lhs, int rhs) { if (i.updateConditionCodes) { - if (i.Rd != 15) { + if (i.Rd != ARM_Registers.PC) { int result = lhs + rhs; boolean carry = Utils.unsignedAddOverflow(lhs, rhs); boolean overflow = Utils.signedAddOverflow(lhs, rhs); @@ -561,7 +565,7 @@ protected final void setFlagsForSub(int lhs, int rhs) { if (i.updateConditionCodes) { - if (i.Rd != 15) { + if (i.Rd != ARM_Registers.PC) { int result = lhs - rhs; boolean carry = !Utils.unsignedSubOverflow(lhs, rhs); boolean overflow = Utils.signedSubOverflow(lhs, rhs); @@ -578,7 +582,7 @@ } public int getSuccessor(int pc) { - if (i.Rd != 15) + if (i.Rd != ARM_Registers.PC) return pc + i.size(); else return -1; @@ -614,11 +618,17 @@ * is set, also sets the flags accordingly. */ protected final void setLogicalResult(int result) { - 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); + if (i.Rd == ARM_Registers.PC) { + + if (regs.getThumbMode()) + result |= 1; + + if (DBT_Options.profileDuringInterpretation) { + 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(i.Rd, result); @@ -629,7 +639,7 @@ protected final void setFlagsForLogicalOperator(int result) { if (i.updateConditionCodes) { - if (i.Rd != 15) { + if (i.Rd != ARM_Registers.PC) { regs.setFlags(result < 0, result == 0, shifterCarryOut); } else { regs.restoreSPSR2CPSR(); @@ -972,9 +982,6 @@ private final ARM_Instructions.BlockDataTransfer i; - /** the lowest address that we're reading a register from / writing a register to */ - private final int registerCount; - /** An array that contains the registers to be transferd in ascending order. * The list is delimited by setting the entry after the last register index to -1. * The PC is not included in this list, if it shall be transferred. */ @@ -982,11 +989,21 @@ /** True if the PC should be transferred to, false otherwise. */ private final boolean transferPC; + + /** Offset of the first memory address from the value stoted in the base register. */ + private final int startAddressOffset; + + /** After adding this offset to <code>startAddress</code>, the resulting value will be written back into the + * base register. */ + private final int writebackOffset; + + /** Should writeback be performed? */ + private final boolean doWriteback; public BlockDataTransfer(ARM_Instructions.BlockDataTransfer instr) { i = instr; - transferPC = i.transferRegister(15); + transferPC = i.transferRegister(ARM_Registers.PC); int regCount = 0; for (int i = 0; i <= 14; i++) @@ -996,30 +1013,62 @@ registersToTransfer[regCount] = -1; - registerCount = regCount; - } - - public void execute() { - //build the address, which generally ignores the last two bits - int startAddress = regs.get(i.baseRegister) & 0xFFFFFFFC; + if (transferPC) + regCount++; if (!i.incrementBase) { if (i.postIndexing) { //post-indexing, backward reading - startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; + startAddressOffset = regCount * -4; } else { //pre-indexing, backward-reading - startAddress -= (registerCount + (transferPC ? 2 : 1)) * 4; + startAddressOffset = (regCount + 1) * -4; } } else { if (i.postIndexing) { //post-indexing, forward reading - startAddress -= 4; + startAddressOffset = -4; } else { //pre-indexing, forward reading //no need to adjust the start address + startAddressOffset = 0; } } + + if (!i.writeBack || i.transferRegister(i.baseRegister)) { + //do not change the register + doWriteback = false; + writebackOffset = 0; + } + else { + doWriteback = true; + + if (!i.incrementBase) { + //backward reading + if (i.postIndexing) { + //backward reading, post-indexing + writebackOffset = 0; + } + else { + //backward reading, pre-indexing + writebackOffset = 4; + } + } + else { + //forward reading + if (i.postIndexing) { + writebackOffset = (regCount + 1) * 4; + } + else { + writebackOffset = regCount * 4; + } + } + } + } + + public void execute() { + //build the address, which generally ignores the last two bits + final int startAddress = (regs.get(i.baseRegister) & 0xFFFFFFFC) + startAddressOffset; int nextAddress = startAddress; OperatingMode previousMode = ps.registers.getOperatingMode(); @@ -1041,7 +1090,7 @@ .load32(nextAddress)); } - //if we also transferred the program counter + //Are we also supposed to transfer the program counter? if (transferPC) { nextAddress += 4; int newpc = ps.memory.load32(nextAddress); @@ -1095,27 +1144,8 @@ ps.registers.switchOperatingMode(previousMode); } - if (i.writeBack && !i.transferRegister(i.baseRegister)) { - //write the last address we read from back to a register - if (!i.incrementBase) { - //backward reading - if (i.postIndexing) { - //backward reading, post-indexing - nextAddress = startAddress; - } - else { - //backward reading, pre-indexing - nextAddress = startAddress + 4; - } - } - else { - //forward reading - if (i.postIndexing) - nextAddress += 4; - } - - regs.set(i.baseRegister, nextAddress); - } + if (doWriteback) + regs.set(i.baseRegister, startAddress + writebackOffset); } public Condition getCondition() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |