|
From: <mic...@us...> - 2007-08-07 22:28:52
|
Revision: 161
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=161&view=rev
Author: michael_baer
Date: 2007-08-07 15:28:53 -0700 (Tue, 07 Aug 2007)
Log Message:
-----------
- Added support for interchangeable flag behaviour and flag laziness on ARM
- Improved usage of profiling data for conditional instructions on ARM
Modified Paths:
--------------
src/org/binarytranslator/DBT_Options.java
src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java
src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java
src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
src/org/binarytranslator/generic/decoder/CodeTranslator.java
src/org/binarytranslator/vmInterface/DBT_Trace.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -93,9 +93,12 @@
/** Just a temporary variable for testing. It describes, when the staged emulation controller switches from interpretation to translation. */
public static int minTraceValue = 20;
- /** Just a temporary variable for testing. It describes, if the translated program shall be optimized using profiling information.. */
+ /** Just a temporary variable for testing. It describes, if the translated program shall be optimized using profiling information. */
public static boolean optimizeTranslationByProfiling = false;
+ /** Just a temporary variable for testing. It describes, if the translated program shall be optimized using lazy evaluation.*/
+ public static boolean optimizeTranslationByLazyEvaluation = true;
+
/** Print debug information during the translation of instructions. */
public static boolean debugTranslation = true;
@@ -179,6 +182,8 @@
debugSyscall = Boolean.parseBoolean(value);
} else if (key.equalsIgnoreCase("debugSyscallMore")) {
debugSyscallMore = Boolean.parseBoolean(value);
+ } else if (key.equalsIgnoreCase("debugTranslation")) {
+ debugTranslation = Boolean.parseBoolean(value);
} else if (key.equalsIgnoreCase("instrOpt0")) {
instrOpt0 = Integer.parseInt(value);
} else if (key.equalsIgnoreCase("instrOpt1")) {
@@ -201,9 +206,12 @@
saveProfileToFile = value;
} else if (key.equalsIgnoreCase("minTraceValue")) {
minTraceValue = Integer.parseInt(value);
- } else if (key.equalsIgnoreCase("optimizeTranslation")) {
+ } else if (key.equalsIgnoreCase("optimizeByProfiling")) {
optimizeTranslationByProfiling = Boolean.parseBoolean(value);
+ } else if (key.equalsIgnoreCase("optimizeByLazy")) {
+ optimizeTranslationByLazyEvaluation = Boolean.parseBoolean(value);
}
+
else {
throw new Error("Unknown DBT option: " + key);
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -3,6 +3,9 @@
import java.util.ArrayList;
import org.binarytranslator.DBT;
+import org.binarytranslator.DBT_Options;
+import org.binarytranslator.arch.arm.decoder.ARM_Laziness.Flag;
+import org.binarytranslator.arch.arm.decoder.ARM_Laziness.Operation;
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;
@@ -77,6 +80,9 @@
/** The class performing the actual translation of the bytecode. */
private final ARM_Translator translator;
+ /** Determines how flags are resolved and if laziness is used.*/
+ private final ARM_FlagBehavior flagBehavior;
+
static {
psTref = VM_TypeReference.findOrCreate(ARM_ProcessSpace.class);
@@ -136,8 +142,274 @@
public ARM2IR(OPT_GenerationContext context, DBT_Trace trace) {
super(context, trace);
translator = new ARM_Translator((ARM_ProcessSpace)ps, this);
+
+ if (DBT_Options.optimizeTranslationByLazyEvaluation)
+ flagBehavior = new ARM_LazyFlagBehavior();
+ else
+ flagBehavior = new ARM_ImmediateFlagBehavior();
}
+
+ /** ARM has an interchangeable flag behavior. Flags can either be evaluated immediately or on demand using
+ * lazy evaluation. This interface encapsulates the differences. */
+ public abstract class ARM_FlagBehavior {
+
+ /**
+ * Interface helper function. If a flag behaviour wants to set a value of a flag, it shall set
+ * the {@link OPT_RegisterOperand} returned by this function.
+ */
+ protected final OPT_RegisterOperand getFlag(Flag flag) {
+ switch (flag) {
+ case Zero:
+ return new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean);
+
+ case Carry:
+ return new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean);
+
+ case Negative:
+ return new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean);
+
+ case Overflow:
+ return new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean);
+
+ default:
+ throw new RuntimeException("Unexpected flag type: " + flag);
+ }
+ }
+ /** Called before a flag is written to directly. */
+ public abstract void onFlagWrite(Flag flag, ARM_Laziness lazy);
+
+ /** Called before a flag is read. */
+ public abstract void onFlagRead(Flag flag, ARM_Laziness lazy);
+
+ /** Called when the ARM flags shall be set by a logical operation. This sets the zero and negative flag. */
+ public abstract void appendLogicalFlags(ARM_Laziness lazy, OPT_Operand result);
+
+ /** Called when the ARM flags shall be set by a ADD operation. This sets all ARM flags. */
+ public abstract void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2);
+
+ /** Called when the ARM flags shall be set by a SUB operation. This sets all ARM flags. */
+ public abstract void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2);
+ }
+
+ /** Implements a flag behavior that will immediately evaluate all flag values. */
+ public final class ARM_ImmediateFlagBehavior extends ARM_FlagBehavior {
+ @Override
+ public void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Zero), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), result.copy(), op1.copy(), OPT_ConditionOperand.LOWER(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
+ }
+
+ @Override
+ public void appendLogicalFlags(ARM_Laziness lazy, OPT_Operand result) {
+
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Zero), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+
+ }
+
+ @Override
+ public void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Zero), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely()));
+ }
+
+ @Override
+ public void onFlagRead(Flag flag, ARM_Laziness lazy) {
+ //nothing to do here, because the flags are already resolved
+ }
+
+ @Override
+ public void onFlagWrite(Flag flag, ARM_Laziness lazy) {
+ //nothing to do here, because the flags are already resolved
+ }
+ }
+
+ /** Implements a flag behavior that will use lazy evaluation to only determine a flag value
+ * when it is necessary. */
+ public final class ARM_LazyFlagBehavior extends ARM_FlagBehavior {
+
+ /** Operands for lazy evaluation of condition codes. */
+ private OPT_Register lazyOperand1;
+ private OPT_Register lazyOperand2;
+ private OPT_Register lazyLogicalOperand;
+
+ public ARM_LazyFlagBehavior() {
+ //prepare the laziness registers
+ lazyOperand1 = makeTemp(VM_TypeReference.Int).register;
+ lazyOperand2 = makeTemp(VM_TypeReference.Int).register;
+ lazyLogicalOperand = makeTemp(VM_TypeReference.Int).register;
+ }
+
+ @Override
+ public void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+
+ appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(lazyOperand1, VM_TypeReference.Int), op1.copy()));
+ appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(lazyOperand2, VM_TypeReference.Int), op2.copy()));
+
+ lazy.setValid(Flag.Zero, false);
+ lazy.setValid(Flag.Negative, false);
+ lazy.setValid(Flag.Carry, false);
+ lazy.setValid(Flag.Overflow, false);
+ lazy.setOperation(Operation.Add);
+
+ if (DBT_Options.debugTranslation) {
+ System.out.println("New Lazy state: " + lazy);
+ }
+ }
+
+ @Override
+ public void appendLogicalFlags(ARM_Laziness lazy, OPT_Operand result) {
+ appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(lazyLogicalOperand, VM_TypeReference.Int), result.copy()));
+
+ lazy.setValid(Flag.Zero, false);
+ lazy.setValid(Flag.Negative, false);
+
+ switch (lazy.getOperation()) {
+ case Add:
+ lazy.setOperation(Operation.LogicalOpAfterAdd);
+ break;
+
+ case Sub:
+ lazy.setOperation(Operation.LogicalOpAfterSub);
+ break;
+
+ case LogicalOpAfterAdd:
+ case LogicalOpAfterSub:
+ break;
+
+ default:
+ throw new RuntimeException("Unhandled laziness operation: " + lazy.getOperation());
+ }
+
+ if (DBT_Options.debugTranslation) {
+ System.out.println("New Lazy state: " + lazy);
+ }
+ }
+
+ @Override
+ public void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+
+ appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(lazyOperand1, VM_TypeReference.Int), op1.copy()));
+ appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(lazyOperand2, VM_TypeReference.Int), op2.copy()));
+
+ lazy.setValid(Flag.Zero, false);
+ lazy.setValid(Flag.Negative, false);
+ lazy.setValid(Flag.Carry, false);
+ lazy.setValid(Flag.Overflow, false);
+ lazy.setOperation(Operation.Sub);
+
+ if (DBT_Options.debugTranslation) {
+ System.out.println("New Lazy state: " + lazy);
+ }
+ }
+
+ private void resolveFlag(ARM_Laziness.Flag flag, ARM_Laziness lazy) {
+
+ if (lazy.isValid(flag))
+ return;
+
+ if (DBT_Options.debugTranslation) {
+ System.out.println("Resolving " + flag + " flag.");
+ }
+
+ OPT_RegisterOperand flagRegister = getFlag(flag);
+ OPT_RegisterOperand op1 = new OPT_RegisterOperand(lazyOperand1, VM_TypeReference.Int);
+ OPT_RegisterOperand op2 = new OPT_RegisterOperand(lazyOperand2, VM_TypeReference.Int);
+ OPT_RegisterOperand result;
+
+ switch (lazy.getOperation()) {
+ case Add:
+ result = gc.temps.makeTempInt();
+ appendInstruction(Binary.create(INT_ADD, result, op1, op2));
+ break;
+
+ case Sub:
+ result = gc.temps.makeTempInt();
+ appendInstruction(Binary.create(INT_SUB, result, op1, op2));
+ break;
+
+ case LogicalOpAfterAdd:
+ case LogicalOpAfterSub:
+ result = new OPT_RegisterOperand(lazyLogicalOperand, VM_TypeReference.Int);
+ break;
+
+ default:
+ throw new RuntimeException("Unhandled laziness operation: " + lazy.getOperation());
+ }
+
+ switch (flag) {
+ case Zero:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ break;
+
+ case Carry:
+ switch (lazy.getOperation()) {
+ case LogicalOpAfterAdd:
+ case Add:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, result.copy(), op1.copy(), OPT_ConditionOperand.LOWER(), new OPT_BranchProfileOperand()));
+ break;
+
+ case LogicalOpAfterSub:
+ case Sub:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand()));
+ break;
+
+ default:
+ throw new RuntimeException("Unhandled laziness operation: " + lazy.getOperation());
+ }
+ break;
+
+ case Negative:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+ break;
+
+ case Overflow:
+ switch (lazy.getOperation()) {
+ case Add:
+ case LogicalOpAfterAdd:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
+ break;
+
+ case Sub:
+ case LogicalOpAfterSub:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely()));
+ break;
+
+ default:
+ throw new RuntimeException("Unhandled laziness operation: " + lazy.getOperation());
+ }
+
+ break;
+
+ default:
+ throw new RuntimeException("Unhandled flag type: " + flag);
+ }
+
+ lazy.setValid(flag, true);
+
+ if (DBT_Options.debugTranslation) {
+ System.out.println("New Lazy state: " + lazy);
+ }
+ }
+
+ @Override
+ public void onFlagRead(Flag flag, ARM_Laziness lazy) {
+ resolveFlag(flag, lazy);
+
+ }
+
+ @Override
+ public void onFlagWrite(Flag flag, ARM_Laziness lazy) {
+ lazy.setValid(flag, true);
+ }
+ }
+
@Override
protected Laziness createInitialLaziness() {
return new ARM_Laziness();
@@ -319,26 +591,67 @@
return new OPT_RegisterOperand(regMap[r], VM_TypeReference.Int);
}
- public OPT_RegisterOperand getCarryFlag() {
+ public OPT_Operand readCarryFlag(ARM_Laziness lazy) {
carryUsed = true;
+ flagBehavior.onFlagRead(Flag.Carry, lazy);
return new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean);
}
- public OPT_RegisterOperand getZeroFlag() {
+ public OPT_Operand readZeroFlag(ARM_Laziness lazy) {
zeroUsed = true;
+ flagBehavior.onFlagRead(Flag.Zero, lazy);
return new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean);
}
- public OPT_RegisterOperand getNegativeFlag() {
+ public OPT_Operand readNegativeFlag(ARM_Laziness lazy) {
negativeUsed = true;
+ flagBehavior.onFlagRead(Flag.Negative, lazy);
return new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean);
}
- public OPT_RegisterOperand getOverflowFlag() {
+ public OPT_Operand readOverflowFlag(ARM_Laziness lazy) {
overflowUsed = true;
+ flagBehavior.onFlagRead(Flag.Overflow, lazy);
return new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean);
}
+ public OPT_RegisterOperand writeCarryFlag(ARM_Laziness lazy) {
+ carryUsed = true;
+ flagBehavior.onFlagWrite(Flag.Carry, lazy);
+ return new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean);
+ }
+
+ public OPT_RegisterOperand writeZeroFlag(ARM_Laziness lazy) {
+ zeroUsed = true;
+ flagBehavior.onFlagWrite(Flag.Zero, lazy);
+ return new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean);
+ }
+
+ public OPT_RegisterOperand writeNegativeFlag(ARM_Laziness lazy) {
+ negativeUsed = true;
+ flagBehavior.onFlagWrite(Flag.Negative, lazy);
+ return new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean);
+ }
+
+ public OPT_RegisterOperand writeOverflowFlag(ARM_Laziness lazy) {
+ overflowUsed = true;
+ flagBehavior.onFlagWrite(Flag.Overflow, lazy);
+ return new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean);
+ }
+
+ public void appendLogicalFlags(ARM_Laziness lazy, OPT_Operand result) {
+ flagBehavior.appendLogicalFlags(lazy, result);
+ }
+
+ public void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+ flagBehavior.appendSubFlags(lazy, result, op1, op2);
+ }
+
+ public void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+ flagBehavior.appendAddFlags(lazy, result, op1, op2);
+ }
+
+
@Override
protected OPT_Register[] getUnusedRegisters() {
@@ -372,7 +685,19 @@
@Override
public void resolveLaziness(Laziness laziness) {
- //NO-OP, as we're not using laziness at the moment
+ ARM_Laziness lazy = (ARM_Laziness)laziness;
+
+ if (carryUsed)
+ flagBehavior.onFlagRead(Flag.Carry, lazy);
+
+ if (negativeUsed)
+ flagBehavior.onFlagRead(Flag.Negative, lazy);
+
+ if (overflowUsed)
+ flagBehavior.onFlagRead(Flag.Overflow, lazy);
+
+ if (zeroUsed)
+ flagBehavior.onFlagRead(Flag.Zero, lazy);
}
@Override
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -46,13 +46,18 @@
Instruction decodedInstruction;
- if ((address & 0x1) == 1) {
- short binaryInstruction = (short)ps.memory.loadInstruction16(address & 0xFFFFFFFE);
- decodedInstruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction);
+ try {
+ 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);
+ }
}
- else {
- int binaryInstruction = ps.memory.loadInstruction32(address);
- decodedInstruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction);
+ catch (Exception e) {
+ return new ARM_DisassembledInstruction("Exception (" + e + ") while reading instruction at 0x" + Integer.toHexString(address));
}
DisassemblingVisitor disassembler = new DisassemblingVisitor();
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -2,41 +2,115 @@
import org.binarytranslator.generic.decoder.Laziness;
-public class ARM_Laziness extends Laziness {
+public final class ARM_Laziness extends Laziness {
+ public enum Operation {
+ Add, Sub, LogicalOpAfterAdd, LogicalOpAfterSub
+ }
+
+ public enum Flag {
+ Carry, Zero, Negative, Overflow
+ }
+
+ /** The state of the different ARM flags, compressed as bit fields within an integer. */
+ private int flagValid;
+
+ /** The operation that has to be performed to evaluate the remaining registers */
+ private Operation lazinessOperation;
+
final class ARM_LazinessKey extends Key {
private final int pc;
+ private final byte flagState;
public int hashCode() {
- return pc;
+ return pc | flagState;
}
public boolean equals(Object o) {
- return ((o instanceof ARM_LazinessKey) && ((ARM_LazinessKey) o).pc == pc);
+ if (!(o instanceof ARM_LazinessKey))
+ return false;
+
+ ARM_LazinessKey otherKey = (ARM_LazinessKey)o;
+ return otherKey.pc == pc && otherKey.flagState == flagState;
}
- ARM_LazinessKey(int pc) {
+ ARM_LazinessKey(int pc, ARM_Laziness lazy) {
this.pc = pc;
+ int tmpFlagState = lazy.flagValid & 0xF;
+ tmpFlagState |= (lazinessOperation.ordinal() + 1) << 4;
+
+ this.flagState = (byte)tmpFlagState;
}
public String toString() {
- return "0x" + Integer.toHexString(pc);
+ return String.format("0x%x (%d)", pc, flagState);
}
}
+ public ARM_Laziness() {
+ flagValid = 0xF; //all flags are valid
+ lazinessOperation = Operation.Add;
+ }
+
+ private ARM_Laziness(ARM_Laziness other) {
+ set(other);
+ }
+
+ public void setValid(Flag flag, boolean valid) {
+ flagValid |= 1 << flag.ordinal();
+ }
+
+ public boolean isValid(Flag flag) {
+ return (flagValid & (1 << flag.ordinal())) != 0;
+ }
+
+ public void setAddOperation() {
+ flagValid = 0; // all flags are invalid
+ lazinessOperation = Operation.Add;
+ }
+
+ public void setSubOperation() {
+ flagValid = 0; // all flags are invalid
+ lazinessOperation = Operation.Sub;
+ }
+
+ public Operation getOperation() {
+ return lazinessOperation;
+ }
+
+ public void setOperation(Operation lazinessOperation) {
+ this.lazinessOperation = lazinessOperation;
+ }
+
+ public void set(ARM_Laziness other) {
+ flagValid = other.flagValid;
+ lazinessOperation = other.lazinessOperation;
+ }
+
@Override
public Object clone() {
- return new ARM_Laziness();
+ return new ARM_Laziness(this);
}
@Override
- public boolean equivalent(Laziness other) {
- return other instanceof ARM_Laziness;
+ public boolean equivalent(Laziness o) {
+ if (!(o instanceof ARM_Laziness))
+ return false;
+
+ ARM_Laziness other = (ARM_Laziness)o;
+ return flagValid == other.flagValid && lazinessOperation == other.lazinessOperation;
}
@Override
public Key makeKey(int pc) {
- return new ARM_LazinessKey(pc);
+ return new ARM_LazinessKey(pc, this);
}
+ @Override
+ public String toString() {
+ return "Operation: " + lazinessOperation + ", C:" + (isValid(Flag.Carry) ? "1" : "0")
+ + ", Z:" + (isValid(Flag.Zero) ? "1" : "0")
+ + ", N:" + (isValid(Flag.Negative) ? "1" : "0")
+ + ", O:" + (isValid(Flag.Overflow) ? "1" : "0");
+ }
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -377,8 +377,9 @@
curBlock.deleteNormalOut();
curBlock.insertOut(nextBlock);
curBlock.insertOut(block1);
+ OPT_Operand carryFlag = translator.arm2ir.readCarryFlag(translator.lazy);
translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand.copy(), new OPT_IntConstantOperand(1)));
- translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, translator.arm2ir.getTempValidation(0), carryFlag, new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand()));
//Block 1
translator.arm2ir.setCurrentBlock(block1);
@@ -414,7 +415,7 @@
value = new OPT_IntConstantOperand(operand.getImmediate());
if (operand.getShiftAmount() != 0) {
- OPT_RegisterOperand carryFlag = translator.arm2ir.getCarryFlag();
+ OPT_RegisterOperand carryFlag = translator.arm2ir.writeCarryFlag(translator.lazy);
OPT_Operand shifterCarryOut = new OPT_IntConstantOperand(((operand.getImmediate() & 0x80000000) != 0) ? 1 : 0);
//otherwise there is no shifter carry out
@@ -451,7 +452,7 @@
/** Returns the register that receives the shifte carry out*/
private OPT_RegisterOperand getShifterCarryOutTarget() {
- return translator.arm2ir.getCarryFlag();
+ return translator.arm2ir.writeCarryFlag(translator.lazy);
}
/**
@@ -685,7 +686,7 @@
curBlock.insertOut(block1);
curBlock.insertOut(nextBlock);
translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand.copy(), new OPT_IntConstantOperand(1)));
- translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, translator.arm2ir.readCarryFlag(translator.lazy), new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand()));
//Block 1
translator.arm2ir.setCurrentBlock(block1);
@@ -720,7 +721,7 @@
/** Return the instruction following this one or -1, if that is not yet known. */
int getSuccessor(int pc);
}
-
+
/** All ARM instructions that are supposed to be executed conditionally
* are decorated with this decorator.
* The decorator takes care of checking the individual condition and depending on it, executing the
@@ -729,7 +730,7 @@
protected final ARM_Instruction conditionalInstruction;
protected final Condition condition;
-
+
/** Decorates an ARM interpreter instruction, by making it execute conditionally. */
protected ConditionalDecorator(ARM_Instruction i) {
conditionalInstruction = i;
@@ -738,132 +739,213 @@
public int getSuccessor(int pc) {
- boolean thumbMode = (pc & 0x1) == 1;
- return pc + (thumbMode ? 2 : 4);
+ if (assumeInstructionWillBeSkipped()) {
+ boolean thumbMode = (pc & 0x1) == 1;
+ return pc + (thumbMode ? 2 : 4);
+ }
+ else {
+ return conditionalInstruction.getSuccessor(pc);
+ }
}
public Condition getCondition() {
return condition;
}
+ /**
+ * Returns the probability that this conditional instruction will be skipped.
+ *
+ * @return
+ * The probability that this conditional instruction will be skipped. Returns -1, if this probability
+ * cannot be estimated.
+ */
+ private float getSkipProbability() {
+
+ if (DBT_Options.optimizeTranslationByProfiling)
+ return -1f;
+
+ return ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4));
+ }
+
+ /**
+ * During the processing of this conditional instruction, shall we assume that it will be skipped?
+ * This is helpful to optimize the trace.
+ *
+ * @return
+ * True if it is likely that this instruction will be skipped. False otherwise.
+ */
+ private boolean assumeInstructionWillBeSkipped() {
+ float skipProbability = getSkipProbability();
+
+ return (skipProbability == -1f || skipProbability > 0.5f);
+ }
+
+ /**
+ conditionals are implemented easily: if the condition does not hold, then just
+ jump to the block following the conditional instruction. To do this, the following structure of
+ block is built:
+
+ --------------------------------------------------------
+ 1. block that checks the condition
+ --------------------------------------------------------
+ 2. conditional instruction
+ --------------------------------------------------------
+ 3. next instruction, when the instruction was not skipped
+ --------------------------------------------------------
+ 4. next instruction, when it was skipped <- next block
+ --------------------------------------------------------
+
+ Note that the two last blocks are only necessary when laziness is used. Otherwise, the first of
+ them will remain empty.
+ */
public void translate() {
- //conditionals are implemented easily: if the condition does not hold, then just
- //jump to the block following the conditional instruction
- OPT_BasicBlock nextInstruction = arm2ir.getNextBlock();
- OPT_BasicBlock condBlock = arm2ir.createBlockAfterCurrent();
- arm2ir.getCurrentBlock().deleteNormalOut();
- arm2ir.getCurrentBlock().insertOut(nextInstruction);
- arm2ir.getCurrentBlock().insertOut(condBlock);
+
+ OPT_BasicBlock blockThatChecksCondition = arm2ir.getCurrentBlock();
+ OPT_BasicBlock nextInstruction_InstructionSkipped = arm2ir.getNextBlock();
+ OPT_BasicBlock nextInstruction_InstructionNotSkipped = arm2ir.createBlockAfterCurrent();
+ OPT_BasicBlock condInstructionBlock = arm2ir.createBlockAfterCurrent();
+
+ //prepare to translate the actual condition
+ arm2ir.setCurrentBlock(blockThatChecksCondition);
+ blockThatChecksCondition.deleteNormalOut();
+ blockThatChecksCondition.insertOut(nextInstruction_InstructionSkipped);
+ blockThatChecksCondition.insertOut(condInstructionBlock);
//Query the branch profile to get the probability that this instruction is going to get executed
OPT_BranchProfileOperand profileOperand;
- if (DBT_Options.optimizeTranslationByProfiling) {
- float skipProbability = ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4));
+ float skipProbability = getSkipProbability();
- if (skipProbability == -1 || skipProbability == 0.5f) {
- profileOperand = new OPT_BranchProfileOperand();
- }
- else if (skipProbability > 0.8f) {
- profileOperand = OPT_BranchProfileOperand.always();
- condBlock.setInfrequent();
- }
- else if (skipProbability > 0.5f) {
- profileOperand = OPT_BranchProfileOperand.likely();
- condBlock.setInfrequent();
- }
- else if (skipProbability < 0.2f) {
- profileOperand = OPT_BranchProfileOperand.never();
- }
- else {
- profileOperand = OPT_BranchProfileOperand.unlikely();
- }
+ if (skipProbability == -1 || skipProbability == 0.5f) {
+ profileOperand = new OPT_BranchProfileOperand();
}
+ else if (skipProbability > 0.8f) {
+ profileOperand = OPT_BranchProfileOperand.always();
+ condInstructionBlock.setInfrequent();
+ }
+ else if (skipProbability > 0.5f) {
+ profileOperand = OPT_BranchProfileOperand.likely();
+ condInstructionBlock.setInfrequent();
+ }
+ else if (skipProbability < 0.2f) {
+ profileOperand = OPT_BranchProfileOperand.never();
+ }
else {
- profileOperand = new OPT_BranchProfileOperand();
+ profileOperand = OPT_BranchProfileOperand.unlikely();
}
switch (condition) {
case AL:
- throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator.");
+ throw new RuntimeException("Unconditional instructions should not be decorated with a ConditionalDecorator.");
case CC:
//return !regs.isCarrySet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getCarryFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readCarryFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
break;
case CS:
//return regs.isCarrySet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getCarryFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readCarryFlag(lazy), OPT_ConditionOperand.EQUAL());
break;
case EQ:
//return regs.isZeroSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getZeroFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readZeroFlag(lazy), OPT_ConditionOperand.EQUAL());
break;
case GE:
//return regs.isNegativeSet() == regs.isOverflowSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL(), arm2ir.getOverflowFlag());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.EQUAL(), arm2ir.readOverflowFlag(lazy));
break;
case GT:
- translateCondition_GT(nextInstruction, profileOperand);
+ translateCondition_GT(nextInstruction_InstructionSkipped, profileOperand);
break;
case HI:
- translateCondition_HI(nextInstruction, profileOperand);
+ translateCondition_HI(nextInstruction_InstructionSkipped, profileOperand);
break;
case LE:
- translateCondition_LE(nextInstruction, profileOperand);
+ translateCondition_LE(nextInstruction_InstructionSkipped, profileOperand);
break;
case LS:
- translateCondition_LS(nextInstruction, profileOperand, condBlock);
+ translateCondition_LS(nextInstruction_InstructionSkipped, profileOperand, condInstructionBlock);
break;
case LT:
//return regs.isNegativeSet() != regs.isOverflowSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.getOverflowFlag());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.readOverflowFlag(lazy));
break;
case MI:
//return regs.isNegativeSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.EQUAL());
break;
case NE:
//return !regs.isZeroSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getZeroFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readZeroFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
break;
case NV:
//never execute this instruction
- translateCondition(nextInstruction, profileOperand, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL());
break;
case PL:
//return !regs.isNegativeSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
break;
case VC:
//return !regs.isOverflowSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getOverflowFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readOverflowFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
break;
case VS:
//return regs.isOverflowSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getOverflowFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readOverflowFlag(lazy), OPT_ConditionOperand.EQUAL());
break;
default:
throw new RuntimeException("Unexpected condition code: " + condition);
- }
+ }
+
+ //Translate the conditional instruction first to see if the lazy state is changed by the
+ //conditional instruction
+ ARM_Laziness lazinessWhenInstructionSkipped = (ARM_Laziness)lazy.clone();
- arm2ir.setCurrentBlock(condBlock);
+ arm2ir.setCurrentBlock(condInstructionBlock);
+ arm2ir.setNextBlock(nextInstruction_InstructionNotSkipped);
conditionalInstruction.translate();
+
+ int followingInstructionAddress = pc + (inThumb() ? 2 : 4);
+
+ //yes it did, so we may need to translate the successor instruction twice
+ if (assumeInstructionWillBeSkipped()) {
+
+ //Did the laziness change during the translation?
+ if (!lazy.equivalent(lazinessWhenInstructionSkipped)) {
+ //Modify block 3 so that it resolves the different laziness correctly
+ arm2ir.setCurrentBlock(nextInstruction_InstructionNotSkipped);
+ nextInstruction_InstructionNotSkipped.deleteNormalOut();
+ arm2ir.appendBranch(followingInstructionAddress, lazy);
+ lazy.set(lazinessWhenInstructionSkipped);
+ }
+
+ arm2ir.setNextBlock(nextInstruction_InstructionSkipped);
+
+ }
+ else {
+ //Modify block 4 so that it resolves the different laziness correctly
+ arm2ir.setCurrentBlock(nextInstruction_InstructionSkipped);
+ nextInstruction_InstructionSkipped.deleteNormalOut();
+ arm2ir.appendBranch(followingInstructionAddress, lazinessWhenInstructionSkipped);
+
+ arm2ir.setNextBlock(nextInstruction_InstructionNotSkipped);
+ }
}
private void translateCondition(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability, OPT_Operand operand, OPT_ConditionOperand condition) {
@@ -878,8 +960,8 @@
private void translateCondition_HI(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return regs.isCarrySet() && !regs.isZeroSet();
- OPT_Operand carry = arm2ir.getCarryFlag();
- OPT_Operand zero = arm2ir.getZeroFlag();
+ OPT_Operand carry = arm2ir.readCarryFlag(lazy);
+ OPT_Operand zero = arm2ir.readZeroFlag(lazy);
OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean();
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, carry,
@@ -890,33 +972,20 @@
private void translateCondition_LS(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability, OPT_BasicBlock actualInstruction) {
//return !regs.isCarrySet() || regs.isZeroSet();
- OPT_Operand carry = arm2ir.getCarryFlag();
- OPT_Operand zero = arm2ir.getZeroFlag();
+ OPT_Operand carry = arm2ir.readCarryFlag(lazy);
+ OPT_Operand zero = arm2ir.readZeroFlag(lazy);
OPT_RegisterOperand result = arm2ir.getTempInt(0);
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, carry, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), skipProbability));
-
-/* cond1.deleteNormalOut();
- cond1.insertOut(cond2);
- cond1.insertOut(actualInstruction);
-
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), carry, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), actualInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
-
- arm2ir.setCurrentBlock(cond2);
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), actualInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
- arm2ir.appendInstruction(Goto.create(GOTO, nextInstruction.makeJumpTarget()));
- cond2.deleteNormalOut();
- cond2.insertOut(nextInstruction);
- cond2.insertOut(actualInstruction);*/
}
private void translateCondition_GT(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet();
- OPT_Operand negative = arm2ir.getNegativeFlag();
- OPT_Operand overflow = arm2ir.getOverflowFlag();
- OPT_Operand zero = arm2ir.getZeroFlag();
+ OPT_Operand negative = arm2ir.readNegativeFlag(lazy);
+ OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
+ OPT_Operand zero = arm2ir.readZeroFlag(lazy);
OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean();
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, negative,
@@ -927,9 +996,9 @@
private void translateCondition_LE(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet());
- OPT_Operand negative = arm2ir.getNegativeFlag();
- OPT_Operand overflow = arm2ir.getOverflowFlag();
- OPT_Operand zero = arm2ir.getZeroFlag();
+ OPT_Operand negative = arm2ir.readNegativeFlag(lazy);
+ OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
+ OPT_Operand zero = arm2ir.readZeroFlag(lazy);
OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean();
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, negative,
@@ -1021,21 +1090,8 @@
* The add's right-hand-side operator.
*/
protected final void setAddFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) {
- //set the carry flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), result.copy(), lhs.copy(), OPT_ConditionOperand.LOWER(), new OPT_BranchProfileOperand()));
- //set the overflow flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs.copy(), rhs.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
-
- //set the negative flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
-
- //set the zero flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ arm2ir.appendAddFlags(lazy, result, lhs, rhs);
}
/** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/
@@ -1077,22 +1133,8 @@
* The sub's right-hand-side operator.
*/
protected final void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) {
- //set the carry flag to not(Borrow)
- OPT_ConditionOperand notBorrowFromSub = OPT_ConditionOperand.BORROW_FROM_SUB().flipCode();
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs.copy(), rhs.copy(), notBorrowFromSub, new OPT_BranchProfileOperand()));
- //set the overflow flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs.copy(), rhs.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely()));
-
- //set the negative flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
-
- //set the zero flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ arm2ir.appendSubFlags(lazy, result, lhs, rhs);
}
public Condition getCondition() {
@@ -1165,13 +1207,8 @@
protected final void setLogicalFlags(OPT_Operand result) {
//the shifter carry out has already been set during the resolve-phase
- //set the negative flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
-
- //set the zero flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ //set the negative & zero flag
+ arm2ir.appendLogicalFlags(lazy, result);
}
}
@@ -1287,7 +1324,7 @@
//Is the carry set at all? if not, just jump to addWithoutCarry
arm2ir.appendInstruction(Binary.create(INT_ADD, result, operand1, operand2));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.readCarryFlag(lazy), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand()));
arm2ir.getCurrentBlock().insertOut(addWithCarry);
//Yes, the carry flag is set. Pre-increase the result by one to account for the carry.
@@ -1318,7 +1355,7 @@
//Is the carry set? if yes, just jump to subWithoutCarry
arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), subWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.readCarryFlag(lazy), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), subWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand()));
arm2ir.getCurrentBlock().insertOut(subWithCarry);
//No, the carry flag is not set. That means, we have to use the carry within the subtraction (weird arm logic).
@@ -1674,41 +1711,7 @@
//first translate the register write back
translateWriteback(startAddress.copyRO(), nextAddress.copyRO());
-
- //shall we switch to thumb mode?
- /*OPT_BasicBlock finishInstruction = arm2ir.createBlockAfterCurrentNotInCFG();
- OPT_BasicBlock switchToARMBlock = arm2ir.createBlockAfterCurrentNotInCFG();
- OPT_BasicBlock switchToThumbBlock = arm2ir.createBlockAfterCurrentNotInCFG();
-
- //Current block
- OPT_BasicBlock currentBlock = arm2ir.getCurrentBlock();
- currentBlock.deleteNormalOut();
- currentBlock.insertOut(switchToARMBlock);
- currentBlock.insertOut(switchToThumbBlock);
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), regPC.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.BIT_TEST(), switchToThumbBlock.makeJumpTarget(), OPT_BranchProfileOperand.never()));
- arm2ir.appendInstruction(Goto.create(GOTO, switchToARMBlock.makeJumpTarget()));
-
- //Yes, switch to thumb mode
- arm2ir.setCurrentBlock(switchToThumbBlock);
- switchToThumbBlock.insertOut(finishInstruction);
- OPT_Instruction call_setThumbMode = createCallToRegisters("setThumbMode", "(Z)V", 1);
- Call.setParam(call_setThumbMode, 1, new OPT_IntConstantOperand(1));
- arm2ir.appendCustomCall(call_setThumbMode);
- arm2ir.appendInstruction(Goto.create(GOTO, finishInstruction.makeJumpTarget()));
- //No, don't switch to thumb mode
- arm2ir.setCurrentBlock(switchToARMBlock);
- switchToARMBlock.insertOut(finishInstruction);
- arm2ir.appendInstruction(Binary.create(INT_AND, regPC.copyRO(), regPC.copy(), new OPT_IntConstantOperand(0xFFFFFFFE)));
- OPT_Instruction call_setArmMode = createCallToRegisters("setThumbMode", "(Z)V", 1);
- Call.setParam(call_setArmMode, 1, new OPT_IntConstantOperand(0));
- arm2ir.appendCustomCall(call_setArmMode);
- arm2ir.appendInstruction(Goto.create(GOTO, finishInstruction.makeJumpTarget()));
-
- //according to the APCS, these types of instructions are usually function returns
- arm2ir.setCurrentBlock(finishInstruction);
- arm2ir.appendBranch(regPC, lazy, BranchType.RETURN);*/
-
arm2ir.appendBranch(regPC, lazy, BranchType.RETURN);
return;
}
@@ -1940,13 +1943,8 @@
}
if (i.updateConditionCodes) {
- //set the negative flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
-
- //set the zero flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ //set the negative & zero flag
+ arm2ir.appendLogicalFlags(lazy, result);
}
}
@@ -2006,13 +2004,13 @@
}
if (i.updateConditionCodes) {
- //set the negative flag
+ //set the negative flag
arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_LONG, arm2ir.getNegativeFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+ BOOLEAN_CMP_LONG, arm2ir.writeNegativeFlag(lazy), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
//set the zero flag
arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_LONG, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ BOOLEAN_CMP_LONG, arm2ir.writeZeroFlag(lazy), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
}
}
@@ -2223,6 +2221,7 @@
//do we actually have to perform the rotation?
arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), rotation.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), rotationBlock.makeJumpTarget(), OPT_BranchProfileOperand.never()));
arm2ir.appendInstruction(Goto.create(GOTO, remainderBlock.makeJumpTarget()));
+ arm2ir.getCurrentBlock().insertOut(remainderBlock);
//in case we are performing the rotation...
arm2ir.setCurrentBlock(rotationBlock);
Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java
===================================================================
--- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -247,7 +247,7 @@
* dependencies (unknown branch targets etc.) have been resolved. This function is useful for
* debug purposes.
*/
- protected void printTraceAfterCompletion() {
+ public void printTraceAfterCompletion() {
printTraceAfterCompletionRequested = true;
}
@@ -283,18 +283,9 @@
printTraceAfterCompletionRequested = false;
printNextBlocks(preFillBlock, 50);
}
+
+ ((DBT_Trace) gc.method).setNumberOfInstructions(numberOfInstructions);
}
- /*
- protected final void maximizeBasicBlocks(OPT_IR ir) {
- for (OPT_BasicBlock currBB = ir.cfg.firstInCodeOrder(); currBB != null;) {
- if (currBB.mergeFallThrough(ir)) {
- // don't advance currBB; it may have a new trivial fallthrough to
- // swallow
- } else {
- currBB = currBB.nextBasicBlockInCodeOrder();
- }
- }
- }*/
/**
@@ -759,8 +750,11 @@
* within the code cache c) The trace is already too long d) the branch is
* supposedly a CALL or RETURN
*/
+
+ DBT_Trace compiledTrace = ps.codeCache.tryGet(targetPc);
+
return DBT_Options.singleInstrTranslation == false
- && ps.codeCache.tryGet(targetPc) == null && !shallTraceStop()
+ && (compiledTrace == null || compiledTrace.getNumberOfInstructions() > 20) && !shallTraceStop()
&& jump.type != BranchType.CALL && jump.type != BranchType.RETURN;
}
@@ -789,7 +783,7 @@
if (targetBB != null)
return targetBB;
- if (inlineBranchInstruction(targetPc, jump)) {
+ if (!inlineBranchInstruction(targetPc, jump)) {
// Just exit the trace and continue at the target address in a new trace
if (currentBlock.getNumberOfRealInstructions() != 0) {
@@ -903,7 +897,7 @@
// Copy the value into the register specified by gc.resultReg.
appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(
gc.resultReg, VM_TypeReference.Int), nextPc.copy()));
- resolveLaziness(laziness);
+ resolveLaziness((Laziness)laziness.clone());
appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget()));
currentBlock.deleteNormalOut();
currentBlock.insertOut(finishBlock);
@@ -1305,9 +1299,7 @@
*/
public void appendInterpretedInstruction(int pc, Laziness lazy) {
- if (lazy != null)
- resolveLaziness(lazy);
-
+ resolveLaziness(lazy);
spillAllRegisters();
// Prepare a local variable of type Interpreter
Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java
===================================================================
--- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -97,6 +97,9 @@
*/
public final int pc;
+ /** The number of guest instructions that have been compiled into this trace. */
+ private int numberOfInstructions;
+
/**
* In order to allow arbitrary calls within a trace, we have to store at which bytecode index
* a method is called in which way. This class stores the necessary information. */
@@ -321,4 +324,12 @@
public int getBytecodeLength() {
return 256;
}
+
+ public int getNumberOfInstructions() {
+ return numberOfInstructions;
+ }
+
+ public void setNumberOfInstructions(int numberOfInstructions) {
+ this.numberOfInstructions = numberOfInstructions;
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|