You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
|
Feb
|
Mar
(16) |
Apr
(83) |
May
(27) |
Jun
(14) |
Jul
(11) |
Aug
(22) |
Sep
|
Oct
|
Nov
|
Dec
|
From: <mic...@us...> - 2007-07-09 10:36:57
|
Revision: 149 http://svn.sourceforge.net/pearcolator/?rev=149&view=rev Author: michael_baer Date: 2007-07-09 03:36:57 -0700 (Mon, 09 Jul 2007) Log Message: ----------- Refactorings in org.binarytranslator.generic.decoder: - Renamed classes - Cleaned up interfaces Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_Trace.java Added Paths: ----------- src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java src/org/binarytranslator/generic/decoder/CodeTranslator.java Removed Paths: ------------- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/decoder/DisassembledInstruction.java src/org/binarytranslator/generic/decoder/InstructionDecoder.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-07-09 10:36:57 UTC (rev 149) @@ -6,7 +6,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.classloader.VM_Atom; @@ -17,7 +17,7 @@ import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.ir.*; -public class ARM2IR extends AbstractCodeTranslator implements OPT_HIRGenerator { +public class ARM2IR extends CodeTranslator implements OPT_HIRGenerator { /** Mapping of ARM registers to HIR registers */ private OPT_Register regMap[] = new OPT_Register[16]; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-07-09 10:36:57 UTC (rev 149) @@ -21,6 +21,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; +import org.binarytranslator.generic.decoder.Disassembler; /** * This class transfers an ARM instruction into a human-readable assembly @@ -41,7 +42,7 @@ * The process space from which the instruction is read. * @return A disassembled ARM instruction. */ - public final static DisassembledInstruction disassemble(int address, + public final static Disassembler.Instruction disassemble(int address, ARM_ProcessSpace ps) { Instruction decodedInstruction; @@ -70,7 +71,7 @@ * The instruction that is to be decoded. * @return A human-readable version of the given instruction. */ - final static DisassembledInstruction disassemble( + final static Disassembler.Instruction disassemble( ARM_Instructions.Instruction instruction) { DisassemblingVisitor disassembler = new DisassemblingVisitor(); @@ -81,7 +82,7 @@ /** Represents a disassembled ARM instruction. */ private final static class ARM_DisassembledInstruction implements - DisassembledInstruction { + Disassembler.Instruction { /** A readable version of the diassembled instruction. */ private final String instruction; @@ -129,7 +130,7 @@ ARM_InstructionVisitor { /** This field receives the disassembled instruction. */ - private ARM_DisassembledInstruction result; + private Disassembler.Instruction result; private DisassemblingVisitor() { } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-07-09 10:36:57 UTC (rev 149) @@ -7,13 +7,13 @@ import org.binarytranslator.arch.arm.decoder.ARM_Interpreter; import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace; import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.memory.ByteAddressedMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.vmmagic.pragma.Uninterruptible; public abstract class ARM_ProcessSpace extends ProcessSpace { @@ -49,7 +49,7 @@ * the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new ARM2IR(context, trace); } @@ -73,7 +73,7 @@ } @Override - public Interpreter createInstructionInterpreter() throws UnsupportedOperationException { + public Interpreter createInterpreter() throws UnsupportedOperationException { return new ARM_Interpreter(this); } Modified: src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java 2007-07-09 10:36:57 UTC (rev 149) @@ -111,7 +111,7 @@ int pc = startPC; ps.setCurrentInstructionAddress(startPC); - Interpreter interpreter = ps.createInstructionInterpreter(); + Interpreter interpreter = ps.createInterpreter(); ((ARM_ProcessSpace)ps).registers.set(ARM_Registers.LR, startPC); Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-07-09 10:36:57 UTC (rev 149) @@ -14,7 +14,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.binarytranslator.vmInterface.DBT_Trace; @@ -42,7 +42,7 @@ * * @author Richard Matley, Ian Rogers */ -public final class PPC2IR extends AbstractCodeTranslator implements OPT_HIRGenerator, +public final class PPC2IR extends CodeTranslator implements OPT_HIRGenerator, OPT_Operators, OPT_Constants { // -oO Caches of references to process space entities Oo- Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-07-09 10:36:57 UTC (rev 149) @@ -14,6 +14,7 @@ import org.binarytranslator.arch.ppc.decoder.PPC2IR; import org.binarytranslator.arch.ppc.decoder.PPC_InstructionDecoder; import org.binarytranslator.arch.ppc.os.process.linux.PPC_LinuxProcessSpace; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.memory.ByteAddressedByteSwapMemory; @@ -22,7 +23,6 @@ import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.jikesrvm.ppc.PPC_Disassembler; import org.vmmagic.pragma.Uninterruptible; @@ -140,7 +140,7 @@ * the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new PPC2IR(context, trace); } Modified: src/org/binarytranslator/arch/x86/decoder/X862IR.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-07-09 10:36:57 UTC (rev 149) @@ -13,7 +13,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.binarytranslator.vmInterface.DBT_Trace; @@ -25,7 +25,7 @@ import org.jikesrvm.compilers.opt.OPT_Constants; import org.jikesrvm.compilers.opt.ir.*; -public class X862IR extends AbstractCodeTranslator implements OPT_HIRGenerator, +public class X862IR extends CodeTranslator implements OPT_HIRGenerator, OPT_Operators, OPT_Constants { private static final VM_TypeReference psTref; Added: src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java (rev 0) +++ src/org/binarytranslator/arch/x86/decoder/X86_AbstractInstructionDecoder.java 2007-07-09 10:36:57 UTC (rev 149) @@ -0,0 +1,59 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ +package org.binarytranslator.arch.x86.decoder; + +import org.binarytranslator.generic.os.process.ProcessSpace; +import org.binarytranslator.generic.decoder.CodeTranslator; +import org.binarytranslator.generic.fault.BadInstructionException; + +/** + * A decoder is a class capable of translating, interpretting or disassembling + * an instruction + */ +public abstract class X86_AbstractInstructionDecoder { + /** + * Translate a single instruction + * + * @param translationHelper + * the object containing the translation sequence + * @param ps + * the process space of the translation + * @param pc + * the address of the instruction to translate + * @return the address of the next instruction or -1 if this instruction has + * branched to the end of the trace + */ + public int translate(CodeTranslator translationHelper, ProcessSpace ps, + Object lazy, int pc) { + throw new Error("TODO"); + } + + /** + * Interpret a single instruction + * + * @param ps + * the process space of the interpretation, contains the fetched + * instruction and instruction address + * @return the next instruction interpreter + */ + public X86_AbstractInstructionDecoder interpret(ProcessSpace ps) + throws BadInstructionException { + throw new Error("TODO"); + } + + /** + * Disassemble an instruction + * + * @param ps + */ + public String disassemble(ProcessSpace ps) { + // In general this isn't complete + throw new Error("Disassembly not yet complete"); + } +} Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-09 10:36:57 UTC (rev 149) @@ -12,7 +12,6 @@ import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; -import org.binarytranslator.generic.decoder.InstructionDecoder; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; @@ -22,7 +21,7 @@ /** * Decoder for X86 instructions */ -public class X86_InstructionDecoder extends InstructionDecoder { +public class X86_InstructionDecoder extends X86_AbstractInstructionDecoder { /* * Process defaults @@ -711,7 +710,7 @@ * instruction and instruction address * @return the next instruction interpreter */ - public InstructionDecoder interpret(ProcessSpace ps, int pc) + public X86_AbstractInstructionDecoder interpret(ProcessSpace ps, int pc) throws BadInstructionException { X86_InstructionDecoder decoder = getDecoder(ps, pc); System.err.println("Attempt to interpret " + decoder.disassemble(ps, pc)); Modified: src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java 2007-07-09 10:36:57 UTC (rev 149) @@ -10,7 +10,7 @@ import org.binarytranslator.arch.x86.os.process.X86_Registers; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.decoder.Laziness; /** @@ -386,7 +386,7 @@ * Get the RM field as a decoded operand, the RM field encodes either a * register or memory location */ - X86_DecodedOperand getRM(AbstractCodeTranslator translationHelper, Laziness lazy, + X86_DecodedOperand getRM(CodeTranslator translationHelper, Laziness lazy, X86_SIB_Decoder sib, int displacement, int operandSize, int addressSize, int segment) { if (addressSize == 32) { Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-07-09 10:36:57 UTC (rev 149) @@ -12,11 +12,11 @@ import java.util.Hashtable; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.generic.memory.ByteAddressedMemory; +import org.binarytranslator.generic.decoder.CodeTranslator; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; @@ -149,7 +149,7 @@ * @param context the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) { return new X862IR(context, trace); } Deleted: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-07 00:27:13 UTC (rev 148) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-09 10:36:57 UTC (rev 149) @@ -1,1479 +0,0 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.generic.decoder; - -import java.util.Enumeration; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -import org.binarytranslator.DBT; -import org.binarytranslator.DBT_Options; -import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; -import org.binarytranslator.generic.decoder.Laziness.Key; -import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.generic.os.process.ProcessSpace; -import org.binarytranslator.vmInterface.DBT_Trace; -import org.jikesrvm.classloader.VM_Atom; -import org.jikesrvm.classloader.VM_BytecodeConstants; -import org.jikesrvm.classloader.VM_Class; -import org.jikesrvm.classloader.VM_MemberReference; -import org.jikesrvm.classloader.VM_Method; -import org.jikesrvm.classloader.VM_MethodReference; -import org.jikesrvm.classloader.VM_TypeReference; -import org.jikesrvm.compilers.opt.OPT_Constants; -import org.jikesrvm.compilers.opt.ir.Athrow; -import org.jikesrvm.compilers.opt.ir.BBend; -import org.jikesrvm.compilers.opt.ir.Call; -import org.jikesrvm.compilers.opt.ir.Goto; -import org.jikesrvm.compilers.opt.ir.IfCmp; -import org.jikesrvm.compilers.opt.ir.IfCmp2; -import org.jikesrvm.compilers.opt.ir.LookupSwitch; -import org.jikesrvm.compilers.opt.ir.Move; -import org.jikesrvm.compilers.opt.ir.New; -import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand; -import org.jikesrvm.compilers.opt.ir.OPT_BasicBlock; -import org.jikesrvm.compilers.opt.ir.OPT_BranchOperand; -import org.jikesrvm.compilers.opt.ir.OPT_BranchProfileOperand; -import org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand; -import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_Instruction; -import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; -import org.jikesrvm.compilers.opt.ir.OPT_MethodOperand; -import org.jikesrvm.compilers.opt.ir.OPT_Operand; -import org.jikesrvm.compilers.opt.ir.OPT_Operator; -import org.jikesrvm.compilers.opt.ir.OPT_Operators; -import org.jikesrvm.compilers.opt.ir.OPT_Register; -import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; -import org.jikesrvm.compilers.opt.ir.OPT_TrueGuardOperand; -import org.jikesrvm.compilers.opt.ir.OPT_TypeOperand; - -/** - * A collection of common tools used by decoders. The public entry point for the - * translators is generateHIR(OPT_GenerationContext gc). - * - * <dl> - * <dt>Description of the translation algorithm</dt> - * <dd> - * <ol> - * <li>The translation is set up so that the start and end blocks are created. - * The start block branches to a prefill block that loads all the register - * values</li> - * <li>Translation starts from the PC value given in the DBT_Trace.</li> - * <li>Translation translates subject instructions to HIR using the - * translateInstruction method. This and the derived decoder object contain the - * utilities required to aid an instruction translation.</li> - * <li>The trace ends when the branch prediction deems it necessary. The - * closing basic blocks are generated and things are wrapped up.</li> - * </ol> - * </dd> - * </dl> - */ -public abstract class AbstractCodeTranslator implements OPT_Constants, - OPT_Operators { - - /** The trace that we're currently translating code for. */ - protected final DBT_Trace trace; - - /** VM_TypeReference of org.binarytranslator.generic.os.process.ProcessSpace */ - private static final VM_TypeReference psTref; - - /** Method ProcessSpace.doSysCall */ - public static final VM_Method sysCallMethod; - - /** VM_TypeReference of org.binarytranslator.generic.fault.BadInstructionException */ - public static final VM_Class badInstrKlass; - - /** Method BadInstructionException.<init> */ - public static final VM_Method badInstrKlassInitMethod; - - /** Method ProcessSpace.recordUncaughtBranchBadInstructionException.<init> */ - public static final VM_Method recordUncaughtBranchMethod; - - static { - psTref = VM_TypeReference.findOrCreate(ProcessSpace.class); - VM_MethodReference sysCallMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(psTref, VM_Atom.findOrCreateAsciiAtom("doSysCall"), - VM_Atom.findOrCreateAsciiAtom("()V")); - sysCallMethod = sysCallMethRef.resolveInvokeSpecial(); - - badInstrKlass = VM_TypeReference.findOrCreate(BadInstructionException.class).resolve().asClass(); - - VM_MethodReference badInstrKlassInitMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate( - badInstrKlass.getTypeRef(), - VM_Atom.findOrCreateAsciiAtom("<init>"), - VM_Atom - .findOrCreateAsciiAtom("(ILorg/binarytranslator/generic/os/process/ProcessSpace;)V")); - badInstrKlassInitMethod = badInstrKlassInitMethRef.resolveInvokeSpecial(); - - VM_MethodReference recordUncaughtBranchMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(psTref, VM_Atom - .findOrCreateAsciiAtom("recordUncaughtBranch"), VM_Atom - .findOrCreateAsciiAtom("(IIII)V")); - recordUncaughtBranchMethod = recordUncaughtBranchMethRef - .resolveInvokeSpecial(); - } - - /** Number of translated instructions */ - private int numberOfInstructions; - - /** The process space object used by the running binary. */ - public final ProcessSpace ps; - - /** The VM method's generation context. */ - protected OPT_GenerationContext gc; - - /** The OPT_BasicBlock in which instructions are currently being inserted */ - protected OPT_BasicBlock currentBlock; - - /** The pc value corresponding to the instruction currently being translated */ - protected int currentPC; - - /** The pc value of the first instruction in the trace */ - protected int startingPC; - - /** The OPT_BasicBlock which will contain the next translated instruction */ - protected OPT_BasicBlock nextBlock; - - /** - * The basic block is used by finish trace to hold all the code that must be - * executed before returning to the main run loop - */ - protected OPT_BasicBlock finishBlock; - - /** - * This block gets instructions to pre-fill registers inserted into it. - */ - protected OPT_BasicBlock preFillBlock; - - /** - * This variable is being set by a call to {@link #printTraceAfterCompletion()} and notifies - * the system that the current trace shall be printed, after it has been completed. */ - private boolean requestPrintTrace; - - /** Map to locate HIR basic blocks to re-use translation within a trace */ - protected final HashMap<Laziness.Key, OPT_BasicBlock> blockMap; - - /** This class stores information about a jump instruction within the current trace, whose - * target has not yet been resolved. */ - private final static class UnresolvedJumpInstruction { - - /** A reference to the jump instruction within the code. This is either a GOTO or SWITCH instruction. */ - public final OPT_Instruction instruction; - - /** The lazy state at the jump location. */ - public final Laziness lazyStateAtJump; - - /** Stores the target of the jump instruction or -1, if this value is unknown. */ - public final int targetPC; - - /** Stores the address, at which the jump occurs*/ - public final int pc; - - /** Identifies the type of branch. */ - public final BranchType type; - - public UnresolvedJumpInstruction(OPT_Instruction instruction, - Laziness lazyStateAtJump, int pc, int targetPC, BranchType type) { - this.instruction = instruction; - this.lazyStateAtJump = lazyStateAtJump; - this.pc = pc; - this.type = type; - this.targetPC = targetPC; - } - } - - /** - * List of unresolved direct branches. The destinations of direct branches are - * already known at translation time. */ - private final List<UnresolvedJumpInstruction> unresolvedDirectBranches; - - /** - * List of unresolved dynamic branches. Dynamics branches have a destination - * address that is only determined at runtime. */ - private final List<UnresolvedJumpInstruction> unresolvedDynamicBranches; - - /** - * Constructor - * - * @param context - * The JRVM generation context for this trace. - */ - protected AbstractCodeTranslator(OPT_GenerationContext context, - DBT_Trace trace) { - - // Store the trace that we're invoked from - this.trace = trace; - - // Make copies of popular variables - gc = context; - ps = ((DBT_Trace) (gc.method)).ps; - currentPC = ((DBT_Trace) (gc.method)).pc; - startingPC = currentPC; - - // Number of translated instructions - numberOfInstructions = 0; - - // Create map of (PC & laziness) -> OPT_BasicBlock - blockMap = new HashMap<Key, OPT_BasicBlock>(); - - // Create preFillBlock, currentBlock and finishBlock - gc.prologue.insertOut(gc.epilogue); - preFillBlock = createBlockAfter(gc.prologue); - currentBlock = createBlockAfter(preFillBlock); - finishBlock = createBlockAfterCurrent(); - - // Fix up stores - unresolvedDirectBranches = new LinkedList<UnresolvedJumpInstruction>(); - unresolvedDynamicBranches = new LinkedList<UnresolvedJumpInstruction>(); - } - - /** Returns the number of previously translated instructions within this trace. */ - public int getNumInstructions() { - return numberOfInstructions; - } - - /** - * Deriving classes may call this method if they want to print the current trace after all - * dependencies (unknown branch targets etc.) have been resolved. This function is useful for - * debug purposes. - */ - protected void printTraceAfterCompletion() { - requestPrintTrace = true; - } - - /** This is the main loop, which generates the HIR. */ - public void generateHIR() { - // Load all the register values to be used in a trace - preFillAllRegisters(); - - // Translate from the current program counter - translateSubTrace(createInitialLaziness(), currentPC); - - // Translating the subtrace finished so resolve any unresolved branches - - while (unresolvedDirectBranches.size() > 0 || unresolvedDynamicBranches.size() > 0) { - // Resolve all open direct branches first - resolveAllDirectBranches(); - - // Resolve unresolved dynamic jumps - resolveAllDynamicBranches(); - } - - // Finish up the trace - finishTrace(); - - if (DBT_Options.eliminateRegisterFills) { - eliminateRegisterFills(getUnusedRegisters()); - } - - if (requestPrintTrace) { - requestPrintTrace = false; - printNextBlocks(preFillBlock, 50); - } - - // TODO: maximizeBasicBlocks() - } - - /** - * Translate a sequence of instructions upto an instruction that doesn't know - * its immediate/default successor. The currentBlock should be an empty basic - * block. - */ - private void translateSubTrace(Laziness lazy, int pc) { - currentPC = pc; - - if (shallTraceStop()) { - // Record mapping of this pc value and laziness to this block - registerMapping(pc, lazy, currentBlock); - // Create next block - nextBlock = createBlockAfterCurrent(); - // Finish block to return and exit - appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); - // Move currentBlock along - currentBlock = nextBlock; - } else { - do { - if (DBT.VerifyAssertions) - DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); - - // Record mapping of this pc value and laziness to this block - registerMapping(pc, lazy, currentBlock); - - // Create next block - nextBlock = createBlockAfterCurrent(); - - // Translare instruction and get address of next instruction - pc = translateInstruction(lazy, pc); - numberOfInstructions++; - - // Move currentBlock along - currentBlock = nextBlock; - currentPC = pc; - - if (DBT.VerifyAssertions) - DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); - - // Are we translating in single instruction mode - if (DBT_Options.singleInstrTranslation == true) { - if (pc != -1) { - appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); - } - - break; - } - - // Do we already have a translation for this next block? - OPT_BasicBlock possibleNextBlock = findMapping(pc, lazy); - if (possibleNextBlock != null) { - // Yes, branch to that and stop translating - appendInstruction(Goto.create(GOTO, possibleNextBlock - .makeJumpTarget())); - OPT_BasicBlock gotoBlock = currentBlock; - currentBlock = createBlockAfterCurrent(); - gotoBlock.deleteNormalOut(); - gotoBlock.insertOut(possibleNextBlock); - if (DBT.VerifyAssertions) - DBT._assert(gotoBlock.getNumberOfNormalOut() == 1); - break; - } - } while (pc != -1); - } - } - - /** - * Get the block which is currently having instructions inserted into it - * - * @return the current block - */ - public OPT_BasicBlock getCurrentBlock() { - return currentBlock; - } - - /** - * Get the block which will contain the translation of the next PPC - * instruction - * - * @return the next block - */ - public OPT_BasicBlock getNextBlock() { - return nextBlock; - } - - /** - * Set the block which is currently having instructions inserted into it - * - * @param newCurrentBlock - * the new current basic block - */ - public void setCurrentBlock(OPT_BasicBlock newCurrentBlock) { - currentBlock = newCurrentBlock; - } - - /** - * Set the block which will contain the translation of the next PPC - * instruction - * - * @param newCurrentBlock - * the new next basic block - */ - public void setNextBlock(OPT_BasicBlock newNextBlock) { - nextBlock = newNextBlock; - } - - /** - * Create a basic block immediately after the current block and link its edges - * into the CFG and code ordering - * - * @return the new basic block - */ - public OPT_BasicBlock createBlockAfterCurrent() { - OPT_BasicBlock nxtBlock = currentBlock.nextBasicBlockInCodeOrder(); - OPT_BasicBlock newBlock = new OPT_BasicBlock(0, gc.inlineSequence, gc.cfg); - - gc.cfg.breakCodeOrder(currentBlock, nxtBlock); - gc.cfg.linkInCodeOrder(currentBlock, newBlock); - gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - - /* - * if (DBT.VerifyAssertions) DBT._assert(currentBlock.isOut(nxtBlock)); - */ - - if (currentBlock.isOut(nxtBlock)) { - currentBlock.deleteOut(nxtBlock); - currentBlock.insertOut(newBlock); - newBlock.insertOut(nxtBlock); - } else { - currentBlock.insertOut(newBlock); - } - - if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, - currentBlock)); - } - - return newBlock; - } - - /** - * Create a basic block immediately after the current block and link its edges - * into code ordering but not the CFG - * - * @return the new basic block - */ - public OPT_BasicBlock createBlockAfterCurrentNotInCFG() { - OPT_BasicBlock nxtBlock = currentBlock.nextBasicBlockInCodeOrder(); - OPT_BasicBlock newBlock = new OPT_BasicBlock(0, gc.inlineSequence, gc.cfg); - - gc.cfg.breakCodeOrder(currentBlock, nxtBlock); - gc.cfg.linkInCodeOrder(currentBlock, newBlock); - gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - - if (DBT_Options.debugCFG) { - report(String.format("Created non-cfg block (%s) after current (%s).", - newBlock, currentBlock)); - } - return newBlock; - } - - /** - * Create a basic block immediately after the given block and link its edges - * into the CFG and code ordering - * - * @param afterBlock - * The block after which the new block is to be created. - * @return the new basic block - */ - public OPT_BasicBlock createBlockAfter(OPT_BasicBlock afterBlock) { - OPT_BasicBlock nxtBlock = afterBlock.nextBasicBlockInCodeOrder(); - OPT_BasicBlock newBlock = new OPT_BasicBlock(0, gc.inlineSequence, gc.cfg); - - gc.cfg.breakCodeOrder(afterBlock, nxtBlock); - gc.cfg.linkInCodeOrder(afterBlock, newBlock); - gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - - if (DBT.VerifyAssertions) - DBT._assert(afterBlock.isOut(nxtBlock)); - afterBlock.deleteOut(nxtBlock); - afterBlock.insertOut(newBlock); - newBlock.insertOut(nxtBlock); - - if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, - afterBlock)); - } - - return newBlock; - } - - /** - * Append a HIR instruction to the current basic block - * - * @param i - * The instruciton that is to be appended to the current bloc. - */ - public void appendInstruction(OPT_Instruction i) { - if (i.bcIndex == UNKNOWN_BCI) { - i.position = gc.inlineSequence; - // we only have 16bits to distinguish instructions (the bcIndex - // is effective 16bit when stored in the machine code map), - // Intel can't distinguish branches within 16bytes, so neither - // can we, the top bit is saved for distinguished addresses we - // need to know to dynamically link things - i.bcIndex = ((currentPC - startingPC) >> 4) & 0x7FFF; - } - currentBlock.appendInstruction(i); - } - - /** - * Generate a branch profile operand for the current instruction - * - * @param likely - * Does this branch have a likely hint? - */ - public OPT_BranchProfileOperand getConditionalBranchProfileOperand( - boolean likely) { - return gc.getConditionalBranchProfileOperand( - ((currentPC - startingPC) >> 4) & 0x7FFF, likely); - } - - /** - * We're finished translating this trace so .. 1) put all the registers back - * into the process space 2) return the new PC value - */ - protected void finishTrace() { - // finishBlock is already linked into the cfg, we just need to - // make sure we are adding to it. - currentBlock = finishBlock; - spillAllRegisters(); - } - - /** - * Get the generation context. - */ - public OPT_GenerationContext getGenerationContext() { - return gc; - } - - /** - * Register a mapping between a pc and lazy and a hir block - * - * @param pc - * The program counter whose translation the basic bock represents. - * @param lazy - * The lazy state that is assumed for this basic block. - * @param hirBlock - * The block that is to be registered. - */ - protected void registerMapping(int pc, Laziness lazy, OPT_BasicBlock hirBlock) { - blockMap.put(lazy.makeKey(pc), hirBlock); - } - - /** - * Find if there's already a translation for a given pc and laziness - * - * @param pc - * The program counter address at which the returned basic block - * shall start. - * @param lazy - * The lazy state assumed within the returned trace. - * @return An appropriate basic block or null if no translation exists. - */ - protected OPT_BasicBlock findMapping(int pc, Laziness lazy) { - return blockMap.get(lazy.makeKey(pc)); - } - - /** - * Create a HIR Goto instruction that jumps to the address - * <code>targetPc</code>. There's a caveat on using this that there are no - * other out edges for this BB. - * - * @param targetPC - * The address where we shall jump to. - * @param targetLaziness - * The current at the point of jump. - */ - public void appendBranch(int targetPC, Laziness targetLaziness) { - - appendStaticBranch(Goto.create(GOTO, null), targetPC, targetLaziness, BranchType.DIRECT_BRANCH, -1); - } - - /** - * Appends the conditional branch instruction <code>conditional</code> that jumps to the address - * <code>targetPc</code> to the current block. - * - * @param targetPC - * The address where we shall jump to. - * @param targetLaziness - * The current at the point of jump. - */ - public void appendConditionalBranch(OPT_Instruction conditional, int targetPC, Laziness targetLaziness) { - - if (DBT.VerifyAssertions) DBT._assert(IfCmp.conforms(conditional) || IfCmp2.conforms(conditional)); - appendStaticBranch(conditional, targetPC, targetLaziness, BranchType.DIRECT_BRANCH, -1); - } - - /** - * Create a HIR Goto instruction that jumps to the address - * <code>targetPc</code>. There's a caveat on using this that there are no - * other out edges for this BB. - * - * @param targetPC - * The address where we shall jump to. - * @param targetLaziness - * The current at the point of jump. - * @param branchType - * The type of branch that best describes this jump. - */ - public void appendCall(int targetPC, Laziness targetLaziness, int retAddr) { - - appendStaticBranch(Goto.create(GOTO, null), targetPC, targetLaziness, BranchType.CALL, retAddr); - } - - private void appendStaticBranch(OPT_Instruction branch, int targetPC, Laziness targetLaziness, BranchType branchType, int retAddr) { - // Place a GOTO instruction at this point. However, this instruction - // serves more as a placeholder and might be mutated later on. - appendInstruction(branch); - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction( - branch, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL); - unresolvedDirectBranches.add(unresolvedJump); - - if (branchType == BranchType.CALL) - ps.branchInfo.registerCall(currentPC, targetPC, retAddr); - else - if (branchType == BranchType.RETURN) - ps.branchInfo.registerReturn(currentPC, targetPC); - else - ps.branchInfo.registerBranch(currentPC, targetPC, branchType); - } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param retAddr - * The address, to which the function call will (most likely) return. - */ - public void appendCall(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, int retAddr) { - - appendDynamicBranch(targetAddress, lazyStateAtJump, BranchType.CALL, retAddr); - } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param branchType - * The type of jump. - */ - public void appendBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType) { - - if (DBT.VerifyAssertions && branchType == BranchType.CALL) throw new RuntimeException("Use the more specific appendCall to create dynamic calls."); - - appendDynamicBranch(targetAddress, lazyStateAtJump, branchType, -1); - } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param branchType - * The type of jump. - * @param retAddr - * The address, to which the function call will (most likely) return or an arbitrary value, if - * branchType is not BranchType.CALL. - */ - private void appendDynamicBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType, int retAddr) { - - OPT_BasicBlock fallThrough = createBlockAfterCurrent(); - OPT_Instruction switchInstr; - switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress.copyRO(), null, null, fallThrough.makeJumpTarget(), null, 0); - appendInstruction(switchInstr); - - UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, -1, branchType); - unresolvedDynamicBranches.add(unresolvedInfo); - - setCurrentBlock(fallThrough); - appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType, retAddr); - appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress); - - } - - /** Resolve all unresolved direct branch instructions. */ - private void resolveAllDirectBranches() { - - while (unresolvedDirectBranches.size() > 0) { - - // Get the jump that we're supposed to resolve - UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches.remove(0); - int targetPc = unresolvedInstr.targetPC; - Laziness lazyStateAtJump = unresolvedInstr.lazyStateAtJump; - OPT_Instruction gotoInstr = unresolvedInstr.instruction; - OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, unresolvedInstr); - - if (DBT_Options.debugBranchResolution) { - report("Resolved goto in block " + gotoInstr.getBasicBlock() - + " to " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); - } - - // Fix up instruction - setBranchTarget(gotoInstr, targetBB.makeJumpTarget()); - gotoInstr.getBasicBlock().insertOut(targetBB); - } - } - - /** - * Sets the target of the branching instruction <code>branch</code> to <code>target</code>. - * @param branch - * A branching instruction. Either a Goto or - * @param target - * The jump target. - */ - private void setBranchTarget(OPT_Instruction branch, OPT_BranchOperand target) { - if (Goto.conforms(branch)) { - Goto.setTarget(branch, target); - } - else if (IfCmp.conforms(branch)) { - IfCmp.setTarget(branch, target); - } - else if (IfCmp2.conforms(branch)) { - IfCmp2.setTarget1(branch, target); - } - } - - /** - * This function is being called to decide whether a branch to <code>targetPc</code> (caused by the - * jump instruction <code>jump</code>) shall be inlined into the trace. This function is only called when - * the jump target is not part of the current trace anyway. - * - * This function may be overriden to fine-tune whether certain branches shall be inlined or not. - * - * @param targetPc - * The address that we're jumping to. - * @param jump - * Detailled information describing the jump. - * @return - * True to make the system inline the target of this branch, false otherwise. - */ - protected boolean inlineBranchInstruction(int targetPc, UnresolvedJumpInstruction jump) { - /* - * The target Block is not yet translated. We do not want to inline it - * into the current trace if a) DBT_Options.singleInstrTranslation is - * enabled b) The jump target has already been compiled as a separate method - * within the code cache c) The trace is already too long d) the branch is - * supposedly a CALL or RETURN - */ - return DBT_Options.singleInstrTranslation == false - && ps.codeCache.tryGet(targetPc) == null && !shallTraceStop() - && jump.type != BranchType.CALL && jump.type != BranchType.RETURN; - } - - /** - * Resolves a branch target to an actual basic block. In case the jump target - * is not yet part of this trace, this method also takes a decision about - * whether the target shall be translated into the trace. - * - * Notice that, when {@link DBT_Options#singleInstrTranslation} is turned on, - * this method will always end the current trace, just returning the address - * of the next instruction. - * - * @param targetPc - * The address of the target basic block that. - * @param jump - * The branch instruction that we are trying to resolve. - * @return A basic block that is equivalent to the program counter address - * <code>targetPc</code> in the original binary. - */ - private OPT_BasicBlock resolveBranchTarget(int targetPc, UnresolvedJumpInstruction jump) { - // Resolve the address of the target block - OPT_BasicBlock targetBB = findMapping(targetPc, jump.lazyStateAtJump); - - // If the target is already part of this trace, then just use the - // precompiled target - if (targetBB != null) - return targetBB; - - if (inlineBranchInstruction(targetPc, jump)) { - - // Just exit the trace and continue at the target address in a new trace - if (currentBlock.getNumberOfRealInstructions() != 0) { - currentBlock = createBlockAfterCurrentNotInCFG(); - - if (DBT_Options.debugBranchResolution) - System.out.println("Resolving branch to next block."); - } - - targetBB = currentBlock; - appendTraceExit(jump.lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); - registerMapping(targetPc, jump.lazyStateAtJump, targetBB); - } else { - // Otherwise we will translate the jump into the trace - translateSubTrace((Laziness) jump.lazyStateAtJump.clone(), targetPc); - targetBB = findMapping(targetPc, jump.lazyStateAtJump); - } - - if (DBT.VerifyAssertions) - DBT._assert(targetBB != null); - - return targetBB; - } - - /** - * Resolves all dynamic branches that have been added with - * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. - */ - private void resolveAllDynamicBranches() { - - while (unresolvedDynamicBranches.size() > 0) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.remove(0); - Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - - resolveSingleDynamicJump(unresolvedSwitch, branchDests); - } - } - - /** - * Resolves a single dynamic jump that has previously been created with - * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. - * - * @param lazy - * The lazy state of the jump that is to be resolved. - * @param lookupswitch - * Each dynamic jump is converted to a switch statement. This is the - * switch statement for the current jump. - * @param destinations - * A list of known destinations that this dynamic jumps branches to. - */ - private void resolveSingleDynamicJump( - UnresolvedJumpInstruction unresolvedJump, Set<Integer> destinations) - throws Error { - - if (DBT.VerifyAssertions) - DBT._assert(LookupSwitch.conforms(unresolvedJump.instruction)); - - OPT_Instruction lookupswitch = unresolvedJump.instruction; - OPT_BranchOperand default_target = LookupSwitch.getDefault(lookupswitch); - OPT_Operand value = LookupSwitch.getValue(lookupswitch); - - if (destinations != null && destinations.size() > 0) { - if ((destinations.size() > 1) - || (lookupswitch.getBasicBlock().nextBasicBlockInCodeOrder() != default_target.target - .getBasicBlock())) { - float branchProb = (1.0f - OPT_BranchProfileOperand.UNLIKELY) - / (float) destinations.size(); - LookupSwitch.mutate(lookupswitch, LOOKUPSWITCH, value, null, null, - default_target, OPT_BranchProfileOperand.unlikely(), destinations - .size() * 3); - int match_no = 0; - for (int dest_pc : destinations) { - - OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump); - - LookupSwitch.setMatch(lookupswitch, match_no, - new OPT_IntConstantOperand(dest_pc)); - LookupSwitch.setTarget(lookupswitch, match_no, target - .makeJumpTarget()); - LookupSwitch.setBranchProfile(lookupswitch, match_no, - new OPT_BranchProfileOperand(branchProb)); - lookupswitch.getBasicBlock().insertOut(target); - match_no++; - } - } else { - int dest_pc = destinations.iterator().next(); - - OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump); - - IfCmp.mutate(lookupswitch, INT_IFCMP, null, value, - new OPT_IntConstantOperand(dest_pc), OPT_ConditionOperand.EQUAL(), - target.makeJumpTarget(), OPT_BranchProfileOperand.likely()); - lookupswitch.getBasicBlock().insertOut(target); - } - } else { - //we don't yet know where this jump will go, so just do nothing, which will exit the trace - } - } - - /** - * Set the return value in the currentBlock, resolve its lazy state (so the - * state is no longer lazy) and then set it to branch to the finish block - * - * @param nextPc - * return value for translated code (the PC value of the next - * instruction to translate) - */ - public void appendTraceExit(Laziness laziness, OPT_Operand nextPc) { - - // 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); - appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget())); - currentBlock.deleteNormalOut(); - currentBlock.insertOut(finishBlock); - if (DBT.VerifyAssertions) - DBT._assert(currentBlock.getNumberOfNormalOut() == 1); - } - - /** - * Should the trace be stopped as soon as possible? This function can be used - * to steer how large a single trace may be. Return true if the target size - * for the trace is about to be or has been exceeded. - * - * @return true => try to stop the trace - */ - protected boolean shallTraceStop() { - if (DBT_Options.singleInstrTranslation && (numberOfInstructions >= 1)) { - return true; - } - - switch (gc.options.getOptLevel()) { - case 0: - return numberOfInstructions > DBT_Options.instrOpt0; - case 1: - return numberOfInstructions > DBT_Options.instrOpt1; - default: - return numberOfInstructions > DBT_Options.instrOpt2; - } - } - - /** - * Register a branch and link instruction - * - * @param pc - * the address of the branch instruction - * @param ret - * the address returned to - * @param dest - * the destination of the branch instruction - */ - public void registerBranchAndLink(int pc, int ret, int dest) { - ps.branchInfo.registerCall(pc, ret, dest); - } - - /** - * Returns a vector of likely branch targets for the branch at address - * <code>pc</code>. - * - * @param pc - * The location at which the branch occurs. - * @return A set of likely destinations for that jump. - */ - private Set<Integer> getLikelyJumpTargets(int pc) { - return ps.branchInfo.getKnownBranchTargets(pc); - } - - /** - * Should a trace follow a branch and link instruction or should it terminate - * the trace? - * - * @param pc - * the address of the branch and link instruction - * @return whether the trace should continue - */ - public boolean traceContinuesAfterBranchAndLink(int pc) { - return shallTraceStop() == false; - } - - /** - * Load all the registers from the ProcessSpace into the pre-fill block - */ - private void preFillAllRegisters() { - OPT_BasicBlock temp = currentBlock; - currentBlock = preFillBlock; - fillAllRegisters(); - ps.memory.initTranslate(this); // Set up memory - currentBlock = temp; - } - - /** - * Eliminate unnecessary register spill and fill code - ie a register wasn't - * used so eliminate references to it - */ - protected void eliminateRegisterFills(OPT_Register unusedRegisters[]) { - if (unusedRegisters.length > 0) { - OPT_BasicBlock curBB = gc.prologue; - while (curBB != null) { - OPT_Instruction curInstr = curBB.firstInstruction(); - loop_over_instructions: while (BBend.conforms(curInstr) == false) { - for (Enumeration du = curInstr.getRootOperands(); du - .hasMoreElements();) { - OPT_Operand curOp = (OPT_Operand) du.nextElement(); - if (curOp.isRegister()) { - OPT_Register curReg = curOp.asRegister().register; - for (int i = 0; i < unusedRegisters.length; i++) { - if (unusedRegisters[i] == curReg) { - OPT_Instruction toRemove = curInstr; - curInstr = curInstr.nextInstructionInCodeOrder(); - toRemove.remove(); - continue loop_over_instructions; - } - } - } - } - curInstr = curInstr.nextInstructionInCodeOrder(); - } - curBB = curBB.nextBasicBlockInCodeOrder(); - } - } - } - - /** - * Appends a system call to the current basic block. - * - * @param lazy - * current translation laziness - * @param pc - * address of system call instruction - */ - public void appendSystemCall(Laziness lazy) { - // We need to make sure that all registers contain their latest values, - // before performing the actual system call. - resolveLaziness(lazy); - spillAllRegisters(); - - // Plant call - OPT_Instruction s = Call.create(CALL, null, null, null, null, 1); - - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(sysCallMethod - .getMemberRef().asMethodReference(), sysCallMethod); - - OPT_Operand psRef = gc.makeLocal(1, psTref); - Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer for - // doSysCall - Call.setGuard(s, new OPT_TrueGuardOperand()); - Call.setMethod(s, methOp); - Call.setAddress(s, - new OPT_AddressConstantOperand(sysCallMethod.getOffset())); - s.position = gc.inlineSequence; - s.bcIndex = DBT_Trace.DO_SYSCALL; - appendInstruction(s); - - // Fill all registers again following system call - fillAllRegisters(); - } - - /** - * Plant a throw of a bad instruction exception - * - * @param lazy - * current translation laziness - * @param pc - * the program counter of the bad instruction - */ - public void appendThrowBadInstruction(Laziness lazy, int pc) { - // We need to make sure that all registers contain their latest values, - // before - // throwing the bad instruction exception. - resolveLaziness(lazy); - spillAllRegisters(); - - OPT_Operator newOperator; - OPT_TypeOperand typeOperand = new OPT_TypeOperand(badInstrKlass); - VM_TypeReference eTref = badInstrKlass.getTypeRef(); - - if (badInstrKlass.isInitialized() || badInstrKlass.isInBootImage()) { - newOperator = NEW; - } else { - newOperator = NEW_UNRESOLVED; - } - - OPT_RegisterOperand eRef = gc.temps.makeTemp(eTref); - OPT_Instruction n = New.create(newOperator, eRef, typeOperand); - n.position = gc.inlineSequence; - n.bcIndex = DBT_Trace.BAD_INSTRUCTION_NEW; - appendInstruction(n); - - OPT_Operand psRef = gc.makeLocal(1, psTref); - OPT_Instruction c = Call.create(CALL, null, null, null, null, 3); - OPT_MethodOperand methOp = OPT_MethodOperand.SPECIAL( - badInstrKlassInitMethod.getMemberRef().asMethodReference(), - badInstrKlassInitMethod); - Call.setParam(c, 0, eRef.copy()); // 'this' pointer in - // BadInstructionException.init - Call.setParam(c, 1, new OPT_IntConstantOperand(pc)); - Call.setParam(c, 2, psRef); - Call.setGuard(c, new OPT_TrueGuardOperand()); - Call.setMethod(c, methOp); - Call.setAddress(c, new OPT_AddressConstantOperand(badInstrKlassInitMethod - .getOffset())); - c.position = gc.inlineSequence; - c.bcIndex = DBT_Trace.BAD_INSTRUCTION_INIT; - - appendInstruction(c); - - OPT_Instruction t = Athrow.create(ATHROW, eRef.copyRO()); - t.position = gc.inlineSequence; - t.bcIndex = DBT_Trace.BAD_INSTRUCTION_THROW; - - appendInstruction(t); - - appendTraceExit(lazy, new OPT_IntConstantOperand(0xEBADC0DE)); - } - - /** - * Plant a record uncaught branch call. NB register state won't get resolved - * for call - * - * @param pc - * the address of the branch instruction - * @param destination - * the register operand holding the destination - * @param branchType - * The type of the uncaught branch - * @param retAddr - * An optional return address, in case the branch is a call. Otherwise, this value is ignored. - */ - private void appendRecordUncaughtBranch(int pc, OPT_RegisterOperand destination, BranchType branchType, int retAddr) { - // Is it sensible to record this information? - if ((gc.options.getOptLevel() > 0) - && (DBT_Options.plantUncaughtBranchWatcher)) { - // Plant call - OPT_Instruction s = Call.create(CALL, null, null, null, null, 5); - OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL( - recordUncaughtBranchMethod.getMemberRef().asMethodReference(), - recordUncaughtBranchMethod); - OPT_Operand psRef = gc.makeLocal(1, psTref); - Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer - Call.setParam(s, 1, new OPT_IntConstantOperand(pc)); // Address of branch - // instruction - Call.setParam(s, 2, destination.copy()); // Destination of branch value - Call.setParam(s, 3, new OPT_IntConstantOperand(branchType.ordinal())); // Branch type - Call.setParam(s, 4, new OPT_IntConstantOperand(retAddr)); // return address - // value - Call.setGuard(s, new OPT_TrueGuardOperand()); - Call.setMethod(s, methOp); - Call.setAddress(s, new OPT_AddressConstantOperand( - recordUncaughtBranchMethod.getOffset())); - s.position = gc.inlineSequence; - s.bcIndex = DBT_Trace.RECORD_BRANCH; - appendInstruction(s); - } - } - - /** Temporary int variables */ - private OPT_Register intTemps[]; - - /** - * Get/create a temporary int - * - * @param num - * a hint to allow for reuse of temps across instructions - */ - public OPT_RegisterOperand getTempInt(int num) { - if (DBT.VerifyAssertions) DBT._assert(num < 10); - - if (intTemps == null) { - intTemps = new OPT_Register[10]; - } - OPT_Register result = intTemps[num];... [truncated message content] |
From: <mic...@us...> - 2007-07-07 00:27:11
|
Revision: 148 http://svn.sourceforge.net/pearcolator/?rev=148&view=rev Author: michael_baer Date: 2007-07-06 17:27:13 -0700 (Fri, 06 Jul 2007) Log Message: ----------- Minor fixes (unused imports etc.) Modified Paths: -------------- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-06 10:39:15 UTC (rev 147) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-07 00:27:13 UTC (rev 148) @@ -13,7 +13,6 @@ import org.binarytranslator.arch.x86.os.process.X86_Registers; import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.InstructionDecoder; -import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; Modified: src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java 2007-07-06 10:39:15 UTC (rev 147) +++ src/org/binarytranslator/arch/x86/os/abi/linux/X86_LinuxSystemCalls.java 2007-07-07 00:27:13 UTC (rev 148) @@ -12,7 +12,6 @@ import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; -import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls.SystemCall; /** * Linux system call handling class Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-06 10:39:15 UTC (rev 147) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-07 00:27:13 UTC (rev 148) @@ -1141,6 +1141,8 @@ * a hint to allow for reuse of temps across instructions */ public OPT_RegisterOperand getTempInt(int num) { + if (DBT.VerifyAssertions) DBT._assert(num < 10); + if (intTemps == null) { intTemps = new OPT_Register[10]; } @@ -1164,10 +1166,14 @@ * a hint to allow for reuse of temps across instructions */ public OPT_RegisterOperand getTempLong(int num) { + if (DBT.VerifyAssertions) DBT._assert(num < 10); + if (longTemps == null) { longTemps = new OPT_Register[10]; } + OPT_Register result = longTemps[num]; + if (result == null) { OPT_RegisterOperand regOp = gc.temps.makeTempLong(); longTemps[num] = regOp.register; @@ -1211,7 +1217,7 @@ */ public OPT_RegisterOperand getTempFloat(int num) { if (DBT.VerifyAssertions) - DBT._assert((num == 0) || (num == 1)); + DBT._assert(num == 0 || num == 1); if (floatTemps == null) { floatTemps = new OPT_Register[2]; } @@ -1237,6 +1243,7 @@ public OPT_RegisterOperand getTempDouble(int num) { if (DBT.VerifyAssertions) DBT._assert(num == 0); + OPT_Register result = doubleTemp; if (result == null) { OPT_RegisterOperand regOp = gc.temps.makeTempDouble(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-07-06 10:39:24
|
Revision: 147 http://svn.sourceforge.net/pearcolator/?rev=147&view=rev Author: michael_baer Date: 2007-07-06 03:39:15 -0700 (Fri, 06 Jul 2007) Log Message: ----------- Renamed BranchLogic to BranchProfile Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/execution/ExecutionController.java src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/generic/branchprofile/ src/org/binarytranslator/generic/branchprofile/BranchProfile.java src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java Removed Paths: ------------- src/org/binarytranslator/generic/branch/ src/org/binarytranslator/generic/branchprofile/BranchLogic.java src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/DBT_Options.java 2007-07-06 10:39:15 UTC (rev 147) @@ -21,7 +21,7 @@ public class DBT_Options { /** Remove features that will only work on jikes? */ - public final static boolean buildForSunVM = true; + public final static boolean buildForSunVM = false; /** Enable the profiling of application during interpretation? */ public final static boolean profileDuringInterpretation = true; Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/Main.java 2007-07-06 10:39:15 UTC (rev 147) @@ -107,7 +107,7 @@ //on SUN's VM, only the interpreter has been tested if (DBT_Options.buildForSunVM) { - DBT_Options.executionController = ExecutionController.Type.PredecodingThreadedInterpreter; + DBT_Options.executionController = ExecutionController.Type.PredecodingInterpreter; } @@ -116,7 +116,7 @@ switch (DBT_Options.executionController) { - case PredecodingThreadedInterpreter: + case PredecodingInterpreter: controller = new PredecodingThreadedInterpreter(ps); //new PredecodingThreadedInterpreter(ps); break; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-07-06 10:39:15 UTC (rev 147) @@ -9,7 +9,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.decoder.Utils; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-07-06 10:39:15 UTC (rev 147) @@ -9,7 +9,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_MemberReference; import org.jikesrvm.classloader.VM_Method; Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-06 10:39:15 UTC (rev 147) @@ -11,8 +11,8 @@ import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; -import org.binarytranslator.generic.branch.BranchLogic; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.Binary; @@ -4026,7 +4026,7 @@ branchAddress = ppc2ir.getLRRegister(); } - ppc2ir.appendBranch(branchAddress, lazy, BranchLogic.BranchType.RETURN); + ppc2ir.appendBranch(branchAddress, lazy, BranchProfile.BranchType.RETURN); // stop translation on branch always if (BO == 0x14) { Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-06 10:39:15 UTC (rev 147) @@ -11,7 +11,7 @@ import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_Registers; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.InstructionDecoder; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.generic.fault.BadInstructionException; Copied: src/org/binarytranslator/generic/branchprofile (from rev 133, src/org/binarytranslator/generic/branch) Deleted: src/org/binarytranslator/generic/branchprofile/BranchLogic.java =================================================================== --- src/org/binarytranslator/generic/branch/BranchLogic.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/generic/branchprofile/BranchLogic.java 2007-07-06 10:39:15 UTC (rev 147) @@ -1,318 +0,0 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.generic.branch; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.binarytranslator.DBT; -import org.binarytranslator.DBT_Options; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.SAXException; - -/** - * Object capturing branches and jumps so that traces can avoid terminating on - * branches whose destinations aren't known - */ -public class BranchLogic { - - public enum BranchType { - INDIRECT_BRANCH, - DIRECT_BRANCH, - CALL, - RETURN - } - - /** A set of procedure information */ - private final SortedMap<Integer, ProcedureInformation> procedures; - - /** A set of switch like branchs sites and their destinations */ - private final SortedMap<Integer, Set<Integer>> branchSitesAndDestinations; - - /** Global branch information */ - private static BranchLogic global; - - /** - * Constructor has 2 functions: (1) when making a local trace we don't want to - * consider as many procedure return points as may be known for the full - * program. (2) making sure switch like branches are all recorded globally - */ - public BranchLogic() { - if (global == null) { - global = this; - branchSitesAndDestinations = new TreeMap<Integer, Set<Integer>>(); - } - else { - branchSitesAndDestinations = global.branchSitesAndDestinations; - } - procedures = new TreeMap<Integer, ProcedureInformation>(); - } - - /** - * Register a call (branch and link) instruction - * - * @param pc - * the address of the branch instruction - * @param dest - * the destination of the branch instruction - * @param ret - * the address that will be returned to - */ - public void registerCall(int pc, int dest, int ret) { - ProcedureInformation procedure = procedures.get(dest); - - if (procedure != null) { - procedure.registerCall(pc, ret); - } else { - procedure = new ProcedureInformation(pc, ret, dest); - procedures.put(dest, procedure); - } - - registerBranch(pc, dest); - } - - /** - * Register a function return. - * - * @param pc - * the address of the branch instruction - * @param lr - * the return address (value of the link register) - */ - public void registerReturn(int pc, int lr) { - - ProcedureInformation procedure = getLikelyProcedure(pc); - - if (procedure != null) { - procedure.registerReturn(pc, lr); - } - - registerBranch(pc, lr); - } - - /** - * Given an address within a procedure, returns the (most likely) procedure - * - * @param pc - * a location within the procedure - * @return corressponding procedure information - */ - private ProcedureInformation getLikelyProcedure(int pc) { - if (procedures.size() > 0) { - SortedMap<Integer, ProcedureInformation> priorProcedures = procedures.headMap(pc); - if (priorProcedures.size() > 0) { - Integer procedureEntry = priorProcedures.lastKey(); - return procedures.get(procedureEntry); - } - } - return null; - } - - /** - * Registers a branch from the address <code>origin</code> to the address <code>target</code>. - * The type of branch is determined by <code>type</code>, which is an ordinal from the - * {@link BranchType} enum. - * - * @param origin - * The address from which the branch occurs. - * @param target - * The address to which the program is branching. - * @param type - * The most likely type of the branch. This is taken from the {@link BranchType} enum. - */ - public void registerBranch(int origin, int target, BranchType type) { - - switch (type) { - case CALL: - throw new RuntimeException("Use the more specific registerCall() for these cases."); - - case RETURN: - registerReturn(origin, target); - break; - - default: - registerBranch(origin, target); - } - } - - /** - * Appends a recorded branch from <code>origin</code> to <code>target</code> to the branch profile. - * - * @param origin - * The address that the branch is taking place from. - * @param target - * The branch target address. - */ - private void registerBranch(int origin, int target) { - //Perform the general branch registration, too - Set<Integer> dests = branchSitesAndDestinations.get(origin); - - if (dests != null && dests.contains(target)) { - // This destination address is already registered - return; - } - else { - dests = new HashSet<Integer>(); - branchSitesAndDestinations.put(origin, dests); - } - - dests.add(target); - } - - /** - * Returns a list of known branch targets for the branch at address <code>pc</code>. - * - * @param pc - * The address where the branch originates from. - * @return - * A list of known target addresses for this branch. It is not critical to the functionality of the - * translated binary, if this list is not complete. - */ - public Set<Integer> getKnownBranchTargets(int pc) { - return branchSitesAndDestinations.get(pc); - } - - public void loadFromXML(String filename) throws IOException { - - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - Document doc; - try { - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - doc = docBuilder.parse(filename); - } catch (ParserConfigurationException e) { - throw new RuntimeException("Error creating DocumentBuilder instance to read an XML file."); - } catch (SAXException e) { - throw new IOException("File " + filename + " is not a valid XML file."); - } - - if (DBT.VerifyAssertions) DBT._assert(doc != null); - - Element root = doc.getDocumentElement(); - - if (!root.getNodeName().equals("branch-profile")) - throw new IOException("File is not a valid XML branch profile."); - - Node branches = null; - - for (int i = 0; i < root.getChildNodes().getLength(); i++) { - Node node = root.getChildNodes().item(0); - - if (node.getNodeName().equals("branches")) { - branches = node; - break; - } - } - - if (branches == null) - throw new IOException("File is not a valid XML branch profile."); - - for (int i = 0; i < branches.getChildNodes().getLength(); i++) { - Node siteNode = branches.getChildNodes().item(i); - - if (!siteNode.getNodeName().equals("origin") || siteNode.getNodeType() != Node.ELEMENT_NODE) - throw new IOException("File is not a valid XML branch profile."); - - int pc = Integer.parseInt(((Element)siteNode).getAttribute("address")); - - for (int n = 0; n < siteNode.getChildNodes().getLength(); n++) { - Node target = siteNode.getChildNodes().item(n); - - if (!target.getNodeName().equals("target") || target.getNodeType() != Node.ELEMENT_NODE) - throw new IOException("File is not a valid XML branch profile."); - - int targetAddress = Integer.parseInt(((Element)target).getAttribute("address")); - registerBranch(pc, targetAddress); - } - } - } - - /** - * Saves the branch profile of the current process space to the give file in XML format. - * - * @param filename - * The name of the file to which the branch profile is saved. - * @throws IOException - * Thrown if there is an error while creating the file. - */ - public void saveAsXML(String filename) throws IOException { - - FileOutputStream outputStream; - - try { - File f = new File(filename); - - if (!f.exists()) - f.createNewFile(); - - outputStream = new FileOutputStream(f); - } - catch (FileNotFoundException e) { - //this should not happen, as we just created the file - throw new IOException("Error creating file: " + filename); - } - - //Create an XML representation of the branch profile - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder; - try { - docBuilder = docBuilderFactory.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - throw new IOException("Error creating parser to produce XML document."); - } - Document doc = docBuilder.newDocument(); - - Element root = doc.createElement("branch-profile"); - root.setAttribute("application", DBT_Options.executableFile); - doc.appendChild(root); - - Element branchesElement = doc.createElement("branches"); - root.appendChild(branchesElement); - - for (int pc : branchSitesAndDestinations.keySet()) { - Element branchSiteElement = doc.createElement("origin"); - branchesElement.appendChild(branchSiteElement); - branchSiteElement.setAttribute("address", Integer.toString(pc)); - - for (int target : getKnownBranchTargets(pc)) { - Element branchTargetElement = doc.createElement("target"); - branchSiteElement.appendChild(branchTargetElement); - branchTargetElement.setAttribute("address", Integer.toString(target)); - } - } - - //Output the resulting XML document - TransformerFactory tFactory = TransformerFactory.newInstance(); - Transformer transformer; - try { - transformer = tFactory.newTransformer(); - DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(outputStream); - transformer.transform(source, result); - - } catch (Exception e) { - e.printStackTrace(); - } - } -} Copied: src/org/binarytranslator/generic/branchprofile/BranchProfile.java (from rev 133, src/org/binarytranslator/generic/branch/BranchLogic.java) =================================================================== --- src/org/binarytranslator/generic/branchprofile/BranchProfile.java (rev 0) +++ src/org/binarytranslator/generic/branchprofile/BranchProfile.java 2007-07-06 10:39:15 UTC (rev 147) @@ -0,0 +1,318 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ +package org.binarytranslator.generic.branchprofile; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +/** + * Object capturing branches and jumps so that traces can avoid terminating on + * branches whose destinations aren't known + */ +public class BranchProfile { + + public enum BranchType { + INDIRECT_BRANCH, + DIRECT_BRANCH, + CALL, + RETURN + } + + /** A set of procedure information */ + private final SortedMap<Integer, ProcedureInformation> procedures; + + /** A set of switch like branchs sites and their destinations */ + private final SortedMap<Integer, Set<Integer>> branchSitesAndDestinations; + + /** Global branch information */ + private static BranchProfile global; + + /** + * Constructor has 2 functions: (1) when making a local trace we don't want to + * consider as many procedure return points as may be known for the full + * program. (2) making sure switch like branches are all recorded globally + */ + public BranchProfile() { + if (global == null) { + global = this; + branchSitesAndDestinations = new TreeMap<Integer, Set<Integer>>(); + } + else { + branchSitesAndDestinations = global.branchSitesAndDestinations; + } + procedures = new TreeMap<Integer, ProcedureInformation>(); + } + + /** + * Register a call (branch and link) instruction + * + * @param pc + * the address of the branch instruction + * @param dest + * the destination of the branch instruction + * @param ret + * the address that will be returned to + */ + public void registerCall(int pc, int dest, int ret) { + ProcedureInformation procedure = procedures.get(dest); + + if (procedure != null) { + procedure.registerCall(pc, ret); + } else { + procedure = new ProcedureInformation(pc, ret, dest); + procedures.put(dest, procedure); + } + + registerBranch(pc, dest); + } + + /** + * Register a function return. + * + * @param pc + * the address of the branch instruction + * @param lr + * the return address (value of the link register) + */ + public void registerReturn(int pc, int lr) { + + ProcedureInformation procedure = getLikelyProcedure(pc); + + if (procedure != null) { + procedure.registerReturn(pc, lr); + } + + registerBranch(pc, lr); + } + + /** + * Given an address within a procedure, returns the (most likely) procedure + * + * @param pc + * a location within the procedure + * @return corressponding procedure information + */ + private ProcedureInformation getLikelyProcedure(int pc) { + if (procedures.size() > 0) { + SortedMap<Integer, ProcedureInformation> priorProcedures = procedures.headMap(pc); + if (priorProcedures.size() > 0) { + Integer procedureEntry = priorProcedures.lastKey(); + return procedures.get(procedureEntry); + } + } + return null; + } + + /** + * Registers a branch from the address <code>origin</code> to the address <code>target</code>. + * The type of branch is determined by <code>type</code>, which is an ordinal from the + * {@link BranchType} enum. + * + * @param origin + * The address from which the branch occurs. + * @param target + * The address to which the program is branching. + * @param type + * The most likely type of the branch. This is taken from the {@link BranchType} enum. + */ + public void registerBranch(int origin, int target, BranchType type) { + + switch (type) { + case CALL: + throw new RuntimeException("Use the more specific registerCall() for these cases."); + + case RETURN: + registerReturn(origin, target); + break; + + default: + registerBranch(origin, target); + } + } + + /** + * Appends a recorded branch from <code>origin</code> to <code>target</code> to the branch profile. + * + * @param origin + * The address that the branch is taking place from. + * @param target + * The branch target address. + */ + private void registerBranch(int origin, int target) { + //Perform the general branch registration, too + Set<Integer> dests = branchSitesAndDestinations.get(origin); + + if (dests != null && dests.contains(target)) { + // This destination address is already registered + return; + } + else { + dests = new HashSet<Integer>(); + branchSitesAndDestinations.put(origin, dests); + } + + dests.add(target); + } + + /** + * Returns a list of known branch targets for the branch at address <code>pc</code>. + * + * @param pc + * The address where the branch originates from. + * @return + * A list of known target addresses for this branch. It is not critical to the functionality of the + * translated binary, if this list is not complete. + */ + public Set<Integer> getKnownBranchTargets(int pc) { + return branchSitesAndDestinations.get(pc); + } + + public void loadFromXML(String filename) throws IOException { + + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + Document doc; + try { + DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); + doc = docBuilder.parse(filename); + } catch (ParserConfigurationException e) { + throw new RuntimeException("Error creating DocumentBuilder instance to read an XML file."); + } catch (SAXException e) { + throw new IOException("File " + filename + " is not a valid XML file."); + } + + if (DBT.VerifyAssertions) DBT._assert(doc != null); + + Element root = doc.getDocumentElement(); + + if (!root.getNodeName().equals("branch-profile")) + throw new IOException("File is not a valid XML branch profile."); + + Node branches = null; + + for (int i = 0; i < root.getChildNodes().getLength(); i++) { + Node node = root.getChildNodes().item(0); + + if (node.getNodeName().equals("branches")) { + branches = node; + break; + } + } + + if (branches == null) + throw new IOException("File is not a valid XML branch profile."); + + for (int i = 0; i < branches.getChildNodes().getLength(); i++) { + Node siteNode = branches.getChildNodes().item(i); + + if (!siteNode.getNodeName().equals("origin") || siteNode.getNodeType() != Node.ELEMENT_NODE) + throw new IOException("File is not a valid XML branch profile."); + + int pc = Integer.parseInt(((Element)siteNode).getAttribute("address")); + + for (int n = 0; n < siteNode.getChildNodes().getLength(); n++) { + Node target = siteNode.getChildNodes().item(n); + + if (!target.getNodeName().equals("target") || target.getNodeType() != Node.ELEMENT_NODE) + throw new IOException("File is not a valid XML branch profile."); + + int targetAddress = Integer.parseInt(((Element)target).getAttribute("address")); + registerBranch(pc, targetAddress); + } + } + } + + /** + * Saves the branch profile of the current process space to the give file in XML format. + * + * @param filename + * The name of the file to which the branch profile is saved. + * @throws IOException + * Thrown if there is an error while creating the file. + */ + public void saveAsXML(String filename) throws IOException { + + FileOutputStream outputStream; + + try { + File f = new File(filename); + + if (!f.exists()) + f.createNewFile(); + + outputStream = new FileOutputStream(f); + } + catch (FileNotFoundException e) { + //this should not happen, as we just created the file + throw new IOException("Error creating file: " + filename); + } + + //Create an XML representation of the branch profile + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder; + try { + docBuilder = docBuilderFactory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new IOException("Error creating parser to produce XML document."); + } + Document doc = docBuilder.newDocument(); + + Element root = doc.createElement("branch-profile"); + root.setAttribute("application", DBT_Options.executableFile); + doc.appendChild(root); + + Element branchesElement = doc.createElement("branches"); + root.appendChild(branchesElement); + + for (int pc : branchSitesAndDestinations.keySet()) { + Element branchSiteElement = doc.createElement("origin"); + branchesElement.appendChild(branchSiteElement); + branchSiteElement.setAttribute("address", Integer.toString(pc)); + + for (int target : getKnownBranchTargets(pc)) { + Element branchTargetElement = doc.createElement("target"); + branchSiteElement.appendChild(branchTargetElement); + branchTargetElement.setAttribute("address", Integer.toString(target)); + } + } + + //Output the resulting XML document + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer; + try { + transformer = tFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(outputStream); + transformer.transform(source, result); + + } catch (Exception e) { + e.printStackTrace(); + } + } +} Modified: src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java =================================================================== --- src/org/binarytranslator/generic/branch/CallAndReturnAddress.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java 2007-07-06 10:39:15 UTC (rev 147) @@ -6,7 +6,7 @@ * * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 */ -package org.binarytranslator.generic.branch; +package org.binarytranslator.generic.branchprofile; /** * Object for recording a call site and its corresponding return address Deleted: src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java =================================================================== --- src/org/binarytranslator/generic/branch/ProcedureInformation.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-07-06 10:39:15 UTC (rev 147) @@ -1,97 +0,0 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.generic.branch; - -import java.util.HashSet; -import java.util.Comparator; - -/** - * Objects capturing information about what looks like a method - */ -class ProcedureInformation { - /** - * Entry point to the procedure - */ - private int entry; - - /** - * Set of locations that call the procedure and the corressponding return - * address - */ - private HashSet<CallAndReturnAddress> callSitesAndReturnAddresses; - - /** - * Set of locations within the procedure that return - */ - private HashSet<Integer> returnSites; - - /** - * Comparator for procedure information - */ - @SuppressWarnings("unused") - private static final class ProcedureInformationComparator implements - Comparator { - /** - * Compare two procedure information objects - */ - public int compare(Object o1, Object o2) { - return ((ProcedureInformation) o1).entry - - ((ProcedureInformation) o2).entry; - } - } - - /** - * Constructor - * - * @param entry - * starting address of the procedure - * @param callSite - * the address calling the procedure - * @param returnAddress - * the corresponding return address - */ - ProcedureInformation(int entry, int callSite, int returnAddress) { - this.entry = entry; - callSitesAndReturnAddresses = new HashSet<CallAndReturnAddress>(); - callSitesAndReturnAddresses.add(new CallAndReturnAddress(callSite, - returnAddress)); - } - - /** - * Register a call (branch and link) instruction - * - * @param pc - * the address of the branch instruction - * @param ret - * the address that will be returned to - */ - public void registerCall(int pc, int ret) { - CallAndReturnAddress call_tuple = new CallAndReturnAddress(pc, ret); - if (!callSitesAndReturnAddresses.contains(call_tuple)) { - callSitesAndReturnAddresses.add(call_tuple); - } - } - - /** - * Register a return (branch to link register) instruction - * - * @param pc - * the address of the branch instruction - * @param ret - * the address that will be returned to - */ - public void registerReturn(int pc, int ret) { - if (returnSites == null) { - returnSites = new HashSet<Integer>(); - } - returnSites.add(new Integer(pc)); - // TODO: capture that the instruction prior to ret is a call - // site to this procedure - } -} Copied: src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java (from rev 136, src/org/binarytranslator/generic/branch/ProcedureInformation.java) =================================================================== --- src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java (rev 0) +++ src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-07-06 10:39:15 UTC (rev 147) @@ -0,0 +1,196 @@ +/* + * This file is part of binarytranslator.org. The binarytranslator.org + * project is distributed under the Common Public License (CPL). + * A copy of the license is included in the distribution, and is also + * available at http://www.opensource.org/licenses/cpl1.0.php + * + * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 + */ +package org.binarytranslator.generic.branchprofile; + +import java.util.HashSet; +import java.util.Comparator; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Objects capturing information about what looks like a method + */ +class ProcedureInformation { + /** + * Entry point to the procedure + */ + private final int entry; + + /** + * Set of locations that call the procedure and the corressponding return + * address + */ + private HashSet<CallAndReturnAddress> callSitesAndReturnAddresses; + + /** + * Set of locations within the procedure that return + */ + private HashSet<Integer> returnSites; + + /** + * Comparator for procedure information + */ + @SuppressWarnings("unused") + private static final class ProcedureInformationComparator implements + Comparator { + /** + * Compare two procedure information objects + */ + public int compare(Object o1, Object o2) { + return ((ProcedureInformation) o1).entry + - ((ProcedureInformation) o2).entry; + } + } + + private ProcedureInformation(int entry) { + this.entry = entry; + } + + /** + * Constructor + * + * @param entry + * starting address of the procedure + * @param callSite + * the address calling the procedure + * @param returnAddress + * the corresponding return address + */ + ProcedureInformation(int entry, int callSite, int returnAddress) { + this.entry = entry; + callSitesAndReturnAddresses = new HashSet<CallAndReturnAddress>(); + callSitesAndReturnAddresses.add(new CallAndReturnAddress(callSite, + returnAddress)); + } + + /** + * Register a call (branch and link) instruction + * + * @param pc + * the address of the branch instruction + * @param ret + * the address that will be returned to + */ + public void registerCall(int pc, int ret) { + CallAndReturnAddress call_tuple = new CallAndReturnAddress(pc, ret); + if (!callSitesAndReturnAddresses.contains(call_tuple)) { + callSitesAndReturnAddresses.add(call_tuple); + } + } + + /** + * Register a return (branch to link register) instruction + * + * @param pc + * the address of the branch instruction + * @param ret + * the address that will be returned to + */ + public void registerReturn(int pc, int ret) { + if (returnSites == null) { + returnSites = new HashSet<Integer>(); + } + returnSites.add(new Integer(pc)); + } + + /** + * Serializes this object to an XML document. + * + * @param doc + * The XML document that the object shall be serialized to. + * @param parentNode + * The node within <code>doc</code> that the object shall be serialized to. + */ + public void toXML(Document doc, Element parentNode) { + Element procedure = parentNode; + procedure.setAttribute("entry", Integer.toString(entry)); + + Element callSites = doc.createElement("callsites"); + for (CallAndReturnAddress caller : callSitesAndReturnAddresses) { + Element callerNode = doc.createElement("call"); + callerNode.setAttribute("from", Integer.toString(caller.getCallSite())); + callerNode.setAttribute("return", Integer.toString(caller.getReturnAddress())); + callSites.appendChild(callerNode); + } + procedure.appendChild(callSites); + + Element returnSites = doc.createElement("returnsites"); + for (Integer returnSite : this.returnSites) { + Element returnSiteNode = doc.createElement("return"); + returnSiteNode.setAttribute("at", returnSite.toString()); + returnSites.appendChild(returnSiteNode); + } + procedure.appendChild(returnSites); + } + + /** + * Loads a {@link ProcedureInformation} object from an XML element, given that the object + * was previously persisted by {@link #toXML(Document, Element)}. + * @param node + * The XML element that had been provided to {@link #toXML(Document, Element)}. + */ + public static ProcedureInformation fromXML(Element node) { + + ProcedureInformation pi = new ProcedureInformation(Integer.parseInt(node.getAttribute("entry"))); + + for (int i = 0; i < node.getChildNodes().getLength(); i++) { + Node childNode = node.getChildNodes().item(i); + + //skip non-element nodes + if (childNode.getNodeType() != Node.ELEMENT_NODE) + continue; + + if (childNode.getNodeName().equals("callsites")) { + //parse call sites + for (int n = 0; n < childNode.getChildNodes().getLength(); n++) { + Node callsite = childNode.getChildNodes().item(n); + + //skip non-element nodes + if (callsite.getNodeType() != Node.ELEMENT_NODE) + continue; + + if (callsite.getNodeName().equals("call")) + throw new Error("The given XML node is not a valid ProcedureInformation entity."); + + int callFrom = Integer.parseInt(((Element)callsite).getAttribute("from")); + int callReturn = Integer.parseInt(((Element)callsite).getAttribute("return")); + + pi.callSitesAndReturnAddresses.add(new CallAndReturnAddress(callFrom, callReturn)); + } + } + else if (childNode.getNodeName().equals("returnsites")) { + //parse return sites + for (int n = 0; n < childNode.getChildNodes().getLength(); n++) { + Node callsite = childNode.getChildNodes().item(n); + + //skip non-element nodes + if (callsite.getNodeType() != Node.ELEMENT_NODE) + continue; + + if (callsite.getNodeName().equals("return")) + throw new Error("The given XML node is not a valid ProcedureInformation entity."); + + int returnAt = Integer.parseInt(((Element)callsite).getAttribute("at")); + pi.returnSites.add(returnAt); + } + } + else { + throw new Error("The given XML node is not a valid ProcedureInformation entity."); + } + } + + + + + + return pi; + } +} Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-06 10:39:15 UTC (rev 147) @@ -16,7 +16,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.Laziness.Key; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; Modified: src/org/binarytranslator/generic/execution/ExecutionController.java =================================================================== --- src/org/binarytranslator/generic/execution/ExecutionController.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/generic/execution/ExecutionController.java 2007-07-06 10:39:15 UTC (rev 147) @@ -8,7 +8,7 @@ public enum Type { Translator, Interpreter, - PredecodingThreadedInterpreter, + PredecodingInterpreter, GDB } Modified: src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java =================================================================== --- src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-06 10:39:15 UTC (rev 147) @@ -3,15 +3,14 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.os.process.ProcessSpace; public final class PredecodingThreadedInterpreter extends ExecutionController { - private HashMap<Integer, List<Interpreter.Instruction>> traceCache = new HashMap<Integer, List<Interpreter.Instruction>>(); - private Interpreter interpreter; + private final HashMap<Integer, List<Interpreter.Instruction>> traceCache = new HashMap<Integer, List<Interpreter.Instruction>>(); + private final Interpreter interpreter; private List<Interpreter.Instruction> getTrace(int pc) { List<Interpreter.Instruction> cachedTrace = traceCache.get(pc); @@ -58,11 +57,11 @@ public PredecodingThreadedInterpreter(ProcessSpace ps) { super(ps); + interpreter = ps.createInstructionInterpreter(); } @Override public void run() { - interpreter = ps.createInstructionInterpreter(); int pc = ps.getCurrentInstructionAddress(); while (!ps.finished) { Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-07-04 16:39:23 UTC (rev 146) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-07-06 10:39:15 UTC (rev 147) @@ -14,8 +14,8 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.ppc.os.process.PPC_ProcessSpace; import org.binarytranslator.arch.x86.os.process.X86_ProcessSpace; -import org.binarytranslator.generic.branch.BranchLogic; -import org.binarytranslator.generic.branch.BranchLogic.BranchType; +import org.binarytranslator.generic.branchprofile.BranchProfile; +import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType; import org.binarytranslator.generic.decoder.CodeCache; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.execution.GdbController.GdbTarget; @@ -33,7 +33,7 @@ public abstract class ProcessSpace { /** A record of branches to guide translation */ - public final BranchLogic branchInfo; + public final BranchProfile branchInfo; /** Has a system call been called to terminate the process? */ public boolean finished = false; @@ -123,7 +123,7 @@ * Constructor */ protected ProcessSpace() { - branchInfo = new BranchLogic(); + branchInfo = new BranchProfile(); codeCache = new CodeCache(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-07-04 16:39:20
|
Revision: 146 http://svn.sourceforge.net/pearcolator/?rev=146&view=rev Author: michael_baer Date: 2007-07-04 09:39:23 -0700 (Wed, 04 Jul 2007) Log Message: ----------- - Added an execution controller that performs predecoded, threaded interpretation Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/generic/execution/ExecutionController.java Added Paths: ----------- src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-07-04 15:17:39 UTC (rev 145) +++ src/org/binarytranslator/DBT_Options.java 2007-07-04 16:39:23 UTC (rev 146) @@ -21,7 +21,7 @@ public class DBT_Options { /** Remove features that will only work on jikes? */ - public final static boolean buildForSunVM = false; + public final static boolean buildForSunVM = true; /** Enable the profiling of application during interpretation? */ public final static boolean profileDuringInterpretation = true; @@ -47,6 +47,7 @@ /** Instructions to translate for an optimisation level 2 trace */ public static int instrOpt2 = 1500; + /** Determines how the program will be run (i.e. interpreted, translated etc.) */ public static ExecutionController.Type executionController = ExecutionController.Type.Translator; /** Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-07-04 15:17:39 UTC (rev 145) +++ src/org/binarytranslator/Main.java 2007-07-04 16:39:23 UTC (rev 146) @@ -10,6 +10,7 @@ import java.io.File; +import org.binarytranslator.generic.execution.PredecodingThreadedInterpreter; import org.binarytranslator.generic.execution.DynamicTranslationController; import org.binarytranslator.generic.execution.ExecutionController; import org.binarytranslator.generic.execution.GdbController; @@ -106,7 +107,7 @@ //on SUN's VM, only the interpreter has been tested if (DBT_Options.buildForSunVM) { - DBT_Options.executionController = ExecutionController.Type.Interpreter; + DBT_Options.executionController = ExecutionController.Type.PredecodingThreadedInterpreter; } @@ -114,6 +115,11 @@ ExecutionController controller = null; switch (DBT_Options.executionController) { + + case PredecodingThreadedInterpreter: + controller = new PredecodingThreadedInterpreter(ps); //new PredecodingThreadedInterpreter(ps); + break; + case Interpreter: controller = new InterpreterController(ps); break; Modified: src/org/binarytranslator/generic/execution/ExecutionController.java =================================================================== --- src/org/binarytranslator/generic/execution/ExecutionController.java 2007-07-04 15:17:39 UTC (rev 145) +++ src/org/binarytranslator/generic/execution/ExecutionController.java 2007-07-04 16:39:23 UTC (rev 146) @@ -8,6 +8,7 @@ public enum Type { Translator, Interpreter, + PredecodingThreadedInterpreter, GDB } Added: src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java =================================================================== --- src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java (rev 0) +++ src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-04 16:39:23 UTC (rev 146) @@ -0,0 +1,75 @@ +package org.binarytranslator.generic.execution; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.os.process.ProcessSpace; + +public final class PredecodingThreadedInterpreter extends ExecutionController { + private HashMap<Integer, List<Interpreter.Instruction>> traceCache = new HashMap<Integer, List<Interpreter.Instruction>>(); + private Interpreter interpreter; + + private List<Interpreter.Instruction> getTrace(int pc) { + List<Interpreter.Instruction> cachedTrace = traceCache.get(pc); + + if (cachedTrace != null) + return cachedTrace; + + int traceStart = pc; + ArrayList<Interpreter.Instruction> newTrace = new ArrayList<Interpreter.Instruction>(5); + + while (true) { + Interpreter.Instruction instruction = interpreter.decode(pc); + pc = instruction.getSuccessor(pc); + newTrace.add(instruction); + + //is the successor to this instruction known? + if (pc == -1) { + + //No, so stop the trace after this instruction + if (newTrace.size() > 3) { + //add this trace to the trace cache, if it contains enough instructions + traceCache.put(traceStart, newTrace); + } + + break; + } + } + + return newTrace; + } + + private void executeTrace(List<Interpreter.Instruction> trace, int pc) { + + Iterator<Interpreter.Instruction> instructions = trace.iterator(); + while (instructions.hasNext()) { + Interpreter.Instruction instr = instructions.next(); + instr.execute(); + pc = instr.getSuccessor(pc); + + if (pc != -1) + ps.setCurrentInstructionAddress(pc); + } + } + + public PredecodingThreadedInterpreter(ProcessSpace ps) { + super(ps); + } + + @Override + public void run() { + interpreter = ps.createInstructionInterpreter(); + int pc = ps.getCurrentInstructionAddress(); + + while (!ps.finished) { + + List<Interpreter.Instruction> trace = getTrace(pc); + executeTrace(trace, pc); + pc = ps.getCurrentInstructionAddress(); + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-07-04 15:17:38
|
Revision: 145 http://svn.sourceforge.net/pearcolator/?rev=145&view=rev Author: michael_baer Date: 2007-07-04 08:17:39 -0700 (Wed, 04 Jul 2007) Log Message: ----------- - Added support for IfCmp branches to a target address. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-07-02 16:02:39 UTC (rev 144) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-07-04 15:17:39 UTC (rev 145) @@ -833,8 +833,8 @@ default: throw new RuntimeException("Unexpected condition code: " + condition); - } - + } + arm2ir.setCurrentBlock(condBlock); conditionalInstruction.translate(); } @@ -1773,7 +1773,7 @@ } else { //just branch and never return from it - arm2ir.appendBranch(destination, lazy, BranchType.DIRECT_BRANCH); + arm2ir.appendBranch(destination, lazy); arm2ir.getCurrentBlock().deleteNormalOut(); } } @@ -1798,7 +1798,6 @@ arm2ir.getCurrentBlock().deleteNormalOut(); } } - } public Condition getCondition() { Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-02 16:02:39 UTC (rev 144) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-04 15:17:39 UTC (rev 145) @@ -11704,7 +11704,7 @@ } if (LK == 0) - ppc2ir.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); + ppc2ir.appendBranch(target_address, lazy); else ppc2ir.appendCall(target_address, lazy, pc + 4); @@ -11727,7 +11727,7 @@ ppc2ir.setCurrentBlock(instructionEndBlock); ppc2ir.setNextBlock(ppc2ir.createBlockAfterCurrent()); - ppc2ir.appendBranch(pc + 4, lazy, BranchType.DIRECT_BRANCH); + ppc2ir.appendBranch(pc + 4, lazy); return target_address; } } Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-02 16:02:39 UTC (rev 144) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-07-04 15:17:39 UTC (rev 145) @@ -4035,7 +4035,7 @@ translationHelper.appendInstruction(gotoInstr); translationHelper.setCurrentBlock(executeBranch); - translationHelper.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); + translationHelper.appendBranch(target_address, lazy); translationHelper.setCurrentBlock(fallThrough); return pc + length; @@ -4169,7 +4169,7 @@ if (modrm == null) { target_address = absolute ? immediate : pc + length + immediate; translationHelper.getCurrentBlock().deleteNormalOut(); - translationHelper.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); + translationHelper.appendBranch(target_address, lazy); } else { int operandSize; if (prefix3 == null) { Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-02 16:02:39 UTC (rev 144) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-04 15:17:39 UTC (rev 145) @@ -34,6 +34,7 @@ import org.jikesrvm.compilers.opt.ir.Call; import org.jikesrvm.compilers.opt.ir.Goto; import org.jikesrvm.compilers.opt.ir.IfCmp; +import org.jikesrvm.compilers.opt.ir.IfCmp2; import org.jikesrvm.compilers.opt.ir.LookupSwitch; import org.jikesrvm.compilers.opt.ir.Move; import org.jikesrvm.compilers.opt.ir.New; @@ -559,13 +560,25 @@ * The address where we shall jump to. * @param targetLaziness * The current at the point of jump. - * @param branchType - * The type of branch that best describes this jump. */ - public void appendBranch(int targetPC, Laziness targetLaziness, BranchType branchType) { + public void appendBranch(int targetPC, Laziness targetLaziness) { + + appendStaticBranch(Goto.create(GOTO, null), targetPC, targetLaziness, BranchType.DIRECT_BRANCH, -1); + } + + /** + * Appends the conditional branch instruction <code>conditional</code> that jumps to the address + * <code>targetPc</code> to the current block. + * + * @param targetPC + * The address where we shall jump to. + * @param targetLaziness + * The current at the point of jump. + */ + public void appendConditionalBranch(OPT_Instruction conditional, int targetPC, Laziness targetLaziness) { - if (DBT.VerifyAssertions && branchType == BranchType.CALL) throw new RuntimeException("Use the more specific appendCall to create dynamic calls."); - appendStaticBranch(targetPC, targetLaziness, branchType, -1); + if (DBT.VerifyAssertions) DBT._assert(IfCmp.conforms(conditional) || IfCmp2.conforms(conditional)); + appendStaticBranch(conditional, targetPC, targetLaziness, BranchType.DIRECT_BRANCH, -1); } /** @@ -582,16 +595,15 @@ */ public void appendCall(int targetPC, Laziness targetLaziness, int retAddr) { - appendStaticBranch(targetPC, targetLaziness, BranchType.CALL, retAddr); + appendStaticBranch(Goto.create(GOTO, null), targetPC, targetLaziness, BranchType.CALL, retAddr); } - private void appendStaticBranch(int targetPC, Laziness targetLaziness, BranchType branchType, int retAddr) { + private void appendStaticBranch(OPT_Instruction branch, int targetPC, Laziness targetLaziness, BranchType branchType, int retAddr) { // Place a GOTO instruction at this point. However, this instruction // serves more as a placeholder and might be mutated later on. - OPT_Instruction jump = Goto.create(GOTO, null); - appendInstruction(jump); + appendInstruction(branch); UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction( - jump, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL); + branch, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL); unresolvedDirectBranches.add(unresolvedJump); if (branchType == BranchType.CALL) @@ -677,10 +689,6 @@ int targetPc = unresolvedInstr.targetPC; Laziness lazyStateAtJump = unresolvedInstr.lazyStateAtJump; OPT_Instruction gotoInstr = unresolvedInstr.instruction; - - if (DBT.VerifyAssertions) - DBT._assert(Goto.conforms(gotoInstr)); - OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, unresolvedInstr); if (DBT_Options.debugBranchResolution) { @@ -688,13 +696,32 @@ + " to " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); } - // Fix up instruction - Goto.setTarget(gotoInstr, targetBB.makeJumpTarget()); + // Fix up instruction + setBranchTarget(gotoInstr, targetBB.makeJumpTarget()); gotoInstr.getBasicBlock().insertOut(targetBB); } } /** + * Sets the target of the branching instruction <code>branch</code> to <code>target</code>. + * @param branch + * A branching instruction. Either a Goto or + * @param target + * The jump target. + */ + private void setBranchTarget(OPT_Instruction branch, OPT_BranchOperand target) { + if (Goto.conforms(branch)) { + Goto.setTarget(branch, target); + } + else if (IfCmp.conforms(branch)) { + IfCmp.setTarget(branch, target); + } + else if (IfCmp2.conforms(branch)) { + IfCmp2.setTarget1(branch, target); + } + } + + /** * This function is being called to decide whether a branch to <code>targetPc</code> (caused by the * jump instruction <code>jump</code>) shall be inlined into the trace. This function is only called when * the jump target is not part of the current trace anyway. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-07-02 16:02:39
|
Revision: 144 http://svn.sourceforge.net/pearcolator/?rev=144&view=rev Author: michael_baer Date: 2007-07-02 09:02:39 -0700 (Mon, 02 Jul 2007) Log Message: ----------- Introduced a command line parameter to select the desired execution controller. Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/generic/execution/ExecutionController.java src/org/binarytranslator/generic/execution/InterpreterController.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-07-02 16:01:43 UTC (rev 143) +++ src/org/binarytranslator/DBT_Options.java 2007-07-02 16:02:39 UTC (rev 144) @@ -13,6 +13,8 @@ import java.util.Map; import java.util.Map.Entry; +import org.binarytranslator.generic.execution.ExecutionController; + /** * Options for controlling the emulator */ @@ -44,6 +46,8 @@ /** Instructions to translate for an optimisation level 2 trace */ public static int instrOpt2 = 1500; + + public static ExecutionController.Type executionController = ExecutionController.Type.Translator; /** * Favour backward branch optimization. Translate backward branch addresses @@ -135,42 +139,51 @@ catch (NumberFormatException e) { throw new Error("Argument " + arg + " is not a valid integer."); } + catch (Exception e) { + throw new Error("Error while parsing argument '" + arg + "'.", e); + } } } - /** - * Parses a single argument into the options class. - */ + /** Parses a single argument into the options class. */ private static void parseSingleArgument(String arg, String value) { + + if (!arg.startsWith("-X:dbt:")) { + throw new Error("Invalid argument. Argument prefix '-X:dbt:' expected."); + } + + arg = arg.substring(7); - if (arg.equalsIgnoreCase("-X:dbt:debugInstr")) { + if (arg.equalsIgnoreCase("debugInstr")) { debugInstr = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:debugRuntime")) { + } else if (arg.equalsIgnoreCase("debugRuntime")) { debugRuntime = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:debugBranchResolution")) { + } else if (arg.equalsIgnoreCase("debugBranchResolution")) { debugBranchResolution = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:debugMemory")) { + } else if (arg.equalsIgnoreCase("debugMemory")) { debugMemory = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscall")) { + } else if (arg.equalsIgnoreCase("debugSyscall")) { debugSyscall = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscallMore")) { + } else if (arg.equalsIgnoreCase("debugSyscallMore")) { debugSyscallMore = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:instrOpt0")) { + } else if (arg.equalsIgnoreCase("instrOpt0")) { instrOpt0 = Integer.parseInt(value); - } else if (arg.equalsIgnoreCase("-X:dbt:instrOpt1")) { + } else if (arg.equalsIgnoreCase("instrOpt1")) { instrOpt1 = Integer.parseInt(value); - } else if (arg.equalsIgnoreCase("-X:dbt:instrOpt2")) { + } else if (arg.equalsIgnoreCase("instrOpt2")) { instrOpt2 = Integer.parseInt(value); - } else if (arg.equalsIgnoreCase("-X:dbt:singleInstrTranslation")) { + } else if (arg.equalsIgnoreCase("singleInstrTranslation")) { singleInstrTranslation = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:resolveDirectBranchesFirst")) { + } else if (arg.equalsIgnoreCase("resolveDirectBranchesFirst")) { resolveDirectBranchesFirst = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:gdbStub")) { + } else if (arg.equalsIgnoreCase("gdbStub")) { gdbStub = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:gdbStubPort")) { + } else if (arg.equalsIgnoreCase("gdbStubPort")) { gdbStubPort = Integer.parseInt(value); + } else if (arg.equalsIgnoreCase("controller")) { + executionController = ExecutionController.Type.valueOf(value); } else { - throw new Error("DBT Options: Unknown emulator option " + arg); + throw new Error("Unknown DBT option: " + arg); } } Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-07-02 16:01:43 UTC (rev 143) +++ src/org/binarytranslator/Main.java 2007-07-02 16:02:39 UTC (rev 144) @@ -104,19 +104,30 @@ System.out.println(ps); } + //on SUN's VM, only the interpreter has been tested + if (DBT_Options.buildForSunVM) { + DBT_Options.executionController = ExecutionController.Type.Interpreter; + + } + //Create an execution controller and pass execution on to it - ExecutionController controller; + ExecutionController controller = null; - if (DBT_Options.buildForSunVM) { - controller = new InterpreterController(ps); - } - else { - if (DBT_Options.gdbStub) { + switch (DBT_Options.executionController) { + case Interpreter: + controller = new InterpreterController(ps); + break; + + case Translator: + controller = new DynamicTranslationController(ps); + break; + + case GDB: controller = new GdbController(DBT_Options.gdbStubPort, ps); - } - else { - controller = new DynamicTranslationController(ps); - } + break; + + default: + throw new Error("Unknown requested controller: " + DBT_Options.executionController); } controller.run(); Modified: src/org/binarytranslator/generic/execution/ExecutionController.java =================================================================== --- src/org/binarytranslator/generic/execution/ExecutionController.java 2007-07-02 16:01:43 UTC (rev 143) +++ src/org/binarytranslator/generic/execution/ExecutionController.java 2007-07-02 16:02:39 UTC (rev 144) @@ -1,12 +1,22 @@ package org.binarytranslator.generic.execution; +import org.binarytranslator.DBT; import org.binarytranslator.generic.os.process.ProcessSpace; public abstract class ExecutionController { + public enum Type { + Translator, + Interpreter, + GDB + } + protected final ProcessSpace ps; public ExecutionController(ProcessSpace ps) { + if (DBT.VerifyAssertions) + DBT._assert(ps != null); + this.ps = ps; } Modified: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-07-02 16:01:43 UTC (rev 143) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-07-02 16:02:39 UTC (rev 144) @@ -18,9 +18,10 @@ while (!ps.finished) { Interpreter.Instruction instruction = interpreter.decode(pc); - System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); + //System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); instruction.execute(); + //System.out.println(ps.toString()); pc = instruction.getSuccessor(pc); if (pc == -1) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-07-02 16:01:40
|
Revision: 143 http://svn.sourceforge.net/pearcolator/?rev=143&view=rev Author: michael_baer Date: 2007-07-02 09:01:43 -0700 (Mon, 02 Jul 2007) Log Message: ----------- Switch from JikesRVMSupport to using VM_TypeReference as to not confuse the BootImageWriter Modified Paths: -------------- src/org/binarytranslator/vmInterface/DBT_Trace.java Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java =================================================================== --- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-07-02 09:25:04 UTC (rev 142) +++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-07-02 16:01:43 UTC (rev 143) @@ -23,6 +23,7 @@ import org.jikesrvm.classloader.VM_MemberReference; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_BytecodeStream; +import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.runtime.VM_Statics; import org.jikesrvm.runtime.VM_DynamicLink; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; @@ -147,8 +148,8 @@ private static final VM_Atom invokeCodeDescriptor; static { - dummyRunner = java.lang.JikesRVMSupport.getTypeForClass( - DummyDynamicCodeRunner.class).asClass(); + dummyRunner = VM_TypeReference.findOrCreate(DummyDynamicCodeRunner.class).resolve().asClass(); + VM_Atom memName = VM_Atom.findOrCreateAsciiAtom("invokeCode"); invokeCodeDescriptor = VM_Atom .findOrCreateAsciiAtom("(Lorg/jikesrvm/ArchitectureSpecific$VM_CodeArray;Lorg/binarytranslator/generic/os/process/ProcessSpace;)I"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-07-02 09:25:04
|
Revision: 142 http://svn.sourceforge.net/pearcolator/?rev=142&view=rev Author: michael_baer Date: 2007-07-02 02:25:04 -0700 (Mon, 02 Jul 2007) Log Message: ----------- - Moved away from JikesRVMSupport. - Using List interface instead of ArrayList to store unresolved branches - Moved decision to inline a branch into a separate function Modified Paths: -------------- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-06-29 14:43:15 UTC (rev 141) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-07-02 09:25:04 UTC (rev 142) @@ -8,9 +8,10 @@ */ package org.binarytranslator.generic.decoder; -import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; import java.util.Set; import org.binarytranslator.DBT; @@ -65,7 +66,7 @@ * The start block branches to a prefill block that loads all the register * values</li> * <li>Translation starts from the PC value given in the DBT_Trace.</li> - * <li>Translation translates PPC instructions to HIR using the + * <li>Translation translates subject instructions to HIR using the * translateInstruction method. This and the derived decoder object contain the * utilities required to aid an instruction translation.</li> * <li>The trace ends when the branch prediction deems it necessary. The @@ -86,10 +87,7 @@ /** Method ProcessSpace.doSysCall */ public static final VM_Method sysCallMethod; - /** - * VM_TypeReference of - * org.binarytranslator.generic.fault.BadInstructionException - */ + /** VM_TypeReference of org.binarytranslator.generic.fault.BadInstructionException */ public static final VM_Class badInstrKlass; /** Method BadInstructionException.<init> */ @@ -99,15 +97,13 @@ public static final VM_Method recordUncaughtBranchMethod; static { - psTref = java.lang.JikesRVMSupport.getTypeForClass(ProcessSpace.class) - .getTypeRef(); + psTref = VM_TypeReference.findOrCreate(ProcessSpace.class); VM_MethodReference sysCallMethRef = (VM_MethodReference) VM_MemberReference .findOrCreate(psTref, VM_Atom.findOrCreateAsciiAtom("doSysCall"), VM_Atom.findOrCreateAsciiAtom("()V")); sysCallMethod = sysCallMethRef.resolveInvokeSpecial(); - badInstrKlass = java.lang.JikesRVMSupport.getTypeForClass( - BadInstructionException.class).asClass(); + badInstrKlass = VM_TypeReference.findOrCreate(BadInstructionException.class).resolve().asClass(); VM_MethodReference badInstrKlassInitMethRef = (VM_MethodReference) VM_MemberReference .findOrCreate( @@ -174,32 +170,35 @@ /** The lazy state at the jump location. */ public final Laziness lazyStateAtJump; + + /** Stores the target of the jump instruction or -1, if this value is unknown. */ + public final int targetPC; - /** Depending on the type of the branch, this value either stores the address from which the branch - * is taken or the target address of the branch. */ + /** Stores the address, at which the jump occurs*/ public final int pc; /** Identifies the type of branch. */ public final BranchType type; public UnresolvedJumpInstruction(OPT_Instruction instruction, - Laziness lazyStateAtJump, int pc, BranchType type) { + Laziness lazyStateAtJump, int pc, int targetPC, BranchType type) { this.instruction = instruction; this.lazyStateAtJump = lazyStateAtJump; this.pc = pc; this.type = type; + this.targetPC = targetPC; } } /** * List of unresolved direct branches. The destinations of direct branches are * already known at translation time. */ - private final ArrayList<UnresolvedJumpInstruction> unresolvedDirectBranches; + private final List<UnresolvedJumpInstruction> unresolvedDirectBranches; /** * List of unresolved dynamic branches. Dynamics branches have a destination * address that is only determined at runtime. */ - private final ArrayList<UnresolvedJumpInstruction> unresolvedDynamicBranches; + private final List<UnresolvedJumpInstruction> unresolvedDynamicBranches; /** * Constructor @@ -232,8 +231,8 @@ finishBlock = createBlockAfterCurrent(); // Fix up stores - unresolvedDirectBranches = new ArrayList<UnresolvedJumpInstruction>(); - unresolvedDynamicBranches = new ArrayList<UnresolvedJumpInstruction>(); + unresolvedDirectBranches = new LinkedList<UnresolvedJumpInstruction>(); + unresolvedDynamicBranches = new LinkedList<UnresolvedJumpInstruction>(); } /** Returns the number of previously translated instructions within this trace. */ @@ -258,22 +257,16 @@ // Translate from the current program counter translateSubTrace(createInitialLaziness(), currentPC); - // Translating the subtrace finished so resolve any unresolved - // branches - /*if (!DBT_Options.resolveDirectBranchesFirst) { - resolveAllDynamicBranchTargets(); - }*/ + // Translating the subtrace finished so resolve any unresolved branches + + while (unresolvedDirectBranches.size() > 0 || unresolvedDynamicBranches.size() > 0) { + // Resolve all open direct branches first + resolveAllDirectBranches(); - // Resolve all open direct branches first - resolveAllDirectBranches(); + // Resolve unresolved dynamic jumps + resolveAllDynamicBranches(); + } - /*if (DBT_Options.resolveDirectBranchesFirst) { - resolveAllDynamicBranchTargets(); - }*/ - - // Resolve unresolved dynamic jumps - resolveDynamicBranches(); - // Finish up the trace finishTrace(); @@ -296,6 +289,7 @@ */ private void translateSubTrace(Laziness lazy, int pc) { currentPC = pc; + if (shallTraceStop()) { // Record mapping of this pc value and laziness to this block registerMapping(pc, lazy, currentBlock); @@ -597,7 +591,7 @@ OPT_Instruction jump = Goto.create(GOTO, null); appendInstruction(jump); UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction( - jump, (Laziness) targetLaziness.clone(), targetPC, BranchType.CALL); + jump, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL); unresolvedDirectBranches.add(unresolvedJump); if (branchType == BranchType.CALL) @@ -664,7 +658,7 @@ switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress.copyRO(), null, null, fallThrough.makeJumpTarget(), null, 0); appendInstruction(switchInstr); - UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, branchType); + UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, -1, branchType); unresolvedDynamicBranches.add(unresolvedInfo); setCurrentBlock(fallThrough); @@ -676,18 +670,18 @@ /** Resolve all unresolved direct branch instructions. */ private void resolveAllDirectBranches() { - for (int i = 0; i < unresolvedDirectBranches.size(); i++) { + while (unresolvedDirectBranches.size() > 0) { // Get the jump that we're supposed to resolve - UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches.get(i); - int targetPc = unresolvedInstr.pc; + UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches.remove(0); + int targetPc = unresolvedInstr.targetPC; Laziness lazyStateAtJump = unresolvedInstr.lazyStateAtJump; OPT_Instruction gotoInstr = unresolvedInstr.instruction; if (DBT.VerifyAssertions) DBT._assert(Goto.conforms(gotoInstr)); - OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, lazyStateAtJump, unresolvedInstr.type); + OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, unresolvedInstr); if (DBT_Options.debugBranchResolution) { report("Resolved goto in block " + gotoInstr.getBasicBlock() @@ -698,9 +692,34 @@ Goto.setTarget(gotoInstr, targetBB.makeJumpTarget()); gotoInstr.getBasicBlock().insertOut(targetBB); } - - unresolvedDirectBranches.clear(); } + + /** + * This function is being called to decide whether a branch to <code>targetPc</code> (caused by the + * jump instruction <code>jump</code>) shall be inlined into the trace. This function is only called when + * the jump target is not part of the current trace anyway. + * + * This function may be overriden to fine-tune whether certain branches shall be inlined or not. + * + * @param targetPc + * The address that we're jumping to. + * @param jump + * Detailled information describing the jump. + * @return + * True to make the system inline the target of this branch, false otherwise. + */ + protected boolean inlineBranchInstruction(int targetPc, UnresolvedJumpInstruction jump) { + /* + * The target Block is not yet translated. We do not want to inline it + * into the current trace if a) DBT_Options.singleInstrTranslation is + * enabled b) The jump target has already been compiled as a separate method + * within the code cache c) The trace is already too long d) the branch is + * supposedly a CALL or RETURN + */ + return DBT_Options.singleInstrTranslation == false + && ps.codeCache.tryGet(targetPc) == null && !shallTraceStop() + && jump.type != BranchType.CALL && jump.type != BranchType.RETURN; + } /** * Resolves a branch target to an actual basic block. In case the jump target @@ -713,31 +732,21 @@ * * @param targetPc * The address of the target basic block that. - * @param lazyStateAtJump - * The lazy state with which we would be entering the block. + * @param jump + * The branch instruction that we are trying to resolve. * @return A basic block that is equivalent to the program counter address * <code>targetPc</code> in the original binary. */ - private OPT_BasicBlock resolveBranchTarget(int targetPc, - Laziness lazyStateAtJump, BranchType branchtype) { + private OPT_BasicBlock resolveBranchTarget(int targetPc, UnresolvedJumpInstruction jump) { // Resolve the address of the target block - OPT_BasicBlock targetBB = findMapping(targetPc, lazyStateAtJump); + OPT_BasicBlock targetBB = findMapping(targetPc, jump.lazyStateAtJump); // If the target is already part of this trace, then just use the // precompiled target if (targetBB != null) return targetBB; - /* - * The target Block is not yet translated. We do not want to translate it - * into the current trace if a) DBT_Options.singleInstrTranslation is - * enabled b) The jump target has already been compiled as a separate method - * within the code cache c) The trace is already too long d) the branch is - * supposedly a CALL or RETURN - */ - if (DBT_Options.singleInstrTranslation == true - || ps.codeCache.tryGet(targetPc) != null || shallTraceStop() - || branchtype == BranchType.CALL || branchtype == BranchType.RETURN) { + if (inlineBranchInstruction(targetPc, jump)) { // Just exit the trace and continue at the target address in a new trace if (currentBlock.getNumberOfRealInstructions() != 0) { @@ -748,12 +757,12 @@ } targetBB = currentBlock; - appendTraceExit(lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); - registerMapping(targetPc, lazyStateAtJump, targetBB); + appendTraceExit(jump.lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); + registerMapping(targetPc, jump.lazyStateAtJump, targetBB); } else { // Otherwise we will translate the jump into the trace - translateSubTrace((Laziness) lazyStateAtJump.clone(), targetPc); - targetBB = findMapping(targetPc, lazyStateAtJump); + translateSubTrace((Laziness) jump.lazyStateAtJump.clone(), targetPc); + targetBB = findMapping(targetPc, jump.lazyStateAtJump); } if (DBT.VerifyAssertions) @@ -766,18 +775,15 @@ * Resolves all dynamic branches that have been added with * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. */ - private void resolveDynamicBranches() { + private void resolveAllDynamicBranches() { - for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { + while (unresolvedDynamicBranches.size() > 0) { - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches - .get(i); + UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.remove(0); Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); resolveSingleDynamicJump(unresolvedSwitch, branchDests); } - - unresolvedDynamicBranches.clear(); } /** @@ -815,8 +821,7 @@ int match_no = 0; for (int dest_pc : destinations) { - OPT_BasicBlock target = resolveBranchTarget(dest_pc, - unresolvedJump.lazyStateAtJump, unresolvedJump.type); + OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump); LookupSwitch.setMatch(lookupswitch, match_no, new OPT_IntConstantOperand(dest_pc)); @@ -830,8 +835,7 @@ } else { int dest_pc = destinations.iterator().next(); - OPT_BasicBlock target = resolveBranchTarget(dest_pc, - unresolvedJump.lazyStateAtJump, unresolvedJump.type); + OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump); IfCmp.mutate(lookupswitch, INT_IFCMP, null, value, new OPT_IntConstantOperand(dest_pc), OPT_ConditionOperand.EQUAL(), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-29 14:43:14
|
Revision: 141 http://svn.sourceforge.net/pearcolator/?rev=141&view=rev Author: michael_baer Date: 2007-06-29 07:43:15 -0700 (Fri, 29 Jun 2007) Log Message: ----------- Added primordinals for Pearcolator Modified Paths: -------------- rvmroot.patch Modified: rvmroot.patch =================================================================== --- rvmroot.patch 2007-06-21 17:27:50 UTC (rev 140) +++ rvmroot.patch 2007-06-29 14:43:15 UTC (rev 141) @@ -137,3 +137,24 @@ static org.jikesrvm.compilers.opt.OPT_SpecializedMethodPool q; + static org.jikesrvm.compilers.opt.ir.BooleanCmp2 b; } +Index: build/primordials/RVM_OPT.txt +=================================================================== +--- build/primordials/RVM_OPT.txt (revision 12759) ++++ build/primordials/RVM_OPT.txt (working copy) +@@ -16,3 +16,15 @@ + Ljava/io/FileReader; + Ljava/io/PushbackReader; + [Lorg/jikesrvm/compilers/opt/OPT_Simplifier$DefUseEffect; ++[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$ELF_Identity$AddressSize; ++[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$ELF_Identity$ByteOrder; ++[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$Header$ObjectFileType; ++[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$SegmentRange; ++[Lorg/binarytranslator/vmInterface/DummyDynamicCodeRunner; ++Lorg/binarytranslator/vmInterface/DBT_Trace; ++[Lorg/binarytranslator/vmInterface/DBT_Trace; ++[Lorg/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder$ARM32$Decoder; ++[Lorg/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder$Thumb$Decoder; ++[Lorg/binarytranslator/arch/arm/decoder/ARM_Instructions$Instruction$Condition; ++[Lorg/binarytranslator/arch/arm/decoder/ARM_Instructions$DataProcessing$Opcode; ++[Lorg/binarytranslator/arch/arm/decoder/ARM_Instructions$OperandWrapper$ShiftType; + \ No newline at end of file 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. |
From: <mic...@us...> - 2007-06-20 13:53:32
|
Revision: 139 http://svn.sourceforge.net/pearcolator/?rev=139&view=rev Author: michael_baer Date: 2007-06-20 06:53:32 -0700 (Wed, 20 Jun 2007) Log Message: ----------- - Added missing .copy() calls within AbstractCodeTranslator - Removed unused options from DBT_Options Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-06-20 13:25:36 UTC (rev 138) +++ src/org/binarytranslator/DBT_Options.java 2007-06-20 13:53:32 UTC (rev 139) @@ -19,7 +19,7 @@ public class DBT_Options { /** Remove features that will only work on jikes? */ - public final static boolean buildForSunVM = true; + public final static boolean buildForSunVM = false; /** Enable the profiling of application during interpretation? */ public final static boolean profileDuringInterpretation = true; @@ -36,9 +36,6 @@ /** Arguments given to the executable.*/ public static String[] executableArguments = null; - /** The initial optimisation level */ - public static int initialOptLevel = 0; - /** Instructions to translate for an optimisation level 0 trace */ public static int instrOpt0 = 684; @@ -61,32 +58,16 @@ /** Should direct branches be resolved before dynamic branches? */ public static boolean resolveDirectBranchesFirst = true; - /** - * Use global branch information rather than local (within the trace) - * information when optimisation level is greater than or equal to this value - */ - public static int globalBranchLevel = 3; - - /** - * Set this to true to translate only one instruction at a time. - */ + /** Set this to true to translate only one instruction at a time. */ public static boolean singleInstrTranslation = false; - /** - * Eliminate unneeded filling of register - */ + /** Eliminate unneeded filling of register */ public final static boolean eliminateRegisterFills = true; - // -oO Translation debugging options Oo- - - /** - * Print dissassembly of translated instructions. - */ + /** Print dissassembly of translated instructions. */ public static boolean debugInstr = true; - /** - * Print information about the lazy resolution of branch addresses... - */ + /** Print information about the lazy resolution of branch addresses...*/ public static boolean debugBranchResolution = true; /** During code translation, print information about the creation of basic blocks. */ @@ -113,12 +94,6 @@ /** Print out messages from the memory system */ public static boolean debugMemory = false; - /** Print out process space between instructions */ - public final static boolean debugPS = false; - - /** When printing process space, omit floating point registers. */ - public final static boolean debugPS_OmitFP = false; - /** The user ID for the user running the command */ public final static int UID = 1000; @@ -180,10 +155,6 @@ debugSyscall = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscallMore")) { debugSyscallMore = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:globalBranchLevel")) { - globalBranchLevel = Integer.parseInt(value); - } else if (arg.equalsIgnoreCase("-X:dbt:initialOptLevel")) { - initialOptLevel = Integer.parseInt(value); } else if (arg.equalsIgnoreCase("-X:dbt:instrOpt0")) { instrOpt0 = Integer.parseInt(value); } else if (arg.equalsIgnoreCase("-X:dbt:instrOpt1")) { Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-06-20 13:25:36 UTC (rev 138) +++ src/org/binarytranslator/Main.java 2007-06-20 13:53:32 UTC (rev 139) @@ -99,7 +99,7 @@ report("Sucessfully created process."); - if (DBT_Options.debugPS) { + if (DBT_Options.debugRuntime) { System.out.println("***** INITIAL PROCESS SPACE *****\n"); System.out.println(ps); } Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-06-20 13:25:36 UTC (rev 138) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-06-20 13:53:32 UTC (rev 139) @@ -661,7 +661,7 @@ OPT_BasicBlock fallThrough = createBlockAfterCurrent(); OPT_Instruction switchInstr; - switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress, null, null, fallThrough.makeJumpTarget(), null, 0); + switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress.copyRO(), null, null, fallThrough.makeJumpTarget(), null, 0); appendInstruction(switchInstr); UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, branchType); @@ -669,7 +669,7 @@ setCurrentBlock(fallThrough); appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType, retAddr); - appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); + appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress); } @@ -855,7 +855,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)); + gc.resultReg, VM_TypeReference.Int), nextPc.copy())); resolveLaziness(laziness); appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget())); currentBlock.deleteNormalOut(); @@ -1086,7 +1086,7 @@ Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer Call.setParam(s, 1, new OPT_IntConstantOperand(pc)); // Address of branch // instruction - Call.setParam(s, 2, destination); // Destination of branch value + Call.setParam(s, 2, destination.copy()); // Destination of branch value Call.setParam(s, 3, new OPT_IntConstantOperand(branchType.ordinal())); // Branch type Call.setParam(s, 4, new OPT_IntConstantOperand(retAddr)); // return address // value This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-20 13:25:36
|
Revision: 138 http://svn.sourceforge.net/pearcolator/?rev=138&view=rev Author: michael_baer Date: 2007-06-20 06:25:36 -0700 (Wed, 20 Jun 2007) Log Message: ----------- Thumb interpret and translator pass validating Dhrystone test. Modified Paths: -------------- 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 Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-19 17:34:26 UTC (rev 137) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-20 13:25:36 UTC (rev 138) @@ -473,8 +473,9 @@ else { //add/subtract register or add/subtract immediate opcode = Utils.getBit(instr, 9) ? Opcode.SUB : Opcode.ADD; - if (Utils.getBit(instr, 10)) + if (Utils.getBit(instr, 10)) { operand2 = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 8)); + } else operand2 = OperandWrapper.createRegister((byte)Utils.getBits(instr, 6, 8)); } @@ -746,7 +747,7 @@ Rd = (byte)Utils.getBits(instr, 0, 2); Rn = (byte)Utils.getBits(instr, 3, 5); - if (Utils.getBits(instr, 13, 15) == 0x5) { + if (Utils.getBits(instr, 12, 15) == 0x5) { //load store register offset offset = OperandWrapper.createRegister((byte)Utils.getBits(instr, 6, 8)); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-19 17:34:26 UTC (rev 137) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-20 13:25:36 UTC (rev 138) @@ -480,7 +480,8 @@ if (i.Rn == ARM_Registers.PC) { int value = regs.readPC(); - if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD) + //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) value = value & 0xFFFFFFFC; return value; @@ -504,12 +505,18 @@ */ protected final void setAddResult(int lhs, int rhs) { setFlagsForAdd(lhs, rhs); - - if (DBT_Options.profileDuringInterpretation && i.Rd == 15) { - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs + rhs, BranchType.INDIRECT_BRANCH); + int result = lhs + rhs; + + if (i.Rd == ARM_Registers.PC) { + if (regs.getThumbMode()) + result |= 1; + + if (DBT_Options.profileDuringInterpretation) { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); + } } - regs.set(i.Rd, lhs + rhs); + regs.set(i.Rd, result); } /** @@ -520,12 +527,18 @@ */ protected final void setSubResult(int lhs, int rhs) { setFlagsForSub(lhs, rhs); + int result = lhs - rhs; - if (DBT_Options.profileDuringInterpretation && i.Rd == 15) { - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs - rhs, BranchType.INDIRECT_BRANCH); + if (i.Rd == ARM_Registers.PC) { + if (regs.getThumbMode()) + result |= 1; + + if (DBT_Options.profileDuringInterpretation) { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH); + } } - regs.set(i.Rd, lhs - rhs); + regs.set(i.Rd, result); } /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-19 17:34:26 UTC (rev 137) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-20 13:25:36 UTC (rev 138) @@ -933,7 +933,7 @@ if (i.Rn == ARM_Registers.PC) { int value = readPC(); - if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD) + if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD && i.operand2.getType() == OperandWrapper.Type.Immediate) value = value & 0xFFFFFFFC; return new OPT_IntConstantOperand( value ); @@ -959,7 +959,7 @@ protected final void setAddResult(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) { if (i.updateConditionCodes) { - if (i.Rd != 15) { + if (i.Rd != ARM_Registers.PC) { setAddFlags(result, lhs, rhs); } else { @@ -968,8 +968,12 @@ } } - if (i.Rd == 15) { + if (i.Rd == ARM_Registers.PC) { + if (inThumb()) { + arm2ir.appendInstruction(Binary.create(INT_OR, result.copyRO(), result.copy(), new OPT_IntConstantOperand(1))); + } + if (i.updateConditionCodes) arm2ir.appendBranch(result, lazy, BranchType.INDIRECT_BRANCH); else @@ -1011,7 +1015,7 @@ protected final void setSubResult(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) { if (i.updateConditionCodes) { - if (i.Rd != 15) { + if (i.Rd != ARM_Registers.PC) { setSubFlags(result, lhs, rhs); } else { @@ -1020,7 +1024,12 @@ } } - if (i.Rd == 15) { + if (i.Rd == ARM_Registers.PC) { + + if (inThumb()) { + arm2ir.appendInstruction(Binary.create(INT_OR, result.copyRO(), result.copy(), new OPT_IntConstantOperand(1))); + } + if (i.updateConditionCodes) arm2ir.appendBranch(result, lazy, BranchType.INDIRECT_BRANCH); else @@ -1640,7 +1649,7 @@ translateWriteback(startAddress.copyRO(), nextAddress.copyRO()); //shall we switch to thumb mode? - OPT_BasicBlock finishInstruction = arm2ir.createBlockAfterCurrentNotInCFG(); + /*OPT_BasicBlock finishInstruction = arm2ir.createBlockAfterCurrentNotInCFG(); OPT_BasicBlock switchToARMBlock = arm2ir.createBlockAfterCurrentNotInCFG(); OPT_BasicBlock switchToThumbBlock = arm2ir.createBlockAfterCurrentNotInCFG(); @@ -1671,6 +1680,8 @@ //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; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-19 17:34:24
|
Revision: 137 http://svn.sourceforge.net/pearcolator/?rev=137&view=rev Author: michael_baer Date: 2007-06-19 10:34:26 -0700 (Tue, 19 Jun 2007) Log Message: ----------- First translator that runs libc "Hello World" from Thumb code. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-19 17:33:45 UTC (rev 136) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-19 17:34:26 UTC (rev 137) @@ -489,32 +489,18 @@ T createDataProcessing(short instr); - T createSwap(short instr); - T createSingleDataTransfer(short instr); T createBlockDataTransfer(short instr); T createIntMultiply(short instr); - - T createLongMultiply(short instr); - + T createSoftwareInterrupt(short instr); T createBranch(short instr); T createBranchExchange(short instr); - T createCoprocessorDataTransfer(short instr); - - T createCoprocessorDataProcessing(short instr); - - T createCoprocessorRegisterTransfer(short instr); - - T createMoveFromStatusRegister(short instr); - - T createMoveToStatusRegister(short instr); - T createUndefinedInstruction(short instr); } @@ -597,34 +583,10 @@ return new BranchExchange(instr); } - public Instruction createCoprocessorDataProcessing(short instr) { - throw new RuntimeException("Thumb does not support coprocessor instructions."); - } - - public Instruction createCoprocessorDataTransfer(short instr) { - throw new RuntimeException("Thumb does not support coprocessor instructions."); - } - - public Instruction createCoprocessorRegisterTransfer(short instr) { - throw new RuntimeException("Thumb does not support coprocessor instructions."); - } - public Instruction createDataProcessing(short instr) { return new DataProcessing(instr); } - public Instruction createLongMultiply(short instr) { - throw new RuntimeException("Thumb does not support long multiplications."); - } - - public Instruction createMoveFromStatusRegister(short instr) { - throw new RuntimeException("Thumb does not support status register transfers."); - } - - public Instruction createMoveToStatusRegister(short instr) { - throw new RuntimeException("Thumb does not support status register transfers."); - } - public Instruction createSingleDataTransfer(short instr) { return new SingleDataTransfer(instr); } @@ -633,10 +595,6 @@ return new SoftwareInterrupt(instr); } - public Instruction createSwap(short instr) { - throw new RuntimeException("Thumb does not support SWAP instructions."); - } - public Instruction createUndefinedInstruction(short instr) { return new UndefinedInstruction(instr); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-19 17:33:45 UTC (rev 136) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-19 17:34:26 UTC (rev 137) @@ -1157,7 +1157,7 @@ //if we're supposed to link, then write the previous address into the link register if (i.link) { - regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + (regs.getThumbMode() ? 2 : 4)); + regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + i.size()); } if (regs.getThumbMode()) @@ -1194,9 +1194,6 @@ } public void execute() { - //remember the previous address - - //are we supposed to jump to thumb (thumb=true) or ARM32 (thumb=false)? boolean thumb; @@ -1212,7 +1209,7 @@ else previousAddress = regs.get(i.target.getRegister()); - targetAddress = previousAddress + i.target.getOffset(); + targetAddress = (previousAddress + i.target.getOffset()) | 1; thumb = true; break; @@ -1825,18 +1822,6 @@ return new BranchExchange(new ARM_Instructions.BranchExchange(instr)); } - public ARM_Instruction createCoprocessorDataProcessing(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - - public ARM_Instruction createCoprocessorDataTransfer(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - - public ARM_Instruction createCoprocessorRegisterTransfer(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - public ARM_Instruction createDataProcessing(short instr) { ARM_Instructions.DataProcessing i = new ARM_Instructions.DataProcessing(instr); @@ -1881,18 +1866,6 @@ } } - public ARM_Instruction createLongMultiply(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - - public ARM_Instruction createMoveFromStatusRegister(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - - public ARM_Instruction createMoveToStatusRegister(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - public ARM_Instruction createSingleDataTransfer(short instr) { return new SingleDataTransfer(new ARM_Instructions.SingleDataTransfer(instr)); } @@ -1901,10 +1874,6 @@ return new SoftwareInterrupt(new ARM_Instructions.SoftwareInterrupt(instr)); } - public ARM_Instruction createSwap(short instr) { - throw new RuntimeException("Instruction type not supported by thumb."); - } - public ARM_Instruction createUndefinedInstruction(short instr) { return new UndefinedInstruction(instr); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-19 17:33:45 UTC (rev 136) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-19 17:34:26 UTC (rev 137) @@ -231,8 +231,9 @@ value = new OPT_IntConstantOperand(translator.readPC() + operand.getOffset()); } else { - value = translator.arm2ir.getTempInt(9); - translator.arm2ir.appendInstruction(Binary.create(INT_ADD, (OPT_RegisterOperand)value, translator.arm2ir.getRegister(operand.getRegister()), new OPT_IntConstantOperand(operand.getOffset()))); + OPT_RegisterOperand tmp = translator.arm2ir.getTempInt(9); + translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, translator.arm2ir.getRegister(operand.getRegister()), new OPT_IntConstantOperand(operand.getOffset()))); + value = tmp.copy(); } return; @@ -737,7 +738,9 @@ } public int getSuccessor(int pc) { - return pc + 4; + + boolean thumbMode = (pc & 0x1) == 1; + return pc + (thumbMode ? 2 : 4); } public Condition getCondition() { @@ -928,7 +931,12 @@ protected OPT_Operand resolveOperand1() { if (i.Rn == ARM_Registers.PC) { - return new OPT_IntConstantOperand( readPC() ); + int value = readPC(); + + if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD) + value = value & 0xFFFFFFFC; + + return new OPT_IntConstantOperand( value ); } return arm2ir.getRegister(i.Rn); @@ -1057,7 +1065,7 @@ public int getSuccessor(int pc) { if (i.Rd != ARM_Registers.PC) - return pc + 4; + return pc + i.size(); else return -1; } @@ -1532,7 +1540,7 @@ public int getSuccessor(int pc) { //according to the ARM Architecture reference, using the pc as Rd yields an undefined //result. Therefore, we can safely assume that this instruction never equals a branch - return pc + 4; + return pc + i.size(); } } @@ -1722,7 +1730,7 @@ if (i.isLoad && transferPC) return -1; else - return pc + 4; + return pc + i.size(); } } @@ -1737,37 +1745,46 @@ } public void translate() { - - - //if we're supposed to link, then write the previous address into the link register - if (i.link) { - arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); - } - else { - //we should never be returning from the goto - arm2ir.getCurrentBlock().deleteNormalOut(); - } - + //can we pre-calculate to where we're branching? if (i.offset.getType() == OperandWrapper.Type.Immediate) { + + int destination = readPC() + i.offset.getImmediate(); + + if (inThumb()) + destination |= 1; + //we can directly resolve this branch to a fixed address - if (i.link) - arm2ir.appendCall(readPC() + i.getOffset().getImmediate(), lazy, pc + i.size()); - else - arm2ir.appendBranch(readPC() + i.getOffset().getImmediate(), lazy, BranchType.DIRECT_BRANCH); + if (i.link) { + //put the return address into the link register, then branch + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + i.size()))); + arm2ir.appendCall(destination, lazy, pc + i.size()); + } + else { + //just branch and never return from it + arm2ir.appendBranch(destination, lazy, BranchType.DIRECT_BRANCH); + arm2ir.getCurrentBlock().deleteNormalOut(); + } } else { //the branch target is not known at compile time OPT_Operand offset = ResolvedOperand.resolve(ARM_Translator.this, i.offset); - OPT_RegisterOperand dest = arm2ir.getTempInt(0); + OPT_RegisterOperand dest = arm2ir.getTempInt(0); + + if (inThumb()) + arm2ir.appendInstruction(Binary.create(INT_ADD, dest, offset, new OPT_IntConstantOperand(readPC() | 1))); + else + arm2ir.appendInstruction(Binary.create(INT_ADD, dest, offset, new OPT_IntConstantOperand(readPC()))); - arm2ir.appendInstruction(Binary.create(INT_ADD, dest, offset, new OPT_IntConstantOperand(readPC()))); - if (i.link) { + //put the return address into the link register, then branch + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + i.size()))); arm2ir.appendCall(dest, lazy, pc + i.size()); } else { + //just branch and never return from it arm2ir.appendBranch(dest, lazy, BranchType.INDIRECT_BRANCH); + arm2ir.getCurrentBlock().deleteNormalOut(); } } @@ -1817,17 +1834,18 @@ } //Call regs.setThumbMode(true) to enable thumb execution - enableThumb = new OPT_IntConstantOperand(inThumb() ? 0 : 1); + enableThumb = new OPT_IntConstantOperand(1); break; case Register: + if (i.target.getRegister() == ARM_Registers.PC) + targetAddress = new OPT_IntConstantOperand(readPC()); + else + targetAddress = arm2ir.getRegister(i.target.getRegister()); + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); - arm2ir.appendInstruction(Binary.create(INT_AND, tmp, arm2ir.getRegister(i.target.getRegister()), new OPT_IntConstantOperand(0xFFFFFFFE) )); - targetAddress = tmp; - - OPT_RegisterOperand tmp2 = arm2ir.getTempInt(1); - arm2ir.appendInstruction(Binary.create(INT_AND, tmp2, arm2ir.getRegister(i.target.getRegister()), new OPT_IntConstantOperand(0x1) )); - enableThumb = tmp2; + arm2ir.appendInstruction(Binary.create(INT_AND, tmp, arm2ir.getRegister(i.target.getRegister()), new OPT_IntConstantOperand(0x1) )); + enableThumb = tmp; break; default: @@ -1837,7 +1855,7 @@ //write the next address into the link register, if requested so. if (i.link) { - arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(previousAddress - (inThumb() ? 2 : 4)))); + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(previousAddress - i.size()))); } //set the correct processor mode (thumb or not) @@ -1900,7 +1918,7 @@ } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -1966,7 +1984,7 @@ } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -2006,7 +2024,7 @@ public int getSuccessor(int pc) { //Rd should never be the PC, so we can safely predict the next instruction - return pc + 4; + return pc + i.size(); } } @@ -2028,7 +2046,7 @@ } public int getSuccessor(int pc) { - return pc+4; + return pc + i.size(); } } @@ -2061,7 +2079,7 @@ } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -2247,7 +2265,7 @@ if (i.Rd == ARM_Registers.PC && i.isLoad) return -1; - return pc + 4; + return pc + i.size(); } } @@ -2272,6 +2290,12 @@ } private final class DebugNopInstruction implements ARM_Instruction { + + private final boolean thumb; + + public DebugNopInstruction(boolean thumb) { + this.thumb = thumb; + } public Condition getCondition() { return Condition.AL; @@ -2281,7 +2305,7 @@ } public int getSuccessor(int pc) { - return pc+4; + return pc + (thumb ? 2 : 4); } } @@ -2352,21 +2376,21 @@ //TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createCoprocessorDataTransfer(int instr) { // TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createCoprocessorRegisterTransfer(int instr) { // TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createIntMultiply(int instr) { @@ -2402,78 +2426,76 @@ } public ARM_Instruction createBlockDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr)); } public ARM_Instruction createBranch(short instr) { - // TODO Auto-generated method stub - return null; + return new Branch(new ARM_Instructions.Branch(instr)); } public ARM_Instruction createBranchExchange(short instr) { - // TODO Auto-generated method stub - return null; + return new BranchExchange(new ARM_Instructions.BranchExchange(instr)); } - public ARM_Instruction createCoprocessorDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; - } - - public ARM_Instruction createCoprocessorDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; - } - - public ARM_Instruction createCoprocessorRegisterTransfer(short instr) { - // TODO Auto-generated method stub - return null; - } - public ARM_Instruction createDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; - } + ARM_Instructions.DataProcessing i = new ARM_Instructions.DataProcessing(instr); - public ARM_Instruction createLongMultiply(short instr) { - // TODO Auto-generated method stub - return null; - } + switch (i.opcode) { + case ADC: + return new DataProcessing_Adc(i); + case ADD: + return new DataProcessing_Add(i); + case AND: + return new DataProcessing_And(i); + case BIC: + return new DataProcessing_Bic(i); + case CMN: + return new DataProcessing_Cmn(i); + case CMP: + return new DataProcessing_Cmp(i); + case EOR: + return new DataProcessing_Eor(i); + case MOV: + return new DataProcessing_Mov(i); + case MVN: + return new DataProcessing_Mvn(i); + case ORR: + return new DataProcessing_Orr(i); + case RSB: + return new DataProcessing_Rsb(i); + case RSC: + return new DataProcessing_Rsc(i); + case SBC: + return new DataProcessing_Sbc(i); + case SUB: + return new DataProcessing_Sub(i); + case TEQ: + return new DataProcessing_Teq(i); + case TST: + return new DataProcessing_Tst(i); + case CLZ: + return new DataProcessing_Clz(i); - public ARM_Instruction createMoveFromStatusRegister(short instr) { - // TODO Auto-generated method stub - return null; + default: + throw new RuntimeException("Unexpected Data Procesing opcode: " + + i.opcode); + } } - public ARM_Instruction createMoveToStatusRegister(short instr) { - // TODO Auto-generated method stub - return null; - } - public ARM_Instruction createSingleDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new SingleDataTransfer(new ARM_Instructions.SingleDataTransfer(instr)); } public ARM_Instruction createSoftwareInterrupt(short instr) { - // TODO Auto-generated method stub - return null; + return new SoftwareInterrupt(new ARM_Instructions.SoftwareInterrupt(instr)); } - public ARM_Instruction createSwap(short instr) { - // TODO Auto-generated method stub - return null; - } - public ARM_Instruction createUndefinedInstruction(short instr) { - // TODO Auto-generated method stub - return null; + return new UndefinedInstruction(instr); } public ARM_Instruction createIntMultiply(short instr) { - // TODO Auto-generated method stub - return null; + return new IntMultiply(new ARM_Instructions.IntMultiply(instr)); } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-19 17:33:43
|
Revision: 136 http://svn.sourceforge.net/pearcolator/?rev=136&view=rev Author: michael_baer Date: 2007-06-19 10:33:45 -0700 (Tue, 19 Jun 2007) Log Message: ----------- Added code to load/store a ProcedureInformation from/to XML. Modified Paths: -------------- src/org/binarytranslator/generic/branch/ProcedureInformation.java Modified: src/org/binarytranslator/generic/branch/ProcedureInformation.java =================================================================== --- src/org/binarytranslator/generic/branch/ProcedureInformation.java 2007-06-19 12:24:56 UTC (rev 135) +++ src/org/binarytranslator/generic/branch/ProcedureInformation.java 2007-06-19 17:33:45 UTC (rev 136) @@ -11,6 +11,10 @@ import java.util.HashSet; import java.util.Comparator; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + /** * Objects capturing information about what looks like a method */ @@ -18,7 +22,7 @@ /** * Entry point to the procedure */ - private int entry; + private final int entry; /** * Set of locations that call the procedure and the corressponding return @@ -45,6 +49,10 @@ - ((ProcedureInformation) o2).entry; } } + + private ProcedureInformation(int entry) { + this.entry = entry; + } /** * Constructor @@ -91,7 +99,98 @@ returnSites = new HashSet<Integer>(); } returnSites.add(new Integer(pc)); - // TODO: capture that the instruction prior to ret is a call - // site to this procedure } + + /** + * Serializes this object to an XML document. + * + * @param doc + * The XML document that the object shall be serialized to. + * @param parentNode + * The node within <code>doc</code> that the object shall be serialized to. + */ + public void toXML(Document doc, Element parentNode) { + Element procedure = parentNode; + procedure.setAttribute("entry", Integer.toString(entry)); + + Element callSites = doc.createElement("callsites"); + for (CallAndReturnAddress caller : callSitesAndReturnAddresses) { + Element callerNode = doc.createElement("call"); + callerNode.setAttribute("from", Integer.toString(caller.getCallSite())); + callerNode.setAttribute("return", Integer.toString(caller.getReturnAddress())); + callSites.appendChild(callerNode); + } + procedure.appendChild(callSites); + + Element returnSites = doc.createElement("returnsites"); + for (Integer returnSite : this.returnSites) { + Element returnSiteNode = doc.createElement("return"); + returnSiteNode.setAttribute("at", returnSite.toString()); + returnSites.appendChild(returnSiteNode); + } + procedure.appendChild(returnSites); + } + + /** + * Loads a {@link ProcedureInformation} object from an XML element, given that the object + * was previously persisted by {@link #toXML(Document, Element)}. + * @param node + * The XML element that had been provided to {@link #toXML(Document, Element)}. + */ + public static ProcedureInformation fromXML(Element node) { + + ProcedureInformation pi = new ProcedureInformation(Integer.parseInt(node.getAttribute("entry"))); + + for (int i = 0; i < node.getChildNodes().getLength(); i++) { + Node childNode = node.getChildNodes().item(i); + + //skip non-element nodes + if (childNode.getNodeType() != Node.ELEMENT_NODE) + continue; + + if (childNode.getNodeName().equals("callsites")) { + //parse call sites + for (int n = 0; n < childNode.getChildNodes().getLength(); n++) { + Node callsite = childNode.getChildNodes().item(n); + + //skip non-element nodes + if (callsite.getNodeType() != Node.ELEMENT_NODE) + continue; + + if (callsite.getNodeName().equals("call")) + throw new Error("The given XML node is not a valid ProcedureInformation entity."); + + int callFrom = Integer.parseInt(((Element)callsite).getAttribute("from")); + int callReturn = Integer.parseInt(((Element)callsite).getAttribute("return")); + + pi.callSitesAndReturnAddresses.add(new CallAndReturnAddress(callFrom, callReturn)); + } + } + else if (childNode.getNodeName().equals("returnsites")) { + //parse return sites + for (int n = 0; n < childNode.getChildNodes().getLength(); n++) { + Node callsite = childNode.getChildNodes().item(n); + + //skip non-element nodes + if (callsite.getNodeType() != Node.ELEMENT_NODE) + continue; + + if (callsite.getNodeName().equals("return")) + throw new Error("The given XML node is not a valid ProcedureInformation entity."); + + int returnAt = Integer.parseInt(((Element)callsite).getAttribute("at")); + pi.returnSites.add(returnAt); + } + } + else { + throw new Error("The given XML node is not a valid ProcedureInformation entity."); + } + } + + + + + + return pi; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-19 12:24:54
|
Revision: 135 http://svn.sourceforge.net/pearcolator/?rev=135&view=rev Author: michael_baer Date: 2007-06-19 05:24:56 -0700 (Tue, 19 Jun 2007) Log Message: ----------- Added a Null-Object for undefined instructions, instead of returning null from the decoder. Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-19 09:10:03 UTC (rev 134) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-19 12:24:56 UTC (rev 135) @@ -17,6 +17,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.SoftwareInterrupt; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Swap; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.ARM_InstructionVisitor; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.UndefinedInstruction; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; @@ -438,5 +439,9 @@ setResult(String.format("MSR%s %s, %s", cond(instr), fields, operand(instr.getSource()))); } + + public void visit(UndefinedInstruction instr) { + setResult("--- (Undefined " + (instr.isThumb ? "Thumb" : "ARM") + " instruction, code 0x" + Integer.toHexString(instr.binaryInstruction) + ")"); + } } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-19 09:10:03 UTC (rev 134) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-19 12:24:56 UTC (rev 135) @@ -582,7 +582,7 @@ } public Instruction createUndefinedInstruction(int instr) { - return null; + return new UndefinedInstruction(instr); } public Instruction createBlockDataTransfer(short instr) { @@ -638,7 +638,7 @@ } public Instruction createUndefinedInstruction(short instr) { - return null; + return new UndefinedInstruction(instr); } public Instruction createIntMultiply(short instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-19 09:10:03 UTC (rev 134) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-19 12:24:56 UTC (rev 135) @@ -47,6 +47,11 @@ this.isThumb = false; } + public Instruction(boolean isThumb) { + condition = Condition.AL; + this.isThumb = isThumb; + } + public final int size() { return isThumb ? 2 : 4; } @@ -1674,9 +1679,31 @@ } } + public static class UndefinedInstruction extends Instruction { + + protected final int binaryInstruction; + + public UndefinedInstruction(short instruction) { + super(false); + this.binaryInstruction = instruction; + } + + public UndefinedInstruction(int instruction) { + super(true); + this.binaryInstruction = instruction; + } + + @Override + public void visit(ARM_InstructionVisitor visitor) { + visitor.visit(this); + } + + } + public interface ARM_InstructionVisitor { void visit(DataProcessing instr); + void visit(UndefinedInstruction instr); void visit(SingleDataTransfer instr); void visit(IntMultiply instr); void visit(LongMultiply instr); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-19 09:10:03 UTC (rev 134) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-19 12:24:56 UTC (rev 135) @@ -1737,16 +1737,27 @@ } public void translate() { - + + + //if we're supposed to link, then write the previous address into the link register + if (i.link) { + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); + } + else { + //we should never be returning from the goto + arm2ir.getCurrentBlock().deleteNormalOut(); + } + + //can we pre-calculate to where we're branching? if (i.offset.getType() == OperandWrapper.Type.Immediate) { //we can directly resolve this branch to a fixed address if (i.link) - arm2ir.appendCall( readPC() + i.getOffset().getImmediate(), lazy, pc + i.size()); + arm2ir.appendCall(readPC() + i.getOffset().getImmediate(), lazy, pc + i.size()); else arm2ir.appendBranch(readPC() + i.getOffset().getImmediate(), lazy, BranchType.DIRECT_BRANCH); } else { - + //the branch target is not known at compile time OPT_Operand offset = ResolvedOperand.resolve(ARM_Translator.this, i.offset); OPT_RegisterOperand dest = arm2ir.getTempInt(0); @@ -1759,15 +1770,6 @@ arm2ir.appendBranch(dest, lazy, BranchType.INDIRECT_BRANCH); } } - - //if we're supposed to link, then write the previous address into the link register - if (i.link) { - arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); - } - else { - //we should never be returning from the goto - arm2ir.getCurrentBlock().deleteNormalOut(); - } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-19 09:10:03
|
Revision: 134 http://svn.sourceforge.net/pearcolator/?rev=134&view=rev Author: michael_baer Date: 2007-06-19 02:10:03 -0700 (Tue, 19 Jun 2007) Log Message: ----------- - Made ARM_InstructionVisitor a subclass of ARM_Instructions - Moved decoder utilities class to package generic.decoder Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java Added Paths: ----------- src/org/binarytranslator/generic/decoder/Utils.java Removed Paths: ------------- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java src/org/binarytranslator/arch/arm/decoder/Utils.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-19 09:10:03 UTC (rev 134) @@ -16,6 +16,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.SingleDataTransfer; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.SoftwareInterrupt; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Swap; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.ARM_InstructionVisitor; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-19 09:10:03 UTC (rev 134) @@ -1,6 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; +import org.binarytranslator.generic.decoder.Utils; /** * This class decodes an ARM or Thumb instruction and uses a user-supplied Deleted: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionVisitor.java 2007-06-19 09:10:03 UTC (rev 134) @@ -1,22 +0,0 @@ -package org.binarytranslator.arch.arm.decoder; - -import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; - -/** An interface that supports iterating over ARM instructions using the visitor pattern. */ -public interface ARM_InstructionVisitor { - - void visit(DataProcessing instr); - void visit(SingleDataTransfer instr); - void visit(IntMultiply instr); - void visit(LongMultiply instr); - void visit(Swap instr); - void visit(BlockDataTransfer instr); - void visit(SoftwareInterrupt instr); - void visit(Branch instr); - void visit(BranchExchange instr); - void visit(CoprocessorDataTransfer instr); - void visit(CoprocessorDataProcessing instr); - void visit(CoprocessorRegisterTransfer instr); - void visit(MoveFromStatusRegister instr); - void visit(MoveToStatusRegister instr); -} Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-19 09:10:03 UTC (rev 134) @@ -3,6 +3,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper.ShiftType; import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.generic.decoder.Utils; /** * In the ARM decoder model, the decoding and usage (translating/interpreting/disassembling) of instructions @@ -1672,4 +1673,22 @@ visitor.visit(this); } } + + public interface ARM_InstructionVisitor { + + void visit(DataProcessing instr); + void visit(SingleDataTransfer instr); + void visit(IntMultiply instr); + void visit(LongMultiply instr); + void visit(Swap instr); + void visit(BlockDataTransfer instr); + void visit(SoftwareInterrupt instr); + void visit(Branch instr); + void visit(BranchExchange instr); + void visit(CoprocessorDataTransfer instr); + void visit(CoprocessorDataProcessing instr); + void visit(CoprocessorRegisterTransfer instr); + void visit(MoveFromStatusRegister instr); + void visit(MoveToStatusRegister instr); + } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-19 09:10:03 UTC (rev 134) @@ -11,6 +11,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; import org.binarytranslator.generic.branch.BranchLogic.BranchType; import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.decoder.Utils; import com.sun.org.apache.bcel.internal.generic.InstructionFactory; Deleted: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-06-18 17:06:44 UTC (rev 133) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-06-19 09:10:03 UTC (rev 134) @@ -1,196 +0,0 @@ -package org.binarytranslator.arch.arm.decoder; - -import org.binarytranslator.DBT; - -public class Utils { - - /** - * Checks if a bit is set within a word. - * @param word - * The word that is being examined. - * @param bit - * The number of the bit that is to be checked, starting from zero. - * @return - * True, if the given bit is set within the word, false otherwise. - */ - static final boolean getBit(int word, int bit) { - if (DBT.VerifyAssertions) - DBT._assert(bit >= 0 && bit <= 31); - return (word & (1 << bit)) != 0; - } - - /** - * Same functions as {@link #getBit(int, int)} for shorts. - */ - static final boolean getBit(short word, int bit) { - if (DBT.VerifyAssertions) - DBT._assert(bit >= 0 && bit <= 15); - return (word & (1 << bit)) != 0; - } - - /** - * Extracts a subsequence of bits from a word and shifts the beginning of that subsequence to - * a zero based-number. - * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. - * @param word - * The word that is to be examined. - * @param from - * The first bit (starting from 0) that is to be extracted. - * @param to - * The last bit (starting from 0) that is to be extracted from the word. - * @return - * A zero-based version of the bit sequence. - */ - static final int getBits(int word, int from, int to) { - if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to < 31); - - return (word & ((1 << (to + 1)) - 1)) >> from; - } - - /** - * Same function as {@link #getBits(int, int, int)} for shorts. - */ - static final int getBits(short word, int from, int to) { - if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to <= 15); - - return (word & ((1 << (to + 1)) - 1)) >> from; - } - - /** - * Sign extends a given value. - * @param value - * The value to sign extends. - * @param bitsUsed - * The number bits used within this value. - * @return - * A sign extended value. - */ - static int signExtend(int value, int bitsUsed) { - return (value << (32 - bitsUsed)) >> (32 - bitsUsed); - } - - /** - * Returns true, if the addition of both operands as unsigned integers will cause an overflow. - * At the moment, this converts both values to longs and checks if the 33rd bit (which actually represents the carry) - * overflows. - */ - public static boolean unsignedAddOverflow(int operand1, int operand2) { - long value1 = (long)operand1 & 0xFFFFFFFFL; - long value2 = (long)operand2 & 0xFFFFFFFFL; - - return ((value1 + value2) & 0x100000000L) != 0; - } - - /** - * Returns true, if the subtraction of both operand1 - operand2 (both unsigned) will issue a borrow. - */ - public static boolean unsignedSubOverflow(int operand1, int operand2) { - operand1 += Integer.MIN_VALUE; - operand2 += Integer.MIN_VALUE; - - return operand1 < operand2; - } - - /** - * Returns true, if the addition of both operands as signed integers will cause an overflow. - * This basically checks <code>operand1 + operand2 > Integer.MAX_VALUE</code>. - */ - public static boolean signedAddOverflow(int operand1, int operand2) { - return operand1 > Integer.MAX_VALUE - operand2; - } - - /** - * Returns true, if the subtraction of operand1 from operand (as signed integers) - * will cause an overflow. - * This basically checks <code>operand1 - operand2 < Integer.MIN_VALUE</code>. - */ - public static boolean signedSubOverflow(int operand1, int operand2) { - // if the MSB is already set in any of the operands, then no overflow can - // occur - if (operand1 >= 0) { - return (operand2 < 0) && ((operand1-operand2) < 0); - } - else { - return (operand2 > 0) && ((operand1-operand2) > 0); - } - } - - /** - * Performs a number of sanity tests that make sure that the above functions are working the - * manner described before.*/ - public static void runSanityTests() { - if (!Utils.unsignedAddOverflow(1, -1)) { - throw new RuntimeException("Error"); - } - - if (!Utils.unsignedAddOverflow(-1, -1)) { - throw new RuntimeException("Error"); - } - - if (!Utils.unsignedAddOverflow(-1, 1)) { - throw new RuntimeException("Error"); - } - - if (Utils.unsignedAddOverflow(10000, 10000)) { - throw new RuntimeException("Error"); - } - - if (Utils.unsignedSubOverflow(-1, 1)) { - throw new RuntimeException("Error"); - } - - if (!Utils.unsignedSubOverflow(1, -1)) { - throw new RuntimeException("Error"); - } - - if (Utils.unsignedSubOverflow(-1, -1)) { - throw new RuntimeException("Error"); - } - - if (Utils.unsignedSubOverflow(10, 0)) { - throw new RuntimeException("Error"); - } - - if (!Utils.unsignedSubOverflow(0, 10)) { - throw new RuntimeException("Error"); - } - - if (!Utils.signedAddOverflow(0x70000000, 0x10000000)) { - throw new RuntimeException("Error"); - } - - if (Utils.signedAddOverflow(0x90000000, 0x10000000)) { - throw new RuntimeException("Error"); - } - - if (!Utils.signedAddOverflow(0x50000000, 0x50000000)) { - throw new RuntimeException("Error"); - } - - if (Utils.signedAddOverflow(0x60000000, 0x10000000)) { - throw new RuntimeException("Error"); - } - - if (Utils.signedAddOverflow(0x10000000, 0x60000000)) { - throw new RuntimeException("Error"); - } - - if (!Utils.signedSubOverflow(0x80000000, 0x30000000)) { - throw new RuntimeException("Error"); - } - - if (!Utils.signedSubOverflow(0x30000000, 0x80000000)) { - throw new RuntimeException("Error"); - } - - if (!Utils.signedSubOverflow(0, 0x80000000)) { - throw new RuntimeException("Error"); - } - - if (Utils.signedSubOverflow(0, 0x70000000)) { - throw new RuntimeException("Error"); - } - } -} Copied: src/org/binarytranslator/generic/decoder/Utils.java (from rev 133, src/org/binarytranslator/arch/arm/decoder/Utils.java) =================================================================== --- src/org/binarytranslator/generic/decoder/Utils.java (rev 0) +++ src/org/binarytranslator/generic/decoder/Utils.java 2007-06-19 09:10:03 UTC (rev 134) @@ -0,0 +1,196 @@ +package org.binarytranslator.generic.decoder; + +import org.binarytranslator.DBT; + +public class Utils { + + /** + * Checks if a bit is set within a word. + * @param word + * The word that is being examined. + * @param bit + * The number of the bit that is to be checked, starting from zero. + * @return + * True, if the given bit is set within the word, false otherwise. + */ + public static final boolean getBit(int word, int bit) { + if (DBT.VerifyAssertions) + DBT._assert(bit >= 0 && bit <= 31); + return (word & (1 << bit)) != 0; + } + + /** + * Same functions as {@link #getBit(int, int)} for shorts. + */ + public static final boolean getBit(short word, int bit) { + if (DBT.VerifyAssertions) + DBT._assert(bit >= 0 && bit <= 15); + return (word & (1 << bit)) != 0; + } + + /** + * Extracts a subsequence of bits from a word and shifts the beginning of that subsequence to + * a zero based-number. + * A call to <code>getBits(0xFF, 2, 3)</code> would return 0x3. + * @param word + * The word that is to be examined. + * @param from + * The first bit (starting from 0) that is to be extracted. + * @param to + * The last bit (starting from 0) that is to be extracted from the word. + * @return + * A zero-based version of the bit sequence. + */ + public static final int getBits(int word, int from, int to) { + if (DBT.VerifyAssertions) + DBT._assert(from < to && from >= 0 && to < 31); + + return (word & ((1 << (to + 1)) - 1)) >> from; + } + + /** + * Same function as {@link #getBits(int, int, int)} for shorts. + */ + public static final int getBits(short word, int from, int to) { + if (DBT.VerifyAssertions) + DBT._assert(from < to && from >= 0 && to <= 15); + + return (word & ((1 << (to + 1)) - 1)) >> from; + } + + /** + * Sign extends a given value. + * @param value + * The value to sign extends. + * @param bitsUsed + * The number bits used within this value. + * @return + * A sign extended value. + */ + public static int signExtend(int value, int bitsUsed) { + return (value << (32 - bitsUsed)) >> (32 - bitsUsed); + } + + /** + * Returns true, if the addition of both operands as unsigned integers will cause an overflow. + * At the moment, this converts both values to longs and checks if the 33rd bit (which actually represents the carry) + * overflows. + */ + public static boolean unsignedAddOverflow(int operand1, int operand2) { + long value1 = (long)operand1 & 0xFFFFFFFFL; + long value2 = (long)operand2 & 0xFFFFFFFFL; + + return ((value1 + value2) & 0x100000000L) != 0; + } + + /** + * Returns true, if the subtraction of both operand1 - operand2 (both unsigned) will issue a borrow. + */ + public static boolean unsignedSubOverflow(int operand1, int operand2) { + operand1 += Integer.MIN_VALUE; + operand2 += Integer.MIN_VALUE; + + return operand1 < operand2; + } + + /** + * Returns true, if the addition of both operands as signed integers will cause an overflow. + * This basically checks <code>operand1 + operand2 > Integer.MAX_VALUE</code>. + */ + public static boolean signedAddOverflow(int operand1, int operand2) { + return operand1 > Integer.MAX_VALUE - operand2; + } + + /** + * Returns true, if the subtraction of operand1 from operand (as signed integers) + * will cause an overflow. + * This basically checks <code>operand1 - operand2 < Integer.MIN_VALUE</code>. + */ + public static boolean signedSubOverflow(int operand1, int operand2) { + // if the MSB is already set in any of the operands, then no overflow can + // occur + if (operand1 >= 0) { + return (operand2 < 0) && ((operand1-operand2) < 0); + } + else { + return (operand2 > 0) && ((operand1-operand2) > 0); + } + } + + /** + * Performs a number of sanity tests that make sure that the above functions are working the + * manner described before.*/ + public static void runSanityTests() { + if (!Utils.unsignedAddOverflow(1, -1)) { + throw new RuntimeException("Error"); + } + + if (!Utils.unsignedAddOverflow(-1, -1)) { + throw new RuntimeException("Error"); + } + + if (!Utils.unsignedAddOverflow(-1, 1)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedAddOverflow(10000, 10000)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedSubOverflow(-1, 1)) { + throw new RuntimeException("Error"); + } + + if (!Utils.unsignedSubOverflow(1, -1)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedSubOverflow(-1, -1)) { + throw new RuntimeException("Error"); + } + + if (Utils.unsignedSubOverflow(10, 0)) { + throw new RuntimeException("Error"); + } + + if (!Utils.unsignedSubOverflow(0, 10)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedAddOverflow(0x70000000, 0x10000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedAddOverflow(0x90000000, 0x10000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedAddOverflow(0x50000000, 0x50000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedAddOverflow(0x60000000, 0x10000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedAddOverflow(0x10000000, 0x60000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedSubOverflow(0x80000000, 0x30000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedSubOverflow(0x30000000, 0x80000000)) { + throw new RuntimeException("Error"); + } + + if (!Utils.signedSubOverflow(0, 0x80000000)) { + throw new RuntimeException("Error"); + } + + if (Utils.signedSubOverflow(0, 0x70000000)) { + throw new RuntimeException("Error"); + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-18 17:06:44
|
Revision: 133 http://svn.sourceforge.net/pearcolator/?rev=133&view=rev Author: michael_baer Date: 2007-06-18 10:06:44 -0700 (Mon, 18 Jun 2007) Log Message: ----------- First version that runs libc "Hello World" in Thumb code Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/generic/execution/InterpreterController.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/DBT_Options.java 2007-06-18 17:06:44 UTC (rev 133) @@ -19,7 +19,7 @@ public class DBT_Options { /** Remove features that will only work on jikes? */ - public final static boolean buildForSunVM = false; + public final static boolean buildForSunVM = true; /** Enable the profiling of application during interpretation? */ public final static boolean profileDuringInterpretation = true; @@ -102,7 +102,7 @@ public static boolean debugTranslation = true; /** In ProcessSpace, print syscall numbers. */ - public static boolean debugSyscall = false; + public static boolean debugSyscall = true; /** In ProcessSpace, print syscall numbers. */ public static boolean debugSyscallMore = false; Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-18 17:06:44 UTC (rev 133) @@ -19,7 +19,6 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; -import org.binarytranslator.generic.os.process.ProcessSpace; /** * This class transfers an ARM instruction into a human-readable assembly @@ -54,7 +53,7 @@ decodedInstruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction); } - DisassemblingVisitor disassembler = new DisassemblingVisitor(address); + DisassemblingVisitor disassembler = new DisassemblingVisitor(); decodedInstruction.visit(disassembler); return disassembler.result; @@ -130,17 +129,9 @@ /** This field receives the disassembled instruction. */ private ARM_DisassembledInstruction result; - /** The address of the instruction which is currently decoded or -1, if that address is not known. */ - private int address; - private DisassemblingVisitor() { - this.address = -1; } - private DisassemblingVisitor(int address) { - this.address = address; - } - /** Wraps a decoded assembly statement within an {@link ARM_DisassembledInstruction} object and * stores it as the result of this operation. */ private void setResult(String assembly) { @@ -180,10 +171,7 @@ op.getShiftAmount()); case RegisterOffset: - if (address != -1) - return String.format("#0x%x", op.getOffset() + address + 8); - else - return String.format("#<%d + pc>", op.getOffset()); + return String.format("#<r%d + %d>", op.getRegister(), op.getOffset()); case Register: return "r" + op.getRegister(); @@ -361,11 +349,7 @@ public void visit(Branch instr) { String mnemonic = instr.link() ? "BL" : "B"; - - if (address != -1) - setResult(String.format("%s%s #%d", mnemonic, cond(instr), instr.getOffset() + address + 8)); - else - setResult(String.format("%s%s #<%d + pc>", mnemonic, cond(instr), instr.getOffset())); + setResult(String.format("%s%s [PC + %s]", mnemonic, cond(instr), operand(instr.offset))); } public void visit(BranchExchange instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-18 17:06:44 UTC (rev 133) @@ -336,10 +336,14 @@ } else { //bit8==bit9==bit10==1? - if ((instr & 0x70) == 0x70) + if ((instr & 0x700) == 0x700) return factory.createBranchExchange(instr); - return factory.createDataProcessing(instr); + //We're not treating multiplication as data processing + if (Utils.getBits(instr, 6, 10) == 13) + return factory.createIntMultiply(instr); + else + return factory.createDataProcessing(instr); } } } @@ -361,20 +365,15 @@ @Override <T> T decode(short instr, ARM_InstructionFactory<T> factory) { - if (Utils.getBit(instr, 11)) { - return factory.createSingleDataTransfer(instr); + //bit9==bit10==bit11==1? + if ((instr & 0x0E00) == 0x0E00) { + if (Utils.getBit(instr, 8)) + return factory.createSoftwareInterrupt(instr); + else + return factory.createUndefinedInstruction(instr); } - else { - //bit9==bit10==bit11==1? - if ((instr & 0xE0) == 0xE0) { - if (Utils.getBit(instr, 8)) - return factory.createSoftwareInterrupt(instr); - else - return factory.createUndefinedInstruction(instr); - } - - return factory.createBranch(instr); - } + + return factory.createBranch(instr); } } @@ -424,7 +423,7 @@ */ static <T> T decode(short instruction, ARM_InstructionFactory<T> factory) { - int bits_12_15 = Utils.getBits(instruction, 12, 15); + int bits_12_15 = (instruction & 0xF000) >>> 12; return prefixDecoders[bits_12_15].decode(instruction, factory); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-18 17:06:44 UTC (rev 133) @@ -22,6 +22,8 @@ /** A base class for all (conditional) ARM instructions. */ public abstract static class Instruction { + protected final boolean isThumb; + public enum Condition { EQ, NE, CS, CC, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV } @@ -31,15 +33,22 @@ private Instruction () { this.condition = Condition.AL; + this.isThumb = true; } private Instruction (Condition condition) { this.condition = condition; + this.isThumb = true; } private Instruction(int instr) { condition = Condition.values()[(instr & 0xF0000000) >>> 28]; + this.isThumb = false; } + + public final int size() { + return isThumb ? 2 : 4; + } /** Returns the condition code that specifies, under which circumstances this operation shall be executed. */ public final Condition getCondition() { @@ -54,69 +63,6 @@ /** All instruction classes are meant to implement the visitor pattern. This is the pattern's visit method. */ public abstract void visit(ARM_InstructionVisitor visitor); } - - /** Base class for multiply operations. */ - protected abstract static class MultiplyTemplate extends Instruction { - - /** @see #updateConditionCodes() */ - protected final boolean updateConditionCodes; - - /** @see #accumulate() */ - protected final boolean accumulate; - - /** @see #getRs() */ - protected final byte Rs; - - /** @see #getRn() */ - protected final byte Rn; - - /** @see #getRm() */ - protected final byte Rm; - - /** @see #getRd() */ - protected final byte Rd; - - protected MultiplyTemplate(int instr) { - super(instr); - - updateConditionCodes = Utils.getBit(instr, 20); - accumulate = Utils.getBit(instr, 21); - Rd = (byte) Utils.getBits(instr, 16, 19); - Rn = (byte) Utils.getBits(instr, 12, 15); - Rs = (byte) Utils.getBits(instr, 8, 11); - Rm = (byte) Utils.getBits(instr, 0, 3); - } - - /** Returns true, if the condition codes shall be updated by the result of this operation. */ - public final boolean updateConditionCodes() { - return updateConditionCodes; - } - - /** Returns true, if this is the accumulate version of the instruction. */ - public final boolean accumulate() { - return accumulate; - } - - /** Returns the register number of the Rs operand register. */ - public final byte getRs() { - return Rs; - } - - /** Returns the register number of the Rm operand register. */ - public final byte getRm() { - return Rm; - } - - /** Returns the register number of the Rn operand register. */ - public final byte getRn() { - return Rn; - } - - /** Returns the register number of the Rd destination register. */ - public final byte getRd() { - return Rd; - } - } /** Base class for coprocessor instructions. */ protected static abstract class CoprocessorTemplate extends Instruction { @@ -473,7 +419,7 @@ updateConditionCodes = false; Rd = (byte)Utils.getBits(instr, 8, 10); Rn = (byte)(Utils.getBit(instr, 11) ? ARM_Registers.SP : ARM_Registers.PC); - operand2 = OperandWrapper.createImmediate(instr & 0xFF); + operand2 = OperandWrapper.createImmediate((instr & 0xFF) << 2); return; } @@ -484,12 +430,12 @@ opcode = Utils.getBit(instr, 7) ? Opcode.SUB : Opcode.ADD; Rd = (byte)ARM_Registers.SP; Rn = (byte)ARM_Registers.SP; - operand2 = OperandWrapper.createImmediate(instr & 0x7F); + operand2 = OperandWrapper.createImmediate((instr & 0x7F) << 2); return; } - if (Utils.getBits(instr, 14, 15) == 0x7) { + if (Utils.getBits(instr, 13, 15) == 0x7) { //first instruction of a long bl/blx if (DBT.VerifyAssertions) DBT._assert(Utils.getBits(instr, 11, 12) == 2); @@ -512,7 +458,7 @@ Rn = (byte)Utils.getBits(instr, 3, 5); updateConditionCodes = true; - if (Utils.getBits(instr, 11, 12) == 0) { + if (Utils.getBits(instr, 11, 12) != 0x3) { //shift by immediate opcode = Opcode.MOV; ShiftType type = ShiftType.values()[Utils.getBits(instr, 11, 12)]; @@ -559,19 +505,21 @@ Rd = (byte)(Utils.getBits(instr, 0, 2) + (Utils.getBit(instr, 7) ? 8 : 0)); Rn = Rd; operand2 = OperandWrapper.createRegister((byte)(Utils.getBits(instr, 3, 5) + (Utils.getBit(instr, 6) ? 8 : 0))); - updateConditionCodes = true; switch (Utils.getBits(instr, 8, 9)) { case 0: opcode = Opcode.ADD; + updateConditionCodes = false; break; case 1: opcode = Opcode.CMP; + updateConditionCodes = true; break; case 2: opcode = Opcode.MOV; + updateConditionCodes = false; break; case 3: @@ -631,6 +579,7 @@ case 8: opcode = Opcode.TST; operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; break; case 9: @@ -641,11 +590,13 @@ case 10: opcode = Opcode.CMP; operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; break; case 11: opcode = Opcode.CMN; operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; break; case 12: @@ -778,7 +729,7 @@ Utils.getBits(instr, 12, 15) == 0x9) { //load from literal pool or stack load/store Rd = (byte) Utils.getBits(instr, 8, 10); - offset = OperandWrapper.createImmediate(instr & 0xFF); + offset = OperandWrapper.createImmediate((instr & 0xFF) * 4); isLoad = Utils.getBit(instr, 11); signExtend = false; size = TransferSize.Word; @@ -812,7 +763,6 @@ } else { //load/store word/halfword/byte with immediate offset - offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10)); isLoad = Utils.getBit(instr, 11); signExtend = false; @@ -824,6 +774,23 @@ //transfer Half-word size = TransferSize.HalfWord; } + + switch (size) { + case Word: + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10) << 2); + break; + + case HalfWord: + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10) << 1); + break; + + case Byte: + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10)); + break; + + default: + throw new RuntimeException("Unexpected transfer size."); + } } } } @@ -947,23 +914,105 @@ } /** Represents a normal (not long) multiply instruction. */ - public final static class IntMultiply extends MultiplyTemplate { + public final static class IntMultiply extends Instruction { + + /** @see #updateConditionCodes() */ + protected final boolean updateConditionCodes; + + /** @see #accumulate() */ + protected final boolean accumulate; + + /** @see #getRs() */ + protected final byte Rs; + + /** @see #getRn() */ + protected final byte Rn; + + /** @see #getRm() */ + protected final byte Rm; + + /** @see #getRd() */ + protected final byte Rd; + + protected IntMultiply(short instr) { + updateConditionCodes = true; + accumulate = false; + Rd = (byte)Utils.getBits(instr, 0, 2); + Rm = (byte)Utils.getBits(instr, 3, 5); + Rn = Rd; + Rs = Rd; + } protected IntMultiply(int instr) { super(instr); + updateConditionCodes = Utils.getBit(instr, 20); + accumulate = Utils.getBit(instr, 21); + Rd = (byte) Utils.getBits(instr, 16, 19); + Rn = (byte) Utils.getBits(instr, 12, 15); + Rs = (byte) Utils.getBits(instr, 8, 11); + Rm = (byte) Utils.getBits(instr, 0, 3); + //check for instruction combinations that show undefined behaviour on ARM if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } + + /** Returns true, if the condition codes shall be updated by the result of this operation. */ + public final boolean updateConditionCodes() { + return updateConditionCodes; + } + /** Returns true, if this is the accumulate version of the instruction. */ + public final boolean accumulate() { + return accumulate; + } + + /** Returns the register number of the Rs operand register. */ + public final byte getRs() { + return Rs; + } + + /** Returns the register number of the Rm operand register. */ + public final byte getRm() { + return Rm; + } + + /** Returns the register number of the Rn operand register. */ + public final byte getRn() { + return Rn; + } + + /** Returns the register number of the Rd destination register. */ + public final byte getRd() { + return Rd; + } + public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); } } /** Represents a long multiply instruction. */ - public final static class LongMultiply extends MultiplyTemplate { + public final static class LongMultiply extends Instruction { + /** @see #updateConditionCodes() */ + protected final boolean updateConditionCodes; + + /** @see #accumulate() */ + protected final boolean accumulate; + + /** @see #getRs() */ + protected final byte Rs; + + /** @see #getRn() */ + protected final byte RdLow; + + /** @see #getRm() */ + protected final byte Rm; + + /** @see #getRd() */ + protected final byte RdHigh; + /** @see #isUnsigned() */ protected final boolean unsigned; @@ -971,19 +1020,45 @@ super(instr); unsigned = Utils.getBit(instr, 22); + updateConditionCodes = Utils.getBit(instr, 20); + accumulate = Utils.getBit(instr, 21); + RdHigh = (byte) Utils.getBits(instr, 16, 19); + RdLow = (byte) Utils.getBits(instr, 12, 15); + Rs = (byte) Utils.getBits(instr, 8, 11); + Rm = (byte) Utils.getBits(instr, 0, 3); //check for instruction combinations that show undefined behaviour on ARM - if (DBT.VerifyAssertions) DBT._assert(Rd != 15); + if (DBT.VerifyAssertions) DBT._assert(RdHigh != 15 && RdLow != 15); } + /** Returns true, if the condition codes shall be updated by the result of this operation. */ + public final boolean updateConditionCodes() { + return updateConditionCodes; + } + + /** Returns true, if this is the accumulate version of the instruction. */ + public final boolean accumulate() { + return accumulate; + } + + /** Returns the register number of the Rs operand register. */ + public final byte getRs() { + return Rs; + } + + /** Returns the register number of the Rm operand register. */ + public final byte getRm() { + return Rm; + } + /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ public final byte getRdHigh() { - return Rd; + return RdHigh; } /** Long multiplication stores its result in two registers. This function gets the register which receives the low int. */ public final byte getRdLow() { - return Rn; + return RdLow; } /** Returns true, if this is an unsigned multiplication or false if it is a signed multiplication. */ @@ -1074,11 +1149,12 @@ forceUser = false; writeBack = true; isLoad = Utils.getBit(instr, 11); - incrementBase = postIndexing = isLoad; int regList = instr & 0xFF; - if (Utils.getBit(instr, 14)) { + if (!Utils.getBit(instr, 14)) { + incrementBase = postIndexing = isLoad; + //PUSH / POP registers baseRegister = ARM_Registers.SP; @@ -1097,6 +1173,7 @@ else { //LDMIA/STMIA baseRegister = (byte)Utils.getBits(instr, 8, 10); + incrementBase = postIndexing = true; } registerList = regList; @@ -1192,19 +1269,23 @@ protected final boolean link; /** @see #getOffset() */ - protected final int offset; + protected final OperandWrapper offset; public Branch(short instr) { - super (Utils.getBit(instr, 13) ? Condition.values()[Utils.getBits(instr, 8, 11)] : Condition.AL); - - if (Utils.getBit(instr, 13)) { - offset = instr & 0xFF; + super (Utils.getBit(instr, 13) ? Condition.AL : Condition.values()[Utils.getBits(instr, 8, 11)]); + + if (!Utils.getBit(instr, 13)) { + offset = OperandWrapper.createImmediate(Utils.signExtend(instr & 0xFF, 8) << 1); link = false; } else { - offset = Utils.getBits(instr, 0, 10); link = Utils.getBit(instr, 12); + if (link) + offset = OperandWrapper.createRegisterOffset(link ? ARM_Registers.LR : ARM_Registers.PC, (Utils.getBits(instr, 0, 10) << 1) - 2); + else + offset = OperandWrapper.createImmediate(Utils.signExtend(Utils.getBits(instr, 0, 10), 11) << 1); + //only the second instruction of a long branch is actually a branch if (DBT.VerifyAssertions && link) DBT._assert(Utils.getBit(instr, 11)); } @@ -1214,7 +1295,7 @@ public Branch(int instr) { super(instr); link = Utils.getBit(instr, 24); - offset = Utils.signExtend((instr & 0xFFFFFF) << 2, 26); + offset = OperandWrapper.createImmediate(Utils.signExtend((instr & 0xFFFFFF) << 2, 26)); } /** Should the current PC be put into the lr? */ @@ -1223,7 +1304,7 @@ } /** The offset of the target address to the PC */ - public final int getOffset() { + public final OperandWrapper getOffset() { return offset; } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-18 17:06:44 UTC (rev 133) @@ -374,21 +374,25 @@ public void execute() { if (isConditionTrue()) { + int nextInstruction = conditionalInstruction.getSuccessor(ps.getCurrentInstructionAddress()); conditionalInstruction.execute(); - int nextInstruction = conditionalInstruction.getSuccessor(ps.getCurrentInstructionAddress()); - if (nextInstruction != -1) ps.setCurrentInstructionAddress(nextInstruction); } - else - ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress()+4); + else { + ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress() + (regs.getThumbMode() ? 2 : 4)); + } } public int getSuccessor(int pc) { //if this instruction is not a jump, then we can tell what the next instruction will be. - if (conditionalInstruction.getSuccessor(pc) == pc + 4) - return pc + 4; + + int conditionalSuccessor = conditionalInstruction.getSuccessor(pc); + boolean thumbMode = (pc & 0x1) == 1; + + if (conditionalSuccessor == pc + 4 && !thumbMode) + return conditionalSuccessor; //ARM may have conditional non-jump instructions else return -1; } @@ -463,12 +467,22 @@ protected DataProcessing(ARM_Instructions.DataProcessing instr) { i = instr; } + + @Override + public String toString() { + return i.toString(); + } /** Returns the value of operand 1 of the data processing instruction. This is always a register value. */ protected int resolveOperand1() { if (i.Rn == ARM_Registers.PC) { - return regs.readPC(); + int value = regs.readPC(); + + if (i.isThumb && !i.updateConditionCodes && i.opcode == Opcode.ADD) + value = value & 0xFFFFFFFC; + + return value; } return regs.get(i.Rn); @@ -551,7 +565,7 @@ public int getSuccessor(int pc) { if (i.Rd != 15) - return pc + 4; + return pc + i.size(); else return -1; } @@ -925,11 +939,16 @@ regs.set(i.Rd, tmp); } } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { //according to the ARM Architecture reference, using the pc as Rd yields an undefined //result. Therefore, we can safely assume that this instruction never equals a branch - return pc + 4; + return pc + i.size(); } } @@ -1036,7 +1055,7 @@ } else { //shall we switch to thumb mode - regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); + regs.set(ARM_Registers.PC, newpc); regs.setThumbMode((newpc & 0x1) != 0); } } @@ -1062,7 +1081,7 @@ ps.registers.switchOperatingMode(previousMode); } - if (i.writeBack) { + if (i.writeBack && !i.transferRegister(i.baseRegister)) { //write the last address we read from back to a register if (!i.incrementBase) { //backward reading @@ -1089,12 +1108,17 @@ return i.condition; } + @Override + public String toString() { + return i.toString(); + } + 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 (i.isLoad && transferPC) return -1; else - return pc + 4; + return pc + i.size(); } } @@ -1108,25 +1132,53 @@ } public void execute() { + + int destination; + BranchType branchType; + + if (i.offset.getType() != OperandWrapper.Type.Immediate) { + branchType = BranchType.INDIRECT_BRANCH; + } + else { + branchType = BranchType.DIRECT_BRANCH; + } + + destination = regs.readPC() + ResolvedOperand.resolve(regs, i.offset); + + if (DBT_Options.profileDuringInterpretation) { + if (i.link) { + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), destination, regs.get(ARM_Registers.PC) + i.size()); + } + else { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), destination, branchType); + } + } + //if we're supposed to link, then write the previous address into the link register if (i.link) { regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + (regs.getThumbMode() ? 2 : 4)); - - if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), regs.get(ARM_Registers.PC) + 4); } - else { - if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), BranchType.DIRECT_BRANCH); - } + + if (regs.getThumbMode()) + destination |= 1; + + regs.set(ARM_Registers.PC, destination); } public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc + i.getOffset() + 8; + if (i.offset.getType() == OperandWrapper.Type.Immediate) + return (pc + 2*i.size() + i.getOffset().getImmediate()) | (pc & 1); + else + return -1; } } @@ -1164,9 +1216,13 @@ break; case Register: - targetAddress = regs.get(i.target.getRegister()); + if (i.target.getRegister() != ARM_Registers.PC) + targetAddress = regs.get(i.target.getRegister()); + else + targetAddress = regs.readPC(); + thumb = (targetAddress & 0x1) != 0; - targetAddress = targetAddress & 0xFFFFFFFE; + //targetAddress = targetAddress & 0xFFFFFFFE; break; default: @@ -1177,7 +1233,7 @@ //if we're supposed to link, then write the previous address into the link register if (i.link) { regs.set(ARM_Registers.LR, regs.readPC() - (regs.getThumbMode() ? 2 : 4)); - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.CALL); + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), targetAddress, regs.get(ARM_Registers.PC) + i.size()); } else { ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.DIRECT_BRANCH); @@ -1191,10 +1247,15 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { //if we're jumping relative to the PC, then we can predict the next instruction - if (i.target.getType() == OperandWrapper.Type.RegisterOffset) { + if (i.target.getType() == OperandWrapper.Type.RegisterOffset && i.target.getRegister() == ARM_Registers.PC) { return pc + i.target.getOffset(); } else { //otherwise we can't predict it @@ -1238,9 +1299,14 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -1293,9 +1359,14 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc + 4; + return pc + i.size(); } } @@ -1319,13 +1390,18 @@ } } + @Override + public String toString() { + return i.toString(); + } + 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 - return pc + 4; + return pc + i.size(); } } @@ -1389,9 +1465,14 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { - return pc+4; + return pc + i.size(); } } @@ -1411,6 +1492,11 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { return -1; @@ -1445,8 +1531,13 @@ int base; //take ARM's PC offset into account - if (i.Rn == ARM_Registers.PC) + if (i.Rn == ARM_Registers.PC) { base = regs.readPC(); + + //Thumb mode has this weird way of accessing the PC sometimes + if (i.isThumb && i.isLoad) + base = base & 0xFFFFFFFC; + } else base = regs.get(i.Rn); @@ -1504,7 +1595,7 @@ regs.set(i.Rd, value); if (DBT_Options.profileDuringInterpretation) { - if (i.Rd == 15) + if (i.Rd == ARM_Registers.PC) ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), value, BranchType.INDIRECT_BRANCH); } } @@ -1551,13 +1642,18 @@ public Condition getCondition() { return i.condition; } + + @Override + public String toString() { + return i.toString(); + } public int getSuccessor(int pc) { //if we're loading to the PC, then the next instruction is undefined if (i.Rd == ARM_Registers.PC && i.isLoad) return -1; - return pc + 4; + return pc + i.size(); } } @@ -1582,6 +1678,12 @@ } private final class DebugNopInstruction implements ARM_Instruction { + + private boolean isThumb; + + public DebugNopInstruction(boolean isThumb) { + this.isThumb = isThumb; + } public void execute() { } @@ -1591,7 +1693,7 @@ } public int getSuccessor(int pc) { - return pc+4; + return pc + (isThumb ? 2 : 4); } } @@ -1661,21 +1763,21 @@ //TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createCoprocessorDataTransfer(int instr) { // TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createCoprocessorRegisterTransfer(int instr) { // TODO: Implement coprocessor instructions /*throw new RuntimeException( "Coprocessor instructions are not yet supported.");*/ - return new DebugNopInstruction(); + return new DebugNopInstruction(false); } public ARM_Instruction createIntMultiply(int instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-18 17:06:44 UTC (rev 133) @@ -1686,7 +1686,7 @@ } private void translateWriteback(OPT_RegisterOperand startAddress, OPT_RegisterOperand nextAddress) { - if (i.writeBack) { + if (i.writeBack && !i.transferRegister(i.baseRegister)) { OPT_RegisterOperand writeBackTarget = arm2ir.getRegister(i.baseRegister); //write the last address we read from back to a register @@ -1737,20 +1737,38 @@ } public void translate() { + + if (i.offset.getType() == OperandWrapper.Type.Immediate) { + //we can directly resolve this branch to a fixed address + if (i.link) + arm2ir.appendCall( readPC() + i.getOffset().getImmediate(), lazy, pc + i.size()); + else + arm2ir.appendBranch(readPC() + i.getOffset().getImmediate(), lazy, BranchType.DIRECT_BRANCH); + } + else { + + OPT_Operand offset = ResolvedOperand.resolve(ARM_Translator.this, i.offset); + OPT_RegisterOperand dest = arm2ir.getTempInt(0); + + arm2ir.appendInstruction(Binary.create(INT_ADD, dest, offset, new OPT_IntConstantOperand(readPC()))); + + if (i.link) { + arm2ir.appendCall(dest, lazy, pc + i.size()); + } + else { + arm2ir.appendBranch(dest, lazy, BranchType.INDIRECT_BRANCH); + } + } //if we're supposed to link, then write the previous address into the link register - if (i.link) { + if (i.link) { arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); } else { //we should never be returning from the goto arm2ir.getCurrentBlock().deleteNormalOut(); } - - if (i.link) - arm2ir.appendCall( readPC() + i.getOffset(), lazy, pc + 4); - else - arm2ir.appendBranch(readPC() + i.getOffset(), lazy, BranchType.DIRECT_BRANCH); + } public Condition getCondition() { @@ -1758,7 +1776,10 @@ } public int getSuccessor(int pc) { - return readPC() + i.getOffset(); + if (i.offset.getType() == OperandWrapper.Type.Immediate) + return readPC() + i.getOffset().getImmediate(); + else + return -1; } } @@ -2086,6 +2107,13 @@ //add the offset to the base register OPT_RegisterOperand tmp = arm2ir.getTempInt(0); arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, base, resolveOffset())); + + if (i.isThumb && i.isLoad && i.Rn == ARM_Registers.PC) { + //with thumb, bit 1 of the address is always ignored - address = address & 0xFFFFFFFC; + //see ARM reference manual for further details + arm2ir.appendInstruction(Binary.create(INT_AND, tmp.copyRO(), tmp.copy(), new OPT_IntConstantOperand(0xFFFFFFFC))); + } + return tmp.copy(); } Modified: src/org/binarytranslator/arch/arm/decoder/Utils.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/decoder/Utils.java 2007-06-18 17:06:44 UTC (rev 133) @@ -53,7 +53,7 @@ */ static final int getBits(short word, int from, int to) { if (DBT.VerifyAssertions) - DBT._assert(from < to && from >= 0 && to < 15); + DBT._assert(from < to && from >= 0 && to <= 15); return (word & ((1 << (to + 1)) - 1)) >> from; } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-06-18 17:06:44 UTC (rev 133) @@ -289,11 +289,13 @@ * or 4 (Thumb) to the program counter itself. */ public int readPC() { - if (getThumbMode()) { - return get(ARM_Registers.PC) + 4; + int pc = get(ARM_Registers.PC); + + if ((pc & 0x1) == 1) { + return (pc & 0xFFFFFFFE) + 4; } else { - return get(ARM_Registers.PC) + 8; + return pc + 8; } } @@ -377,7 +379,7 @@ * Processor in thumb mode? */ public boolean getThumbMode() { - return thumbMode; + return thumbMode || ((get(ARM_Registers.PC) & 1) != 0); } /** Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-06-18 17:06:44 UTC (rev 133) @@ -28,7 +28,9 @@ ARM_Instructions.Instruction instr; if (registers.getThumbMode()) { - short instruction = (short)memory.loadInstruction16(getCurrentInstructionAddress()); + int instrAddr = getCurrentInstructionAddress() & 0xFFFFFFFE; + System.out.println("Thumb syscall at: " + instrAddr); + short instruction = (short)memory.loadInstruction16(instrAddr); instr = ARM_InstructionDecoder.Thumb.decode(instruction); } else { @@ -44,11 +46,11 @@ //Use a mask to let both calls start from the same address int sysCallNr = ((ARM_Instructions.SoftwareInterrupt)instr).getInterruptNumber(); - if (sysCallNr == 0x123456) { + if (sysCallNr == 0x123456 || sysCallNr == 0xab) { sysCalls.doSysCall(registers.get(0)); //simulate a proper return from syscalls - setCurrentInstructionAddress(getCurrentInstructionAddress() + 4); + setCurrentInstructionAddress(getCurrentInstructionAddress() + instr.size()); } else { //switch the operating mode to Supervisor Modified: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-06-14 17:19:16 UTC (rev 132) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-06-18 17:06:44 UTC (rev 133) @@ -18,7 +18,7 @@ while (!ps.finished) { Interpreter.Instruction instruction = interpreter.decode(pc); - //System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); + System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); instruction.execute(); pc = instruction.getSuccessor(pc); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-14 17:19:15
|
Revision: 132 http://svn.sourceforge.net/pearcolator/?rev=132&view=rev Author: michael_baer Date: 2007-06-14 10:19:16 -0700 (Thu, 14 Jun 2007) Log Message: ----------- Moving further towards Thumb support Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/decoder/Utils.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/abi/Legacy.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/memory/AutoMappingMemory.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/loader/elf/ELF_File.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/DBT_Options.java 2007-06-14 17:19:16 UTC (rev 132) @@ -70,7 +70,7 @@ /** * Set this to true to translate only one instruction at a time. */ - public static boolean singleInstrTranslation = true; + public static boolean singleInstrTranslation = false; /** * Eliminate unneeded filling of register @@ -126,10 +126,12 @@ public final static int GID = 100; /** Stores the arguments given to the DBT by the user. These are NOT the arguments given to the executable. */ - private final static HashMap<String, String> dbtArguments = new HashMap<String, String>(); + private static HashMap<String, String> dbtArguments = null; /** Read and parse the command line arguments. */ public static void parseArguments(String[] args) { + + dbtArguments = new HashMap<String, String>(); try { ArrayList<String> remainingArguments = new ArrayList<String>(); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-06-14 17:19:16 UTC (rev 132) @@ -17,6 +17,7 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.SoftwareInterrupt; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Swap; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.generic.decoder.DisassembledInstruction; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -40,11 +41,19 @@ * @return A disassembled ARM instruction. */ public final static DisassembledInstruction disassemble(int address, - ProcessSpace ps) { + ARM_ProcessSpace ps) { - int binaryInstruction = ps.memory.loadInstruction32(address); - Instruction decodedInstruction = ARM_InstructionDecoder.decode(binaryInstruction); + Instruction decodedInstruction; + if ((address & 0x1) == 1) { + short binaryInstruction = (short)ps.memory.loadInstruction16(address & 0xFFFFFFFE); + decodedInstruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction); + } + else { + int binaryInstruction = ps.memory.loadInstruction32(address); + decodedInstruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction); + } + DisassemblingVisitor disassembler = new DisassemblingVisitor(address); decodedInstruction.visit(disassembler); @@ -170,7 +179,7 @@ return String.format("r%d %s #%d", op.getRegister(), op.getShiftType(), op.getShiftAmount()); - case PcRelative: + case RegisterOffset: if (address != -1) return String.format("#0x%x", op.getOffset() + address + 8); else Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-14 17:19:16 UTC (rev 132) @@ -3,312 +3,527 @@ import org.binarytranslator.arch.arm.decoder.ARM_Instructions.*; /** - * This class decodes an ARM instruction and uses a user-supplied ARM_InstructionFactory to create a class - * that represents the given instruction. + * This class decodes an ARM or Thumb instruction and uses a user-supplied + * ARM_InstructionFactory to create a class that represents the given + * instruction. * - * The decoder first performs a pseudo-switch on bits 27-25 of the instruction. - * For performance reasons, the switch is implemented as an array lookup (using the {@link #prefixDecoders} array), - * with single {@link Decoder} classes implementing the cases. - * - * ARM has a very cluttered opcode map, which is why the decoding process does not look very tidy. - * However, the presented decoded scheme has been derived by producing all possible instructions and then - * letting a data mining tool (specifically: Weka) create a decision tree to decode the single - * instruction classes. This has two implications: - * <ol> - * <li>The decoder is correct (at least, when I didn't introduce any typos), as Weka verified an error rate of 0% for this decision tree.</li> - * <li>The decoder is reasonably fast, considering Weka tries to build a shallow decision tree.</li> + * ARM has a very cluttered opcode map, which is why the decoding process does + * not look very tidy. However, the presented decoded scheme has been derived by + * producing all possible instructions and then letting a data mining tool + * (specifically: Weka) create a decision tree to decode the single instruction + * classes. This has two implications: + * <ol> + * <li>The decoder is correct (at least, if I didn't introduce any typos), as + * Weka verified an error rate of 0% for this decision tree.</li> + * <li>The decoder is reasonably fast, considering Weka tries to build a + * shallow decision tree.</li> * </ol> * * @author Michael Baer - * + * */ public class ARM_InstructionDecoder { - /** - * This table is used to perform a lookup on bits 25-27 of an instruction. - * According to the result of this lookup, the {@link Decoder} instances within this - * array perform the subsequent instruction decoding. */ - private static Decoder[] prefixDecoders = { - new decoder_000(), new decoder_001(), - new decoder_010(), new decoder_011(), - new decoder_100(), new decoder_101(), - new decoder_110(), new decoder_111() - }; - - /** - * This static field caches the default {@link ARM_InstructionFactory} implementation, which is used by {@link #decode(int)}. - * It is being lazily initialized once it is used for the first time. */ + /** + * This static field caches the default {@link ARM_InstructionFactory} + * implementation, which is used by {@link #decode(int)}. It is being + * lazily initialized once it is used for the first time. + */ private static DefaultFactory _defaultFactory; - - /** - * This class performs additional instruction decoding, after bits 25-27 of an instruction have been - * determined. The class is basically just a way of substituting a switch by an array lookup+virtual method call. - * */ - private static abstract class Decoder { - abstract <T> T decode(int instr, ARM_InstructionFactory<T> factory); - } - - /** Decoder which assumes that bits 27-25 == 000. */ - private static class decoder_000 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + /** + * + * The decoder first performs a pseudo-switch on bits 27-25 of the + * instruction. For performance reasons, the switch is implemented as an array + * lookup (using the {@link #prefixDecoders} array), with single + * {@link Decoder} classes implementing the cases. + * + */ + public static class ARM32 { + /** + * This table is used to perform a lookup on bits 25-27 of an instruction. + * According to the result of this lookup, the {@link Decoder} instances + * within this array perform the subsequent instruction decoding. + */ + private static Decoder[] prefixDecoders = { new decoder_000(), + new decoder_001(), new decoder_010(), new decoder_011(), + new decoder_100(), new decoder_101(), new decoder_110(), + new decoder_111() }; + /** + * This class performs additional instruction decoding, after bits 25-27 of + * an instruction have been determined. The class is basically just a way of + * substituting a switch by an array lookup+virtual method call. + */ + private static abstract class Decoder { + abstract <T> T decode(int instr, ARM_InstructionFactory<T> factory); + } + + /** Decoder which assumes that bits 27-25 == 000. */ + private static class decoder_000 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } + + byte bits_7_4 = (byte) Utils.getBits(instr, 4, 7); + + if (bits_7_4 == 0 && ((instr & 0x01900000) == 0x01000000)) { + // Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false + // && Utils.getBit(instr, 20) == false + if (Utils.getBit(instr, 21)) + return factory.createMoveToStatusRegister(instr); + else + return factory.createMoveFromStatusRegister(instr); + } + + if (((bits_7_4 & 0xD) == 1) && ((instr & 0x01F00000) == 0x01200000)) { + // bits 7-4 == 1 || bits 7-4 == 3 + // Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false + // && Utils.getBit(instr, 22) == false && Utils.getBit(instr, 21) == + // true && Utils.getBit(instr, 20) == false + return factory.createBranchExchange(instr); + } + + if ((bits_7_4 & 9) == 9) { + // bits7-4 = 1xx1 + if (bits_7_4 == 9) { + if (Utils.getBit(instr, 23)) { + return factory.createLongMultiply(instr); + } else { + if (Utils.getBit(instr, 24)) + return factory.createSwap(instr); + else + return factory.createIntMultiply(instr); + } + } else + return factory.createSingleDataTransfer(instr); + } + + return factory.createDataProcessing(instr); } - - byte bits_7_4 = (byte)Utils.getBits(instr, 4, 7); + } - if (bits_7_4 == 0 && ((instr & 0x01900000) == 0x01000000)) { - //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 20) == false - if (Utils.getBit(instr, 21)) - return factory.createMoveToStatusRegister(instr); - else - return factory.createMoveFromStatusRegister(instr); + /** Decoder which assumes that bits 27-25 == 001. */ + private static class decoder_001 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } + + if (((instr & 0x01900000) == 0x01000000)) { + // Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false + // && Utils.getBit(instr, 20) == false + if (Utils.getBit(instr, 21)) + return factory.createMoveToStatusRegister(instr); + else + return factory.createUndefinedInstruction(instr); + } + + return factory.createDataProcessing(instr); } - - if (((bits_7_4 & 0xD) == 1) && ((instr & 0x01F00000) == 0x01200000)) { - //bits 7-4 == 1 || bits 7-4 == 3 - //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 22) == false && Utils.getBit(instr, 21) == true && Utils.getBit(instr, 20) == false - return factory.createBranchExchange(instr); + } + + /** Decoder which assumes that bits 27-25 == 010. */ + private static class decoder_010 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } else { + return factory.createSingleDataTransfer(instr); + } } - - if ((bits_7_4 & 9) == 9) { - //bits7-4 = 1xx1 - if (bits_7_4 == 9) { - if (Utils.getBit(instr, 23)) { - return factory.createLongMultiply(instr); - } - else { - if (Utils.getBit(instr, 24)) - return factory.createSwap(instr); - else - return factory.createIntMultiply(instr); - } + } + + /** Decoder which assumes that bits 27-25 == 011. */ + private static class decoder_011 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? or bit4==true + if ((instr & 0xF0000000) == 0xF0000000 || Utils.getBit(instr, 4)) { + return factory.createUndefinedInstruction(instr); + } else { + return factory.createSingleDataTransfer(instr); } - else - return factory.createSingleDataTransfer(instr); } - - return factory.createDataProcessing(instr); } - } - - /** Decoder which assumes that bits 27-25 == 001. */ - private static class decoder_001 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); - } - - if (((instr & 0x01900000) == 0x01000000)) { - //Utils.getBit(instr, 24) == true && Utils.getBit(instr, 23) == false && Utils.getBit(instr, 20) == false - if (Utils.getBit(instr, 21)) - return factory.createMoveToStatusRegister(instr); - else + /** Decoder which assumes that bits 27-25 == 100. */ + private static class decoder_100 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { return factory.createUndefinedInstruction(instr); + } + + return factory.createBlockDataTransfer(instr); } - - return factory.createDataProcessing(instr); } - } - - /** Decoder which assumes that bits 27-25 == 010. */ - private static class decoder_010 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + /** Decoder which assumes that bits 27-25 == 101. */ + private static class decoder_101 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createBranchExchange(instr); + } + + return factory.createBranch(instr); } - else { - return factory.createSingleDataTransfer(instr); + } + + /** Decoder which assumes that bits 27-25 == 110. */ + private static class decoder_110 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + return factory.createCoprocessorDataTransfer(instr); } } - } - - /** Decoder which assumes that bits 27-25 == 011. */ - private static class decoder_011 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? or bit4==true - if ((instr & 0xF0000000) == 0xF0000000 || Utils.getBit(instr, 4)) { - return factory.createUndefinedInstruction(instr); + /** Decoder which assumes that bits 27-25 == 111. */ + private static class decoder_111 extends Decoder { + + @Override + <T> T decode(int instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 24)) { + // Check condition==never? + if ((instr & 0xF0000000) == 0xF0000000) { + return factory.createUndefinedInstruction(instr); + } else { + return factory.createSoftwareInterrupt(instr); + } + } else { + if (Utils.getBit(instr, 4)) { + return factory.createCoprocessorRegisterTransfer(instr); + } else { + return factory.createCoprocessorDataProcessing(instr); + } + } } - else { - return factory.createSingleDataTransfer(instr); + } + + /** + * Decodes a given ARM instruction and returns an object representation of + * it. + * + * @param instruction + * A binary ARM instruction, that is to be decoded. + * @return A version of the instruction, which has been decoded into an + * instance of {@link Instruction}. Use the + * {@link Instruction#visit(ARM_InstructionVisitor)} method to + * further interact with the returned instance. + */ + public static Instruction decode(int instruction) { + if (_defaultFactory == null) + _defaultFactory = new DefaultFactory(); + + return decode(instruction, _defaultFactory); + } + + public static int fastpathCount = 0; + + /** + * Decodes a binary ARM instruction. This method will use the supplied + * {@link ARM_InstructionFactory} to create an object representation of the + * decoded instruction. + * + * @param <T> + * The return type depends on whatever the + * {@link ARM_InstructionFactory} actually creates. + * @param instruction + * A binary representation of the instruction that is to be + * decoded. + * @param factory + * A factory, that will create object instances of the instruction. + * @return An object representation of the decoded instruction. + */ + static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { + + if (ARM_Options.DATAPROCESSING_DECODER_FASTPATH) { + + // Check condition!=never? + if ((instruction & 0xF0000000) != 0xF0000000) { + + if ((instruction & 0x0F000000) == 0x02000000) { + fastpathCount++; + return factory.createDataProcessing(instruction); + } + } + + int bits_27_25 = Utils.getBits(instruction, 25, 27); + return prefixDecoders[bits_27_25].decode(instruction, factory); + } else { + int bits_27_25 = Utils.getBits(instruction, 25, 27); + return prefixDecoders[bits_27_25].decode(instruction, factory); } } } - /** Decoder which assumes that bits 27-25 == 100. */ - private static class decoder_100 extends Decoder { + /** + * The instruction decoder for Thumb instructions. It works similar to the ARM32 decoder and has + * also been created using the Weka datamining tool. + */ + public static class Thumb { + /** + * This class performs additional instruction decoding, after bits 12-15 of + * an instruction have been determined. The class is basically just a way of + * substituting a switch by an array lookup+virtual method call. + */ + private static abstract class Decoder { + abstract <T> T decode(short instr, ARM_InstructionFactory<T> factory); + } + + /** This table is used to perform a lookup on bits 12-15 of an instruction. + * According to the result of this lookup, the {@link Decoder} instances + * within this array perform the subsequent instruction decoding. + */ + private static Decoder[] prefixDecoders = { + new DataProcessing_Decoder(), new DataProcessing_Decoder(), + new DataProcessing_Decoder(), new DataProcessing_Decoder(), + new Decoder_0100(), new SingleDataTransfer_Decoder(), + new SingleDataTransfer_Decoder(), new SingleDataTransfer_Decoder(), + new SingleDataTransfer_Decoder(), new SingleDataTransfer_Decoder(), + new DataProcessing_Decoder(), new Decoder_1011(), + new BlockDataTransfer_Decoder(), new Decoder_1101(), + new Decoder_1110(), new Decoder_1111()}; + + private static class DataProcessing_Decoder extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + return factory.createDataProcessing(instr); } - - return factory.createBlockDataTransfer(instr); } - } - - /** Decoder which assumes that bits 27-25 == 101. */ - private static class decoder_101 extends Decoder { + + private static class SingleDataTransfer_Decoder extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createBranchExchange(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + return factory.createSingleDataTransfer(instr); } - - return factory.createBranch(instr); } - } - - /** Decoder which assumes that bits 27-25 == 110. */ - private static class decoder_110 extends Decoder { + + private static class BlockDataTransfer_Decoder extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - return factory.createCoprocessorDataTransfer(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + return factory.createBlockDataTransfer(instr); + } } - } - - /** Decoder which assumes that bits 27-25 == 111. */ - private static class decoder_111 extends Decoder { + + private static class Decoder_0100 extends Decoder { - @Override - <T> T decode(int instr, ARM_InstructionFactory<T> factory) { - if (Utils.getBit(instr, 24)) { - //Check condition==never? - if ((instr & 0xF0000000) == 0xF0000000) { - return factory.createUndefinedInstruction(instr); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + return factory.createSingleDataTransfer(instr); } else { - return factory.createSoftwareInterrupt(instr); + //bit8==bit9==bit10==1? + if ((instr & 0x70) == 0x70) + return factory.createBranchExchange(instr); + + return factory.createDataProcessing(instr); } } - else { - if (Utils.getBit(instr, 4)) { - return factory.createCoprocessorRegisterTransfer(instr); + } + + private static class Decoder_1011 extends Decoder { + + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 10)) { + return factory.createBlockDataTransfer(instr); } else { - return factory.createCoprocessorDataProcessing(instr); + return factory.createDataProcessing(instr); } } } - } - - /** - * Decodes a given ARM instruction and returns an object representation of it. - * @param instruction - * A binary ARM instruction, that is to be decoded. - * @return - * A version of the instruction, which has been decoded into an instance of {@link Instruction}. - * Use the {@link Instruction#visit(ARM_InstructionVisitor)} method to further interact with the - * returned instance. - */ - public static Instruction decode(int instruction) { - if (_defaultFactory == null) - _defaultFactory = new DefaultFactory(); - return decode(instruction, _defaultFactory); - } + private static class Decoder_1101 extends Decoder { - public static int fastpathCount = 0; - - /** - * Decodes a binary ARM instruction. This method will use the supplied {@link ARM_InstructionFactory} - * to create an object representation of the decoded instruction. - * @param <T> - * The return type depends on whatever the {@link ARM_InstructionFactory} actually creates. - * @param instruction - * A binary representation of the instruction that is to be decoded. - * @param factory - * A factory, that will create object instances of the instruction. - * @return - * An object representation of the decoded instruction. - */ - static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + return factory.createSingleDataTransfer(instr); + } + else { + //bit9==bit10==bit11==1? + if ((instr & 0xE0) == 0xE0) { + if (Utils.getBit(instr, 8)) + return factory.createSoftwareInterrupt(instr); + else + return factory.createUndefinedInstruction(instr); + } + + return factory.createBranch(instr); + } + } + } - if (ARM_Options.DATAPROCESSING_DECODER_FASTPATH) { - - //Check condition!=never? - if ((instruction & 0xF0000000) != 0xF0000000) { + private static class Decoder_1110 extends Decoder { - if ((instruction & 0x0F000000) == 0x02000000) { - fastpathCount++; - return factory.createDataProcessing(instruction); + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + if (Utils.getBit(instr, 0)) + return factory.createUndefinedInstruction(instr); + else + return factory.createBranchExchange(instr); } + else { + return factory.createBranch(instr); + } } + } - int bits_27_25 = Utils.getBits(instruction, 25, 27); - return prefixDecoders[bits_27_25].decode(instruction, factory); + private static class Decoder_1111 extends Decoder { + + @Override + <T> T decode(short instr, ARM_InstructionFactory<T> factory) { + if (Utils.getBit(instr, 11)) { + return factory.createBranch(instr); + } + else { + return factory.createDataProcessing(instr); + } + } } - else { - int bits_27_25 = Utils.getBits(instruction, 25, 27); - return prefixDecoders[bits_27_25].decode(instruction, factory); + + /** + * Decodes a binary Thumb instruction. This method will use the supplied + * {@link ARM_InstructionFactory} to create an object representation of the + * decoded instruction. + * + * @param <T> + * The return type depends on whatever the + * {@link ARM_InstructionFactory} actually creates. + * @param instruction + * A binary representation of the instruction that is to be + * decoded. + * @param factory + * A factory, that will create object instances of the instruction. + * @return An object representation of the decoded instruction. + */ + static <T> T decode(short instruction, ARM_InstructionFactory<T> factory) { + + int bits_12_15 = Utils.getBits(instruction, 12, 15); + return prefixDecoders[bits_12_15].decode(instruction, factory); } + + /** + * Decodes a given Thumb instruction and returns an object representation of + * it. + * + * @param instruction + * A binary ARM instruction, that is to be decoded. + * @return A version of the instruction, which has been decoded into an + * instance of {@link Instruction}. Use the + * {@link Instruction#visit(ARM_InstructionVisitor)} method to + * further interact with the returned instance. + */ + public static Instruction decode(short instruction) { + if (_defaultFactory == null) + _defaultFactory = new DefaultFactory(); + + return decode(instruction, _defaultFactory); + } } - + /** - * An interface to a factory class, which will create the actual object representations of the - * instruction classes decoded by {@link ARM_InstructionDecoder}. - * + * An interface to a factory class, which will create the actual object + * representations of the instruction classes decoded by + * {@link ARM_InstructionDecoder}. + * * @param <T> - * The type of the object representations, that shall be created when an ARM instruction is decoded. + * The type of the object representations, that shall be created when + * an ARM instruction is decoded. */ interface ARM_InstructionFactory<T> { T createDataProcessing(int instr); + T createSwap(int instr); + T createSingleDataTransfer(int instr); + T createBlockDataTransfer(int instr); + T createIntMultiply(int instr); + T createLongMultiply(int instr); + T createSoftwareInterrupt(int instr); + T createBranch(int instr); + T createBranchExchange(int instr); + T createCoprocessorDataTransfer(int instr); + T createCoprocessorDataProcessing(int instr); + T createCoprocessorRegisterTransfer(int instr); + T createMoveFromStatusRegister(int instr); + T createMoveToStatusRegister(int instr); + T createUndefinedInstruction(int instr); - + T createDataProcessing(short instr); + T createSwap(short instr); + T createSingleDataTransfer(short instr); + T createBlockDataTransfer(short instr); - T createshortMultiply(short instr); + + T createIntMultiply(short instr); + T createLongMultiply(short instr); - T createSoftwareshorterrupt(short instr); + + T createSoftwareInterrupt(short instr); + T createBranch(short instr); + T createBranchExchange(short instr); + T createCoprocessorDataTransfer(short instr); + T createCoprocessorDataProcessing(short instr); + T createCoprocessorRegisterTransfer(short instr); + T createMoveFromStatusRegister(short instr); + T createMoveToStatusRegister(short instr); + T createUndefinedInstruction(short instr); } - + /** - * A default implementation of the ARM instruction factory, which will create the - * appropriate classes from the {@link ARM_Instructions} namespace. + * A default implementation of the ARM instruction factory, which will create + * the appropriate classes from the {@link ARM_Instructions} namespace. */ - private static class DefaultFactory implements ARM_InstructionFactory<ARM_Instructions.Instruction> { + private static class DefaultFactory implements + ARM_InstructionFactory<ARM_Instructions.Instruction> { public Instruction createBlockDataTransfer(int instr) { return new BlockDataTransfer(instr); @@ -371,79 +586,63 @@ } public Instruction createBlockDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new BlockDataTransfer(instr); } public Instruction createBranch(short instr) { - // TODO Auto-generated method stub - return null; + return new Branch(instr); } public Instruction createBranchExchange(short instr) { - // TODO Auto-generated method stub - return null; + return new BranchExchange(instr); } public Instruction createCoprocessorDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support coprocessor instructions."); } public Instruction createCoprocessorDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support coprocessor instructions."); } public Instruction createCoprocessorRegisterTransfer(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support coprocessor instructions."); } public Instruction createDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; + return new DataProcessing(instr); } public Instruction createLongMultiply(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support long multiplications."); } public Instruction createMoveFromStatusRegister(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support status register transfers."); } public Instruction createMoveToStatusRegister(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support status register transfers."); } public Instruction createSingleDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new SingleDataTransfer(instr); } - public Instruction createSoftwareshorterrupt(short instr) { - // TODO Auto-generated method stub - return null; + public Instruction createSoftwareInterrupt(short instr) { + return new SoftwareInterrupt(instr); } public Instruction createSwap(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Thumb does not support SWAP instructions."); } public Instruction createUndefinedInstruction(short instr) { - // TODO Auto-generated method stub return null; } - public Instruction createshortMultiply(short instr) { - // TODO Auto-generated method stub - return null; + public Instruction createIntMultiply(short instr) { + return new IntMultiply(instr); } - } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-06-14 17:19:16 UTC (rev 132) @@ -2,6 +2,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper.ShiftType; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; /** * In the ARM decoder model, the decoding and usage (translating/interpreting/disassembling) of instructions @@ -149,7 +150,7 @@ /** Describes the type of the operand. */ public enum Type { Immediate, - PcRelative, + RegisterOffset, Register, ImmediateShiftedRegister, RegisterShiftedRegister, @@ -175,8 +176,8 @@ } /** Creates an operand wrapper representing an offset to the pc.*/ - public static OperandWrapper createPcRelative(int offset) { - return new PcRelativeOperand(offset); + public static OperandWrapper createRegisterOffset(byte register, int offset) { + return new RegisterOffsetOperand(register, offset); } public static OperandWrapper createRegisterShiftImmediate(byte register, ShiftType type, byte amount) { @@ -329,17 +330,19 @@ } } - protected static class PcRelativeOperand extends OperandWrapper { + protected static class RegisterOffsetOperand extends OperandWrapper { protected final int offset; + protected final byte register; - protected PcRelativeOperand(int offset) { + protected RegisterOffsetOperand(byte register, int offset) { this.offset = offset; + this.register = register; } @Override public byte getRegister() { - return 15; + return register; } @Override @@ -349,7 +352,7 @@ @Override public Type getType() { - return Type.PcRelative; + return Type.RegisterOffset; } } @@ -463,6 +466,46 @@ protected final OperandWrapper operand2; public DataProcessing(short instr) { + + if (Utils.getBits(instr, 12, 15) == 0xA) { + //add to SP or PC (load address) + opcode = Opcode.ADD; + updateConditionCodes = false; + Rd = (byte)Utils.getBits(instr, 8, 10); + Rn = (byte)(Utils.getBit(instr, 11) ? ARM_Registers.SP : ARM_Registers.PC); + operand2 = OperandWrapper.createImmediate(instr & 0xFF); + + return; + } + + if (Utils.getBits(instr, 12, 15) == 0xB) { + //add offset to SP + updateConditionCodes = false; + opcode = Utils.getBit(instr, 7) ? Opcode.SUB : Opcode.ADD; + Rd = (byte)ARM_Registers.SP; + Rn = (byte)ARM_Registers.SP; + operand2 = OperandWrapper.createImmediate(instr & 0x7F); + + return; + } + + if (Utils.getBits(instr, 14, 15) == 0x7) { + //first instruction of a long bl/blx + if (DBT.VerifyAssertions) DBT._assert(Utils.getBits(instr, 11, 12) == 2); + + //extract and sign-extend the offset + int offset = Utils.getBits(instr, 0, 10); + offset = Utils.signExtend(offset, 11) << 12; + operand2 = OperandWrapper.createImmediate(offset); + + opcode = Opcode.MOV; + Rd = ARM_Registers.LR; + updateConditionCodes = false; + Rn = 0; + + return; + } + if (Utils.getBits(instr, 13, 15) == 0) { //shift by immediate, add/subtract register or add/subtract immediate Rd = (byte)Utils.getBits(instr, 0, 2); @@ -506,99 +549,130 @@ opcode = Opcode.SUB; break; default: - throw new RuntimeException("Values other than 0-4 cannot be represented within 2 bits."); + throw new RuntimeException("Values other than 0-3 cannot be represented within 2 bits."); } } else { - Rd = (byte)Utils.getBits(instr, 0, 2); - byte finalRn = (byte)Utils.getBits(instr, 3, 5); - updateConditionCodes = true; - switch (Utils.getBits(instr, 6, 9)) { - case 0: - opcode = Opcode.AND; - operand2 = OperandWrapper.createRegister(Rd); - break; - case 1: - opcode = Opcode.EOR; - operand2 = OperandWrapper.createRegister(Rd); - break; + if (Utils.getBit(instr, 10)) { + //special data processing + Rd = (byte)(Utils.getBits(instr, 0, 2) + (Utils.getBit(instr, 7) ? 8 : 0)); + Rn = Rd; + operand2 = OperandWrapper.createRegister((byte)(Utils.getBits(instr, 3, 5) + (Utils.getBit(instr, 6) ? 8 : 0))); + updateConditionCodes = true; - case 2: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSL, finalRn); - break; + switch (Utils.getBits(instr, 8, 9)) { + case 0: + opcode = Opcode.ADD; + break; + + case 1: + opcode = Opcode.CMP; + break; + + case 2: + opcode = Opcode.MOV; + break; + + case 3: + throw new RuntimeException("This case is actually a BranchExchange."); + + default: + throw new RuntimeException("Only the values 0-3 can be represented within 2 bits."); + } + } + else { + //data processing-register + Rd = (byte)Utils.getBits(instr, 0, 2); + byte finalRn = (byte)Utils.getBits(instr, 3, 5); + updateConditionCodes = true; - case 3: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSR, finalRn); - break; + switch (Utils.getBits(instr, 6, 9)) { + case 0: + opcode = Opcode.AND; + operand2 = OperandWrapper.createRegister(Rd); + break; + case 1: + opcode = Opcode.EOR; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 2: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSL, finalRn); + break; + + case 3: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.LSR, finalRn); + break; + + case 4: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ASR, finalRn); + break; + + case 5: + opcode = Opcode.ADC; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 6: + opcode = Opcode.SBC; + operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; + break; + + case 7: + opcode = Opcode.MOV; + operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ROR, finalRn); + break; + + case 8: + opcode = Opcode.TST; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 9: + opcode = Opcode.RSB; + operand2 = OperandWrapper.createImmediate(0); + break; + + case 10: + opcode = Opcode.CMP; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 11: + opcode = Opcode.CMN; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + case 12: + opcode = Opcode.ORR; + operand2 = OperandWrapper.createRegister(Rd); + break; + + case 13: + throw new RuntimeException("This is actually a multiply instruction."); + + case 14: + opcode = Opcode.BIC; + operand2 = OperandWrapper.createRegister(finalRn); + finalRn = Rd; + break; + + case 15: + opcode = Opcode.MVN; + operand2 = OperandWrapper.createRegister(finalRn); + break; + + default: + throw new RuntimeException("Only values 0-15 can be represented within 4 bits."); + } - case 4: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ASR, finalRn); - break; - - case 5: - opcode = Opcode.ADC; - operand2 = OperandWrapper.createRegister(Rd); - break; - - case 6: - opcode = Opcode.SBC; - operand2 = OperandWrapper.createRegister(finalRn); - finalRn = Rd; - break; - - case 7: - opcode = Opcode.MOV; - operand2 = OperandWrapper.createRegisterShiftRegister(Rd, ShiftType.ROR, finalRn); - break; - - case 8: - opcode = Opcode.TST; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - case 9: - opcode = Opcode.RSB; - operand2 = OperandWrapper.createImmediate(0); - break; - - case 10: - opcode = Opcode.CMP; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - case 11: - opcode = Opcode.CMN; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - case 12: - opcode = Opcode.ORR; - operand2 = OperandWrapper.createRegister(Rd); - break; - - case 13: - throw new RuntimeException("This is actually a multiply instruction."); - - case 14: - opcode = Opcode.BIC; - operand2 = OperandWrapper.createRegister(finalRn); - finalRn = Rd; - break; - - case 15: - opcode = Opcode.MVN; - operand2 = OperandWrapper.createRegister(finalRn); - break; - - default: - throw new RuntimeException("Only values 0-15 can be represented within 4 bits."); + Rn = finalRn; } - - Rn = finalRn; } } } @@ -692,6 +766,67 @@ /** @see #getRd() */ protected final byte Rd; + + public SingleDataTransfer(short instr) { + + writeBack = false; + preIndexing = true; + forceUserMode = false; + positiveOffset = true; + + if (Utils.getBits(instr, 11, 15) == 0x9 || + Utils.getBits(instr, 12, 15) == 0x9) { + //load from literal pool or stack load/store + Rd = (byte) Utils.getBits(instr, 8, 10); + offset = OperandWrapper.createImmediate(instr & 0xFF); + isLoad = Utils.getBit(instr, 11); + signExtend = false; + size = TransferSize.Word; + Rn = (byte)(Utils.getBit(instr, 15) ? ARM_Registers.SP : ARM_Registers.PC); + } + else { + //load/store register offset, load/store byte/word immediate offset or load/store halfword immediate offset + Rd = (byte)Utils.getBits(instr, 0, 2); + Rn = (byte)Utils.getBits(instr, 3, 5); + + if (Utils.getBits(instr, 13, 15) == 0x5) { + //load store register offset + offset = OperandWrapper.createRegister((byte)Utils.getBits(instr, 6, 8)); + + if (Utils.getBit(instr, 9)) { + //load store byte/halfword + signExtend = Utils.getBit(instr, 10); + isLoad = signExtend || Utils.getBit(instr, 11); + + if (!signExtend) + size = TransferSize.HalfWord; + else + size = Utils.getBit(instr, 11) ? TransferSize.HalfWord : TransferSize.Byte; + } + else { + //load store byte/word + size = Utils.getBit(instr, 10) ? TransferSize.Byte : TransferSize.Word; + isLoad = Utils.getBit(instr, 11); + signExtend = false; + } + } + else { + //load/store word/halfword/byte with immediate offset + offset = OperandWrapper.createImmediate(Utils.getBits(instr, 6, 10)); + isLoad = Utils.getBit(instr, 11); + signExtend = false; + + if (Utils.getBit(instr, 13)) { + //transfer word/byte + size = Utils.getBit(instr, 12) ? TransferSize.Byte : TransferSize.Word; + } + else { + //transfer Half-word + size = TransferSize.HalfWord; + } + } + } + } public SingleDataTransfer(int instr) { super(instr); @@ -934,6 +1069,38 @@ /** Contains a set bit at position N if rN should be transferred using this instruction.*/ protected final int registerList; + + public BlockDataTransfer(short instr) { + forceUser = false; + writeBack = true; + isLoad = Utils.getBit(instr, 11); + incrementBase = postIndexing = isLoad; + + int regList = instr & 0xFF; + + if (Utils.getBit(instr, 14)) { + //PUSH / POP registers + baseRegister = ARM_Registers.SP; + + if (Utils.getBit(instr, 8)) { + //this is a procedure entry/return + if (isLoad) { + //procedure return, load pc + regList |= (1 << ARM_Registers.PC); + } + else { + //procedure entry, push lr + regList |= (1 << ARM_Registers.LR); + } + } + } + else { + //LDMIA/STMIA + baseRegister = (byte)Utils.getBits(instr, 8, 10); + } + + registerList = regList; + } public BlockDataTransfer(int instr) { super(instr); @@ -1026,6 +1193,23 @@ /** @see #getOffset() */ protected final int offset; + + public Branch(short instr) { + super (Utils.getBit(instr, 13) ? Condition.values()[Utils.getBits(instr, 8, 11)] : Condition.AL); + + if (Utils.getBit(instr, 13)) { + offset = instr & 0xFF; + link = false; + } + else { + offset = Utils.getBits(instr, 0, 10); + link = Utils.getBit(instr, 12); + + //only the second instruction of a long branch is actually a branch + if (DBT.VerifyAssertions && link) DBT._assert(Utils.getBit(instr, 11)); + } + + } public Branch(int instr) { super(instr); @@ -1057,6 +1241,19 @@ /** @see #link() */ protected final boolean link; + + public BranchExchange(short instr) { + + if (Utils.getBit(instr, 15)) { + link = true; + target = OperandWrapper.createRegisterOffset(ARM_Registers.LR, Utils.getBits(instr, 0, 10)); + } + else { + link = Utils.getBit(instr, 7); + int register = Utils.getBits(instr, 3, 6); + target = OperandWrapper.createRegister((byte)register); + } + } public BranchExchange(int instr) { super(Utils.getBit(instr, 27) ? 0xE0000000 : instr); @@ -1072,7 +1269,7 @@ if (Utils.getBit(instr, 24)) jumpTarget += 2; - target = OperandWrapper.createPcRelative(jumpTarget); + target = OperandWrapper.createRegisterOffset(ARM_Registers.PC, jumpTarget); } else { link = Utils.getBit(instr, 5); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-13 16:35:34 UTC (rev 131) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-14 17:19:16 UTC (rev 132) @@ -40,10 +40,18 @@ /** Decodes the instruction at the given address.*/ public Instruction decode(int pc) { - - int binaryInstruction = ps.memory.loadInstruction32(pc); - ARM_Instruction instruction = ARM_InstructionDecoder.decode(binaryInstruction, instructionFactory); + ARM_Instruction instruction; + + if ((pc & 1) != 0) { + short binaryInstruction = (short)ps.memory.loadInstruction16(pc & 0xFFFFFFFE); + instruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction, instructionFactory); + } + else { + int binaryInstruction = ps.memory.loadInstruction32(pc); + instruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction, instructionFactory); + } + if (instruction.getCondition() != Condition.AL) { return new ConditionalDecorator(instruction); } @@ -56,7 +64,6 @@ return instructionFactory.toString(); } - private abstract static class ResolvedOperand { protected int value; @@ -99,11 +106,11 @@ int reg = operand.getRegister(); //mind the arm pc offset - value = regs.get(reg); + if (reg == ARM_Registers.PC) + value = regs.readPC(); + else + value = regs.get(reg); - if (reg == 15) - value += 8; - return; case RegisterShiftedRegister: @@ -111,10 +118,15 @@ value = resolveShift(regs, operand); return; - case PcRelative: - value = regs.get(ARM_Registers.PC) + 8 + operand.getOffset(); - break; + case RegisterOffset: + if (operand.getRegister() == ARM_Registers.PC) + value = regs.readPC(); + else + value =regs.get(operand.getRegister()); + value += operand.getOffset(); + return; + default: throw new RuntimeException("Unexpected wrapped operand type: " + operand.getType()); @@ -128,11 +140,11 @@ DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); - int value = regs.get(operand.getRegister()); - //consider the "usual" ARM program counter offset if (operand.getRegister() == ARM_Registers.PC) - value += 8; + value = regs.readPC(); + else + value = regs.get(operand.getRegister()); byte shiftAmount; @@ -213,11 +225,11 @@ int reg = operand.getRegister(); //mind the arm pc offset - value = regs.get(reg); + if (reg == ARM_Registers.PC) + value = regs.readPC(); + else + value = regs.get(reg); - if (reg == 15) - value += 8; - return; case RegisterShiftedRegister: @@ -225,7 +237,7 @@ value = resolveShift(regs, operand); return; - case PcRelative: + case RegisterOffset: throw new RuntimeException("This operand type does not produce a shifter carry out."); default: @@ -241,11 +253,13 @@ DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); - int value = regs.get(operand.getRegister()); + int value; //consider the "usual" ARM program counter offset if (operand.getRegister() == ARM_Registers.PC) - value += 8; + value = regs.readPC(); + else + value = regs.get(operand.getRegister()); byte shiftAmount; @@ -454,7 +468,7 @@ protected int resolveOperand1() { if (i.Rn == ARM_Registers.PC) { - return regs.get(i.Rn) + 8; + return regs.readPC(); } return regs.get(i.Rn); @@ -585,7 +599,7 @@ /** Sets the condition field for logical operations. */ protected final void setFlagsForLogicalOperator(int result) { - + if (i.updateConditionCodes) { if (i.Rd != 15) { regs.setFlags(result < 0, result == 0, shifterCarryOut); @@ -1038,7 +1052,7 @@ //also transfer the program counter, if requested so if (transferPC) { nextAddress += 4; - ps.memory.store32(nextAddress, regs.get(15) + 8); + ps.memory.store32(nextAddress, regs.readPC()); } } @@ -1096,14 +1110,14 @@ public void execute() { //if we're supposed to link, then write the previous address into the link register if (i.link) { - regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + 4); + regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + (regs.getThumbMode() ? 2 : 4)); if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + i.getOffset() + 8, regs.get(ARM_Registers.PC) + 4); + ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), regs.get(ARM_Registers.PC) + 4); } else { if (DBT_Options.profileDuringInterpretation) - ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + i.getOffset() + 8, BranchType.DIRECT_BRANCH); + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.readPC() + i.getOffset(), BranchType.DIRECT_BRANCH); } } @@ -1128,8 +1142,8 @@ public void execute() { //remember the previous address - int previousAddress = regs.get(ARM_Registers.PC) + 8; + //are we supposed to jump to thumb (thumb=true) or ARM32 (thumb=false)? boolean thumb; @@ -1137,7 +1151,14 @@ int targetAddress; switch (i.target.getType()) { - case PcRelative: + case RegisterOffset: + int previousAddress; + + if (i.target.getRegister() == ARM_Registers.PC) + previousAddress = regs.readPC(); + else + previousAddress = regs.get(i.target.getRegister()); + targetAddress = previousAddress + i.target.getOffset(); thumb = true; break; @@ -1155,7 +1176,7 @@ //if we're supposed to link, then write the previous address into the link register if (i.link) { - regs.set(ARM_Registers.LR, previousAddress - 4); + regs.set(ARM_Registers.LR, regs.readPC() - (regs.getThumbMode() ? 2 : 4)); ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.CALL); } else { @@ -1173,7 +1194,7 @@ public int getSuccessor(int pc) { //if we're jumping relative to the PC, then we can predict the next instruction - if (i.target.getType() == OperandWrapper.Type.PcRelative) { + if (i.target.getType() == OperandWrapper.Type.RegisterOffset) { return pc + i.target.getOffset(); } else { //otherwise we can't predict it @@ -1421,11 +1442,13 @@ private int resolveAddress() { //acquire the base address - int base = regs.get(i.Rn); + int base; //take ARM's PC offset into account - if (i.Rn == 15) - base += 8; + if (i.Rn == ARM_Registers.PC) + base = regs.readPC(); + else + base = regs.get(i.Rn); //if we are not pre-indexing, then just use the base register for the memory access if (!i.preIndexing) @@ -1688,78 +1711,103 @@ } public ARM_Instruction createBlockDataTransfer(short instr) { - // TODO Auto-generated method stub - return null; + return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr)); } public ARM_Instruction createBranch(short instr) { - // TODO Auto-generated method stub - return null; + return new Branch(new ARM_Instructions.Branch(instr)); } public ARM_Instruction createBranchExchange(short instr) { - // TODO Auto-generated method stub - return null; + return new BranchExchange(new ARM_Instructions.BranchExchange(instr)); } public ARM_Instruction createCoprocessorDataProcessing(short instr) { - // TODO Auto-generated method stub - return null; + throw new RuntimeException("Instruction type not supported by thumb."); } public ARM_Instruction createCoprocess... [truncated message content] |
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] |
From: <cap...@us...> - 2007-06-11 16:00:26
|
Revision: 130 http://svn.sourceforge.net/pearcolator/?rev=130&view=rev Author: captain5050 Date: 2007-06-11 09:00:28 -0700 (Mon, 11 Jun 2007) Log Message: ----------- Fixes to get us building against the Jikes RVM SVN head again Modified Paths: -------------- ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java rvmroot.patch src/org/binarytranslator/vmInterface/DynamicCodeRunner.java Modified: ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java =================================================================== --- ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java 2007-06-11 15:48:25 UTC (rev 129) +++ ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java 2007-06-11 16:00:28 UTC (rev 130) @@ -1,10 +1,14 @@ /* - * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). - * The Jikes RVM project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php + * This file is part of the Jikes RVM project (http://jikesrvm.org). * - * (C) Copyright IBM Corp. 2001 + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.ia32; @@ -15,7 +19,6 @@ import org.jikesrvm.compilers.opt.OPT_DefUse; import org.jikesrvm.compilers.opt.OPT_OptimizingCompilerException; import org.jikesrvm.compilers.opt.ir.Binary; -import org.jikesrvm.compilers.opt.ir.BinaryAcc; import org.jikesrvm.compilers.opt.ir.CacheOp; import org.jikesrvm.compilers.opt.ir.Call; import org.jikesrvm.compilers.opt.ir.CondMove; @@ -26,11 +29,13 @@ import org.jikesrvm.compilers.opt.ir.MIR_Call; import org.jikesrvm.compilers.opt.ir.MIR_Compare; import org.jikesrvm.compilers.opt.ir.MIR_CompareExchange; +import org.jikesrvm.compilers.opt.ir.MIR_CompareExchange8B; import org.jikesrvm.compilers.opt.ir.MIR_CondBranch; import org.jikesrvm.compilers.opt.ir.MIR_CondMove; import org.jikesrvm.compilers.opt.ir.MIR_ConvertDW2QW; import org.jikesrvm.compilers.opt.ir.MIR_Divide; import org.jikesrvm.compilers.opt.ir.MIR_DoubleShift; +import org.jikesrvm.compilers.opt.ir.MIR_Lea; import org.jikesrvm.compilers.opt.ir.MIR_LowTableSwitch; import org.jikesrvm.compilers.opt.ir.MIR_Move; import org.jikesrvm.compilers.opt.ir.MIR_Multiply; @@ -63,6 +68,9 @@ import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_CMPL; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_CMPL; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GUARD_MOVE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SHL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SHR; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_USHR; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_ADC; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_ADD; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_AND; @@ -92,8 +100,12 @@ import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_IDIV; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_IMUL2; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_JCC; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_LEA; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_LOCK_CMPXCHG; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_LOCK_CMPXCHG8B; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOV; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOVSD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOVSS; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOVSX__B; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOVZX__B; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MUL; @@ -116,7 +128,6 @@ import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_XOR; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IR_PROLOGUE; import static org.jikesrvm.compilers.opt.ir.OPT_Operators.MIR_LOWTABLESWITCH; - import org.jikesrvm.compilers.opt.ir.OPT_Register; import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperandEnumeration; @@ -166,6 +177,95 @@ } /** + * Create the MIR instruction given by operator from the Binary LIR operands + * @param operator the MIR operator + * @param s the instruction being replaced + * @param result the destination register/memory + * @param val1 the first operand + * @param val2 the second operand + */ + protected void EMIT_Commutative(OPT_Operator operator, OPT_Instruction s, OPT_Operand result, OPT_Operand val1, OPT_Operand val2) { + if(VM.VerifyAssertions) VM._assert(result.isRegister() || result.isMemory()); + // Swap operands to reduce chance of generating a move or to normalize + // constants into val2 + if (val2.similar(result) || val1.isConstant()) { + OPT_Operand temp = val1; + val1 = val2; + val2 = temp; + } + // Do we need to move prior to the operator - result = val1 + if (!result.similar(val1)) { + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copy(), val1))); + } + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + + /** + * Create the MIR instruction given by operator from the Binary LIR operands + * @param operator the MIR operator + * @param s the instruction being replaced + * @param result the destination register/memory + * @param val1 the first operand + * @param val2 the second operand + */ + protected void EMIT_NonCommutative(OPT_Operator operator, OPT_Instruction s, OPT_Operand result, OPT_Operand val1, OPT_Operand val2) { + if(VM.VerifyAssertions) VM._assert(result.isRegister() || result.isMemory()); + if (result.similar(val1)) { + // Straight forward case where instruction is already in accumulate form + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + else if (!result.similar(val2)) { + // Move first operand to result and perform operator on result, if + // possible redundant moves should be remove by register allocator + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copy(), val1))); + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + else { + // Potential to clobber second operand during move to result. Use a + // temporary register to perform the operation and rely on register + // allocator to remove redundant moves + OPT_RegisterOperand temp = regpool.makeTemp(result); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, temp, val1))); + EMIT(MIR_BinaryAcc.mutate(s, operator, temp.copyRO(), val2)); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result, temp.copyRO()))); + } + } + + /** + * Create the MIR instruction given by operator from the Binary LIR operands + * @param operator the MIR operator + * @param s the instruction being replaced + * @param result the destination register/memory + * @param value the first operand + */ + protected void EMIT_Unary(OPT_Operator operator, OPT_Instruction s, OPT_Operand result, OPT_Operand value) { + if(VM.VerifyAssertions) VM._assert(result.isRegister() || result.isMemory()); + // Do we need to move prior to the operator - result = val1 + if (!result.similar(value)) { + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copy(), value))); + } + EMIT(MIR_UnaryAcc.mutate(s, operator, result)); + } + + /** + * Convert the given comparison with a boolean (int) value into a condition + * suitable for the carry flag + * @param x the value 1 (true) or 0 (false) + * @param cond either equal or not equal + * @return lower or higher equal + */ + protected static OPT_ConditionOperand BIT_TEST(int x, OPT_ConditionOperand cond) { + if (VM.VerifyAssertions) VM._assert((x==0)||(x==1)); + if (VM.VerifyAssertions) VM._assert(EQ_NE(cond)); + if ((x == 1 && cond.isEQUAL())|| + (x == 0 && cond.isNOT_EQUAL())) { + return OPT_ConditionOperand.LOWER(); + } else { + return OPT_ConditionOperand.HIGHER_EQUAL(); + } + } + + /** * Follow a chain of Move operations filtering back to a def * * @param use the place to start from @@ -351,8 +451,7 @@ return IA32_FLDL2T; } } - throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", - "unexpected 387 constant " + val); + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", "unexpected 387 constant " + val); } protected final OPT_IA32ConditionOperand COND(OPT_ConditionOperand op) { @@ -403,12 +502,15 @@ protected final OPT_Operand myFP1() { return new OPT_BURSManagedFPROperand(1); } + + protected final OPT_Register getST0() { + return getIR().regpool.getPhysicalRegisterSet().getST0(); + } /** * Move op into a register operand if it isn't one already. */ - private OPT_Operand asReg(OPT_Instruction s, OPT_Operator movop, - OPT_Operand op) { + private OPT_Operand asReg(OPT_Instruction s, OPT_Operator movop, OPT_Operand op) { if (op.isRegister()) { return op; } @@ -450,16 +552,12 @@ OPT_RegisterOperand hval = (OPT_RegisterOperand) op; OPT_RegisterOperand lval = new OPT_RegisterOperand(regpool .getSecondReg(hval.register), VM_TypeReference.Int); - EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, - offset + 4, DW), hval)); - EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset, - DW), lval)); + EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset + 4, DW), hval)); + EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset, DW), lval)); } else { OPT_LongConstantOperand val = LC(op); - EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, - offset + 4, DW), IC(val.upper32()))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset, - DW), IC(val.lower32()))); + EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset + 4, DW), IC(val.upper32()))); + EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset, DW), IC(val.lower32()))); } } @@ -472,8 +570,7 @@ private OPT_MemoryOperand loadFromJTOC(Offset offset) { OPT_LocationOperand loc = new OPT_LocationOperand(offset); OPT_Operand guard = TG(); - return OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus(offset), (byte) 4, - loc, guard); + return OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus(offset), (byte) 4, loc, guard); } /* @@ -513,18 +610,25 @@ * @param s the instruction to expand * @param result the result operand * @param value the second operand + * @param signExtend should the value be sign or zero extended? */ protected final void INT_2LONG(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { +OPT_Operand value, boolean signExtend) { OPT_Register hr = result.register; OPT_Register lr = regpool.getSecondReg(hr); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lr, - VM_TypeReference.Int), value)); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(hr, - VM_TypeReference.Int), - new OPT_RegisterOperand(lr, VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_SAR, new OPT_RegisterOperand(hr, - VM_TypeReference.Int), IC(31))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lr, VM_TypeReference.Int), value))); + if (signExtend) { + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(hr, VM_TypeReference.Int), + new OPT_RegisterOperand(lr, VM_TypeReference.Int)))); + EMIT(MIR_BinaryAcc.mutate(s,IA32_SAR, + new OPT_RegisterOperand(hr, VM_TypeReference.Int), + IC(31))); + } else { + EMIT(MIR_Move.mutate(s, IA32_MOV, + new OPT_RegisterOperand(hr, VM_TypeReference.Int), + IC(0))); + } } /** @@ -537,15 +641,14 @@ * @param result the result operand * @param value the second operand */ - protected final void FPR_2INT(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { + protected final void FPR_2INT(OPT_Instruction s, OPT_RegisterOperand result, OPT_Operand value) { OPT_MemoryOperand M; // Step 1: Get value to be converted into myFP0 // and in 'strict' IEEE mode. if (value instanceof OPT_MemoryOperand) { // value is in memory, all we have to do is load it - EMIT(MIR_Move.create(IA32_FLD, myFP0(), value)); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), value))); } else { // sigh. value is an FP register. Unfortunately, // SPECjbb requires some 'strict' FP semantics. Naturally, we don't @@ -558,16 +661,16 @@ if (VM.VerifyAssertions) { VM._assert(value.similar(myFP0())); } - EMIT(MIR_Move.create(IA32_FSTP, MO_CONV(DW), value)); - EMIT(MIR_Move.create(IA32_FLD, myFP0(), MO_CONV(DW))); + EMIT(CPOS(s, MIR_Move.create(IA32_FSTP, MO_CONV(DW), value))); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), MO_CONV(DW)))); } else { - EMIT(MIR_Move.create(IA32_FMOV, MO_CONV(DW), value)); - EMIT(MIR_Move.create(IA32_FLD, myFP0(), MO_CONV(DW))); + EMIT(CPOS(s, MIR_Move.create(IA32_FMOV, MO_CONV(DW), value))); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), MO_CONV(DW)))); } } // FP Stack: myFP0 = value - EMIT(MIR_Move.create(IA32_FIST, MO_CONV(DW), myFP0())); + EMIT(CPOS(s, MIR_Move.create(IA32_FIST, MO_CONV(DW), myFP0()))); // MO_CONV now holds myFP0 converted to an integer (round-toward nearest) // FP Stack: myFP0 == value @@ -576,112 +679,93 @@ OPT_Register one = regpool.getInteger(); OPT_Register isPositive = regpool.getInteger(); OPT_Register isNegative = regpool.getInteger(); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(one, - VM_TypeReference.Int), IC(1))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(isPositive, - VM_TypeReference.Int), IC(0))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(isNegative, - VM_TypeReference.Int), IC(0))); - EMIT(MIR_Nullary.create(IA32_FLDZ, myFP0())); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(one, VM_TypeReference.Int), IC(1)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(isPositive, VM_TypeReference.Int), IC(0)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(isNegative, VM_TypeReference.Int), IC(0)))); + EMIT(CPOS(s, MIR_Nullary.create(IA32_FLDZ, myFP0()))); // FP Stack: myFP0 = 0.0; myFP1 = value - EMIT(MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())); + EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1()))); // FP Stack: myFP0 = value - EMIT(MIR_CondMove.create(IA32_CMOV, - new OPT_RegisterOperand(isPositive, - VM_TypeReference.Int), - new OPT_RegisterOperand(one, - VM_TypeReference.Int), - OPT_IA32ConditionOperand.LLT())); - EMIT(MIR_CondMove.create(IA32_CMOV, - new OPT_RegisterOperand(isNegative, - VM_TypeReference.Int), - new OPT_RegisterOperand(one, - VM_TypeReference.Int), - OPT_IA32ConditionOperand.LGT())); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + new OPT_RegisterOperand(isPositive, VM_TypeReference.Int), + new OPT_RegisterOperand(one, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LLT()))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + new OPT_RegisterOperand(isNegative, VM_TypeReference.Int), + new OPT_RegisterOperand(one, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LGT()))); - EMIT(MIR_Move.create(IA32_FILD, myFP0(), MO_CONV(DW))); + EMIT(CPOS(s, MIR_Move.create(IA32_FILD, myFP0(), MO_CONV(DW)))); // FP Stack: myFP0 = round(value), myFP1 = value // addee = 1 iff round(x) < x // subtractee = 1 iff round(x) > x OPT_Register addee = regpool.getInteger(); OPT_Register subtractee = regpool.getInteger(); - EMIT(MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())); + EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1()))); // FP Stack: myFP0 = value - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(addee, - VM_TypeReference.Int), IC(0))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(subtractee, - VM_TypeReference.Int), IC(0))); - EMIT(MIR_CondMove.create(IA32_CMOV, - new OPT_RegisterOperand(addee, - VM_TypeReference.Int), - new OPT_RegisterOperand(one, - VM_TypeReference.Int), - OPT_IA32ConditionOperand.LLT())); - EMIT(MIR_CondMove.create(IA32_CMOV, - new OPT_RegisterOperand(subtractee, - VM_TypeReference.Int), - new OPT_RegisterOperand(one, - VM_TypeReference.Int), - OPT_IA32ConditionOperand.LGT())); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(addee, VM_TypeReference.Int), IC(0)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(subtractee, VM_TypeReference.Int), IC(0)))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + new OPT_RegisterOperand(addee, VM_TypeReference.Int), + new OPT_RegisterOperand(one, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LLT()))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + new OPT_RegisterOperand(subtractee, VM_TypeReference.Int), + new OPT_RegisterOperand(one, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LGT()))); // Now a little tricky part. // We will add 1 iff isNegative and x > round(x) // We will subtract 1 iff isPositive and x < round(x) - EMIT(MIR_BinaryAcc.create(IA32_AND, - new OPT_RegisterOperand(addee, - VM_TypeReference.Int), - new OPT_RegisterOperand(isNegative, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_AND, - new OPT_RegisterOperand(subtractee, - VM_TypeReference.Int), - new OPT_RegisterOperand(isPositive, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, result.copy(), MO_CONV(DW))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, result.copy(), new OPT_RegisterOperand( - addee, VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_SUB, result.copy(), new OPT_RegisterOperand( - subtractee, VM_TypeReference.Int))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_AND, + new OPT_RegisterOperand(addee, VM_TypeReference.Int), + new OPT_RegisterOperand(isNegative, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_AND, + new OPT_RegisterOperand(subtractee, VM_TypeReference.Int), + new OPT_RegisterOperand(isPositive, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copy(), MO_CONV(DW)))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_ADD, result.copy(), new OPT_RegisterOperand(addee, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, result.copy(), new OPT_RegisterOperand(subtractee, VM_TypeReference.Int)))); // Compare myFP0 with (double)Integer.MAX_VALUE - M = OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus( - VM_Entrypoints.maxintField.getOffset()), QW, null, null); - EMIT(MIR_Move.create(IA32_FLD, myFP0(), M)); + M = OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus(VM_Entrypoints.maxintField.getOffset()), QW, null, null); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), M))); // FP Stack: myFP0 = (double)Integer.MAX_VALUE; myFP1 = value - EMIT(MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())); + EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1()))); // FP Stack: myFP0 = value // If MAX_VALUE < value, then result := MAX_INT OPT_Register maxInt = regpool.getInteger(); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(maxInt, - VM_TypeReference.Int), IC(Integer.MAX_VALUE))); - EMIT(MIR_CondMove.create(IA32_CMOV, result.copy(), new OPT_RegisterOperand( - maxInt, VM_TypeReference.Int), OPT_IA32ConditionOperand.LLT())); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(maxInt, VM_TypeReference.Int), IC(Integer.MAX_VALUE)))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + result.copy(), + new OPT_RegisterOperand(maxInt, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LLT()))); // Compare myFP0 with (double)Integer.MIN_VALUE - M = OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus( - VM_Entrypoints.minintField.getOffset()), QW, null, null); - EMIT(MIR_Move.create(IA32_FLD, myFP0(), M)); + M = OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus(VM_Entrypoints.minintField.getOffset()), QW, null, null); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), M))); // FP Stack: myFP0 = (double)Integer.MIN_VALUE; myFP1 = value - EMIT(MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())); + EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1()))); // FP Stack: myFP0 = value // If MIN_VALUE > value, then result := MIN_INT OPT_Register minInt = regpool.getInteger(); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(minInt, - VM_TypeReference.Int), IC(Integer.MIN_VALUE))); - EMIT(MIR_CondMove.create(IA32_CMOV, result.copy(), new OPT_RegisterOperand( - minInt, VM_TypeReference.Int), OPT_IA32ConditionOperand.LGT())); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(minInt, VM_TypeReference.Int), IC(Integer.MIN_VALUE)))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + result.copy(), + new OPT_RegisterOperand(minInt, VM_TypeReference.Int), + OPT_IA32ConditionOperand.LGT()))); // Set condition flags: set PE iff myFP0 is a NaN - EMIT(MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP0())); + EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP0()))); // FP Stack: back to original level (all BURS managed slots freed) // If FP0 was classified as a NaN, then result := 0 OPT_Register zero = regpool.getInteger(); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(zero, - VM_TypeReference.Int), IC(0))); - EMIT(MIR_CondMove.create(IA32_CMOV, result.copy(), new OPT_RegisterOperand( - zero, VM_TypeReference.Int), OPT_IA32ConditionOperand.PE())); - + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(zero, VM_TypeReference.Int), IC(0)))); + EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, + result.copy(), + new OPT_RegisterOperand(zero, VM_TypeReference.Int), + OPT_IA32ConditionOperand.PE()))); } /** @@ -690,15 +774,13 @@ protected final void FPR2GPR_64(OPT_Instruction s) { int offset = -burs.ir.stackManager.allocateSpaceForConversion(); OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, QW); - OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, - offset + 4, DW); - OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, - DW); - EMIT(MIR_Move.create(IA32_FMOV, sl, Unary.getVal(s))); + OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, offset + 4, DW); + OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, DW); + EMIT(CPOS(s, MIR_Move.create(IA32_FMOV, sl, Unary.getVal(s)))); OPT_RegisterOperand i1 = Unary.getResult(s); OPT_RegisterOperand i2 = new OPT_RegisterOperand(regpool .getSecondReg(i1.register), VM_TypeReference.Int); - EMIT(MIR_Move.create(IA32_MOV, i1, sl1)); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, i1, sl1))); EMIT(MIR_Move.mutate(s, IA32_MOV, i2, sl2)); } @@ -708,28 +790,216 @@ protected final void GPR2FPR_64(OPT_Instruction s) { int offset = -burs.ir.stackManager.allocateSpaceForConversion(); OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, QW); - OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, - offset + 4, DW); - OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, - DW); + OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, offset + 4, DW); + OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, DW); OPT_Operand i1, i2; OPT_Operand val = Unary.getVal(s); if (val instanceof OPT_RegisterOperand) { OPT_RegisterOperand rval = (OPT_RegisterOperand) val; i1 = val; - i2 = new OPT_RegisterOperand(regpool.getSecondReg(rval.register), - VM_TypeReference.Int); + i2 = new OPT_RegisterOperand(regpool.getSecondReg(rval.register), VM_TypeReference.Int); } else { OPT_LongConstantOperand rhs = (OPT_LongConstantOperand) val; i1 = IC(rhs.upper32()); i2 = IC(rhs.lower32()); } - EMIT(MIR_Move.create(IA32_MOV, sl1, i1)); - EMIT(MIR_Move.create(IA32_MOV, sl2, i2)); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl1, i1))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl2, i2))); EMIT(MIR_Move.mutate(s, IA32_FMOV, Unary.getResult(s), sl)); } + + /** + * Returns the appropriate move operator based on the type of operand. + */ + protected final OPT_Operator SSE2_MOVE(OPT_Operand o) { + return o.isFloat() ? IA32_MOVSS : IA32_MOVSD; + } + + /** + * Returns the size based on the type of operand. + */ + protected final byte SSE2_SIZE(OPT_Operand o) { + return o.isFloat() ? DW : QW; + } + + /** + * Performs a long -> double/float conversion using x87 and marshalls back to XMMs. + */ + protected final void SSE2_X87_FROMLONG(OPT_Instruction s) { + OPT_Operand result = Unary.getResult(s); + STORE_LONG_FOR_CONV(Unary.getVal(s)); + // conversion space allocated, contains the long to load. + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, SSE2_SIZE(result)); + OPT_RegisterOperand st0 = new OPT_RegisterOperand(getST0(), result.getType()); + EMIT(CPOS(s, MIR_Move.create(IA32_FILD, st0, sl))); + EMIT(CPOS(s, MIR_Move.create(IA32_FSTP, sl.copy(), st0.copyD2U()))); + EMIT(CPOS(s, MIR_Move.mutate(s, SSE2_MOVE(result), result, sl.copy()))); + } + + /** + * Performs a long -> double/float conversion using x87 and marshalls between to XMMs. + */ + protected final void SSE2_X87_REM(OPT_Instruction s) { + OPT_Operand result = Move.getClearResult(s); + OPT_RegisterOperand st0 = new OPT_RegisterOperand(getST0(), result.getType()); + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, SSE2_SIZE(result)); + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), sl, Binary.getVal2(s)))); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, st0, sl.copy()))); + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), sl.copy(), Binary.getVal1(s)))); + EMIT(CPOS(s, MIR_Move.create(IA32_FLD, st0.copy(), sl.copy()))); + EMIT(CPOS(s, MIR_Nullary.create(IA32_FPREM, st0.copy()))); + EMIT(CPOS(s, MIR_Move.create(IA32_FSTP, sl.copy(), st0.copy()))); + EMIT(MIR_Move.mutate(s, SSE2_MOVE(result), result, sl.copy())); + } + + /** + * Emit code to move 64 bits from SSE2 FPRs to GPRs + */ + protected final void SSE2_FPR2GPR_64(OPT_Instruction s) { + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, QW); + OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, offset + 4, DW); + OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, DW); + EMIT(CPOS(s, MIR_Move.create(IA32_MOVSD, sl, Unary.getVal(s)))); + OPT_RegisterOperand i1 = Unary.getResult(s); + OPT_RegisterOperand i2 = new OPT_RegisterOperand(regpool + .getSecondReg(i1.register), VM_TypeReference.Int); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, i1, sl1))); + EMIT(MIR_Move.mutate(s, IA32_MOV, i2, sl2)); + } /** + * Emit code to move 64 bits from GPRs to SSE2 FPRs + */ + protected final void SSE2_GPR2FPR_64(OPT_Instruction s) { + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, QW); + OPT_StackLocationOperand sl1 = new OPT_StackLocationOperand(true, offset + 4, DW); + OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, DW); + OPT_Operand i1, i2; + OPT_Operand val = Unary.getVal(s); + if (val instanceof OPT_RegisterOperand) { + OPT_RegisterOperand rval = (OPT_RegisterOperand) val; + i1 = val; + i2 = new OPT_RegisterOperand(regpool.getSecondReg(rval.register), VM_TypeReference.Int); + } else { + OPT_LongConstantOperand rhs = (OPT_LongConstantOperand) val; + i1 = IC(rhs.upper32()); + i2 = IC(rhs.lower32()); + } + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl1, i1))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl2, i2))); + EMIT(MIR_Move.mutate(s, IA32_MOVSD, Unary.getResult(s), sl)); + } + + /** + * Emit code to move 32 bits from FPRs to GPRs + */ + protected final void SSE2_FPR2GPR_32(OPT_Instruction s) { + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, DW); + EMIT(CPOS(s, MIR_Move.create(IA32_MOVSS, sl, Unary.getVal(s)))); + EMIT(MIR_Move.mutate(s, IA32_MOV, Unary.getResult(s), sl.copy())); + } + + /** + * Emit code to move 32 bits from GPRs to FPRs + */ + protected final void SSE2_GPR2FPR_32(OPT_Instruction s) { + int offset = -burs.ir.stackManager.allocateSpaceForConversion(); + OPT_StackLocationOperand sl = new OPT_StackLocationOperand(true, offset, DW); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl, Unary.getVal(s)))); + EMIT(MIR_Move.mutate(s, IA32_MOVSS, Unary.getResult(s), sl.copy())); + } + + /** + * BURS expansion of a commutative SSE2 operation. + */ + protected void SSE2_COP(OPT_Operator operator, OPT_Instruction s, OPT_Operand result, OPT_Operand val1, OPT_Operand val2) { + if(VM.VerifyAssertions) VM._assert(result.isRegister()); + // Swap operands to reduce chance of generating a move or to normalize + // constants into val2 + if (val2.similar(result)) { + OPT_Operand temp = val1; + val1 = val2; + val2 = temp; + } + // Do we need to move prior to the operator - result = val1 + if (!result.similar(val1)) { + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), result.copy(), val1))); + } + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + + /** + * BURS expansion of a non commutative SSE2 operation. + */ + protected void SSE2_NCOP(OPT_Operator operator, OPT_Instruction s, OPT_Operand result, OPT_Operand val1, OPT_Operand val2) { + if(VM.VerifyAssertions) VM._assert(result.isRegister()); + if (result.similar(val1)) { + // Straight forward case where instruction is already in accumulate form + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + else if (!result.similar(val2)) { + // Move first operand to result and perform operator on result, if + // possible redundant moves should be remove by register allocator + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), result.copy(), val1))); + EMIT(MIR_BinaryAcc.mutate(s, operator, result, val2)); + } + else { + // Potential to clobber second operand during move to result. Use a + // temporary register to perform the operation and rely on register + // allocator to remove redundant moves + OPT_RegisterOperand temp = regpool.makeTemp(result); + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), temp, val1))); + EMIT(MIR_BinaryAcc.mutate(s, operator, temp.copyRO(), val2)); + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), result, temp.copyRO()))); + } + } + + /** + * Expansion of SSE2 negation ops + */ + protected final void SSE2_NEG(OPT_Operator xorOp, OPT_Operator subOp, OPT_Instruction s, OPT_Operand result, OPT_Operand value) { + if(VM.VerifyAssertions) VM._assert(result.isRegister()); + if (!result.similar(value)) { + EMIT(CPOS(s, MIR_BinaryAcc.create(xorOp, result.copy(), result.copy()))); + EMIT(MIR_BinaryAcc.mutate(s, subOp, result, value)); + } else { + OPT_RegisterOperand temp = regpool.makeTemp(value.getType()); + EMIT(CPOS(s, MIR_Move.create(xorOp, temp.copyRO(), temp))); + EMIT(MIR_BinaryAcc.mutate(s, subOp, temp.copyRO(), value)); + EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), result, temp.copyRO()))); + } + } + + /** + * Expansion of SSE2 conversions double <-> float + */ + protected final void SSE2_CONV(OPT_Operator op, OPT_Instruction s, OPT_Operand result, OPT_Operand value) { + if(VM.VerifyAssertions) VM._assert(result.isRegister()); + if(VM.VerifyAssertions) VM._assert(value.isRegister()); + EMIT(MIR_Unary.mutate(s, op, result, value)); + } + + /** + * Expansion of SSE2 comparison operations + */ + protected final void SSE2_IFCMP(OPT_Operator op, OPT_Instruction s, OPT_Operand val1, OPT_Operand val2) { + EMIT(CPOS(s, MIR_Compare.create(op, val1, val2))); + EMIT(s); // OPT_ComplexLIR2MIRExpansion will handle rest of the work. + } + + /** + * Expansion of SSE2 floating point constant loads + */ + protected final void SSE2_FPCONSTANT(OPT_Instruction s) { + EMIT(MIR_Move.mutate(s, SSE2_MOVE(Unary.getResult(s)), Binary.getResult(s), MO_MC(s))); + } + + /** * Expansion of ROUND_TO_ZERO. * * @param s the instruction to expand @@ -741,16 +1011,16 @@ OPT_Operand jtoc = OPT_MemoryOperand.BD(PR, VM_Entrypoints.jtocField .getOffset(), DW, null, null); OPT_RegisterOperand regOp = regpool.makeTempInt(); - EMIT(MIR_Move.create(IA32_MOV, regOp, jtoc)); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, regOp, jtoc))); // Store the FPU Control Word to a JTOC slot - OPT_MemoryOperand M = OPT_MemoryOperand.BD(regOp.copyRO(), - VM_Entrypoints.FPUControlWordField.getOffset(), W, null, null); - EMIT(MIR_UnaryNoRes.create(IA32_FNSTCW, M)); + OPT_MemoryOperand M = + OPT_MemoryOperand.BD(regOp.copyRO(), VM_Entrypoints.FPUControlWordField.getOffset(), W, null, null); + EMIT(CPOS(s, MIR_UnaryNoRes.create(IA32_FNSTCW, M))); // Set the bits in the status word that control round to zero. // Note that we use a 32-bit and, even though we only care about the // low-order 16 bits - EMIT(MIR_BinaryAcc.create(IA32_OR, M.copy(), IC(0x00000c00))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_OR, M.copy(), IC(0x00000c00)))); // Now store the result back into the FPU Control Word EMIT(MIR_Nullary.mutate(s, IA32_FLDCW, M.copy())); } @@ -764,196 +1034,315 @@ * @param val2 the second operand * @param isDiv true for div, false for rem */ - protected final void INT_DIVIDES(OPT_Instruction s, - OPT_RegisterOperand result, OPT_Operand val1, OPT_Operand val2, + protected final void INT_DIVIDES(OPT_Instruction s, OPT_RegisterOperand result, OPT_Operand val1, OPT_Operand val2, boolean isDiv) { - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), val1)); - EMIT(MIR_ConvertDW2QW.create(IA32_CDQ, - new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), - new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), VM_TypeReference.Int), val1))); + EMIT(CPOS(s, MIR_ConvertDW2QW.create(IA32_CDQ, + new OPT_RegisterOperand(getEDX(), VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), VM_TypeReference.Int)))); if (val2 instanceof OPT_IntConstantOperand) { OPT_RegisterOperand temp = regpool.makeTempInt(); - EMIT(MIR_Move.create(IA32_MOV, temp, val2)); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, temp, val2))); val2 = temp.copyRO(); } EMIT(MIR_Divide.mutate(s, IA32_IDIV, - new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), - new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), + new OPT_RegisterOperand(getEDX(), VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), VM_TypeReference.Int), val2, GuardedBinary.getGuard(s))); if (isDiv) { - EMIT(MIR_Move.create(IA32_MOV, result.copyD2D(), new OPT_RegisterOperand( - getEAX(), VM_TypeReference.Int))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copyD2D(), new OPT_RegisterOperand(getEAX(), VM_TypeReference.Int)))); } else { - EMIT(MIR_Move.create(IA32_MOV, result.copyD2D(), new OPT_RegisterOperand( - getEDX(), VM_TypeReference.Int))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copyD2D(), new OPT_RegisterOperand(getEDX(), VM_TypeReference.Int)))); } } /** - * Expansion of LONG_ADD_ACC + * Expansion of LONG_ADD * * @param s the instruction to expand - * @param result the result/first operand - * @param value the second operand + * @param result the result operand + * @param value1 the first operand + * @param value2 the second operand */ protected final void LONG_ADD(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { + OPT_Operand value1, OPT_Operand value2) { + // The value of value1 should be identical to result, to avoid moves, and a + // register in the case of addition with a constant + if ((value2.similar(result)) || value1.isLongConstant()) { + OPT_Operand temp = value1; + value1 = value2; + value2 = temp; + } OPT_Register lhsReg = result.register; OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); - if (value instanceof OPT_RegisterOperand) { - OPT_Register rhsReg = ((OPT_RegisterOperand) value).register; - OPT_Register lowrhsReg = regpool.getSecondReg(rhsReg); - EMIT(MIR_BinaryAcc.create(IA32_ADD, - new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), - new OPT_RegisterOperand(lowrhsReg, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.mutate(s, - IA32_ADC, - new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), - new OPT_RegisterOperand(rhsReg, - VM_TypeReference.Int))); - } else { - OPT_LongConstantOperand rhs = (OPT_LongConstantOperand) value; - int low = rhs.lower32(); - int high = rhs.upper32(); + if (value1.isRegister() && value2.isRegister()) { + OPT_Register rhsReg1 = ((OPT_RegisterOperand) value1).register; + OPT_Register lowrhsReg1 = regpool.getSecondReg(rhsReg1); + OPT_Register rhsReg2 = ((OPT_RegisterOperand) value2).register; + OPT_Register lowrhsReg2 = regpool.getSecondReg(rhsReg2); + // Do we need to move prior to the add - result = value1 + if (!value1.similar(result)) { + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg1, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg1, VM_TypeReference.Int)))); + } + // Perform add - result += value2 + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg2, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_ADC, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg2, VM_TypeReference.Int)))); + } else if (value1.isRegister()){ + OPT_Register rhsReg1 = ((OPT_RegisterOperand) value1).register; + OPT_Register lowrhsReg1 = regpool.getSecondReg(rhsReg1); + OPT_LongConstantOperand rhs2 = (OPT_LongConstantOperand) value2; + int low = rhs2.lower32(); + int high = rhs2.upper32(); + // Do we need to move prior to the add - result = value1 + if (!value1.similar(result)) { + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg1, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg1, VM_TypeReference.Int)))); + } + // Perform add - result += value2 if (low == 0) { - EMIT(MIR_BinaryAcc.mutate(s, IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_ADD, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + IC(high)))); } else { - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), IC(low))); - EMIT(MIR_BinaryAcc.mutate(s, IA32_ADC, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + IC(low)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_ADC, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + IC(high)))); } + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + value1 + "+" + value2); } } /** - * Expansion of LONG_SUB_ACC + * Expansion of LONG_SUB * * @param s the instruction to expand - * @param result the result/first operand - * @param value the second operand + * @param result the result operand + * @param value1 the first operand + * @param value2 the second operand */ - protected final void LONG_SUB(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { - OPT_Register lhsReg = result.register; - OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); - if (value instanceof OPT_RegisterOperand) { - OPT_Register rhsReg = ((OPT_RegisterOperand) value).register; - OPT_Register lowrhsReg = regpool.getSecondReg(rhsReg); - EMIT(MIR_BinaryAcc.create(IA32_SUB, - new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), - new OPT_RegisterOperand(lowrhsReg, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.mutate(s, - IA32_SBB, - new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), - new OPT_RegisterOperand(rhsReg, - VM_TypeReference.Int))); - } else { - OPT_LongConstantOperand rhs = (OPT_LongConstantOperand) value; - int low = rhs.lower32(); - int high = rhs.upper32(); - if (low == 0) { - EMIT(MIR_BinaryAcc.mutate(s, IA32_SUB, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + protected final void LONG_SUB(OPT_Instruction s, OPT_Operand result, + OPT_Operand val1, OPT_Operand val2) { + + if (result.similar(val1)) { + // Straight forward case where instruction is already in accumulate form + if (result.isRegister()) { + OPT_Register lhsReg = result.asRegister().register; + OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); + if (val2.isRegister()) { + OPT_Register rhsReg2 = val2.asRegister().register; + OPT_Register lowrhsReg2 = regpool.getSecondReg(rhsReg2); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg2, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg2, VM_TypeReference.Int)))); + } else if (val2.isLongConstant()) { + OPT_LongConstantOperand rhs2 = val2.asLongConstant(); + int low = rhs2.lower32(); + int high = rhs2.upper32(); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + IC(low)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + IC(high)))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } } else { - EMIT(MIR_BinaryAcc.create(IA32_SUB, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), IC(low))); - EMIT(MIR_BinaryAcc.mutate(s, IA32_SBB, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); } + } + else if (!result.similar(val2)) { + // Move first operand to result and perform operator on result, if + // possible redundant moves should be remove by register allocator + if (result.isRegister()) { + OPT_Register lhsReg = result.asRegister().register; + OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); + // Move val1 into result + if (val1.isRegister()) { + OPT_Register rhsReg1 = val1.asRegister().register; + OPT_Register lowrhsReg1 = regpool.getSecondReg(rhsReg1); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg1, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg1, VM_TypeReference.Int)))); + } else if (val1.isLongConstant()) { + OPT_LongConstantOperand rhs1 = val1.asLongConstant(); + int low = rhs1.lower32(); + int high = rhs1.upper32(); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + IC(low)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + IC(high)))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } + // Perform subtract + if (val2.isRegister()) { + OPT_Register rhsReg2 = val2.asRegister().register; + OPT_Register lowrhsReg2 = regpool.getSecondReg(rhsReg2); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(lowrhsReg2, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + new OPT_RegisterOperand(rhsReg2, VM_TypeReference.Int)))); + } else if (val2.isLongConstant()) { + OPT_LongConstantOperand rhs2 = val2.asLongConstant(); + int low = rhs2.lower32(); + int high = rhs2.upper32(); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + IC(low)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + IC(high)))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } } + else { + // Potential to clobber second operand during move to result. Use a + // temporary register to perform the operation and rely on register + // allocator to remove redundant moves + OPT_RegisterOperand temp1 = regpool.makeTempInt(); + OPT_RegisterOperand temp2 = regpool.makeTempInt(); + // Move val1 into temp + if (val1.isRegister()) { + OPT_Register rhsReg1 = val1.asRegister().register; + OPT_Register lowrhsReg1 = regpool.getSecondReg(rhsReg1); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + temp1, + new OPT_RegisterOperand(lowrhsReg1, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + temp2, + new OPT_RegisterOperand(rhsReg1, VM_TypeReference.Int)))); + } else if (val1.isLongConstant()) { + OPT_LongConstantOperand rhs1 = val1.asLongConstant(); + int low = rhs1.lower32(); + int high = rhs1.upper32(); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + temp1, + IC(low)))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + temp2, + IC(high)))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } + // Perform subtract + if (val2.isRegister()) { + OPT_Register rhsReg2 = val2.asRegister().register; + OPT_Register lowrhsReg2 = regpool.getSecondReg(rhsReg2); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + temp1.copyRO(), + new OPT_RegisterOperand(lowrhsReg2, VM_TypeReference.Int)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + temp2.copyRO(), + new OPT_RegisterOperand(rhsReg2, VM_TypeReference.Int)))); + } else if (val2.isLongConstant()) { + OPT_LongConstantOperand rhs2 = val2.asLongConstant(); + int low = rhs2.lower32(); + int high = rhs2.upper32(); + EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, + temp1.copyRO(), + IC(low)))); + EMIT(CPOS(s, MIR_BinaryAcc.mutate(s, IA32_SBB, + temp2.copyRO(), + IC(high)))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } + // Move result back + if (result.isRegister()) { + OPT_Register lhsReg = result.asRegister().register; + OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, VM_TypeReference.Int), + temp1.copyRO()))); + EMIT(CPOS(s, MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, VM_TypeReference.Int), + temp2.copyRO()))); + } else { + throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", + "unexpected parameters: " + result + "=" + val1 + "-" + val2); + } + } } /** - * Expansion of RDTSC (called GET_TIME_BASE for consistency with PPC) + * Expansion of LONG_MUL * * @param s the instruction to expand - * @param result the result/first operand + * @param result the result operand + * @param value1 the first operand + * @param value2 the second operand */ - protected final void GET_TIME_BASE(OPT_Instruction s, - OPT_RegisterOperand result) { - OPT_Register highReg = result.register; - OPT_Register lowReg = regpool.getSecondReg(highReg); - EMIT(MIR_RDTSC.create(IA32_RDTSC, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(highReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); - } - - /** - * Expansion of LONG_MUL_ACC - * - * @param s the instruction to expand - * @param result the result/first operand - * @param value the second operand - */ protected final void LONG_MUL(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { - // In general, (a,b) * (c,d) = (l(a imul d)+l(b imul c)+u(b mul d), l(b mul - // d)) - OPT_Register lhsReg = result.register; - OPT_Register lowlhsReg = regpool.getSecondReg(lhsReg); - if (value instanceof OPT_RegisterOperand) { - OPT_Register rhsReg = ((OPT_RegisterOperand) value).register; - OPT_Register lowrhsReg = regpool.getSecondReg(rhsReg); - OPT_Register tmp = regpool.getInteger(); - EMIT(MIR_BinaryAcc.create(IA32_IMUL2, - new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), - new OPT_RegisterOperand(lowrhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(tmp, - VM_TypeReference.Int), new OPT_RegisterOperand(rhsReg, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_IMUL2, - new OPT_RegisterOperand(tmp, - VM_TypeReference.Int), - new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(tmp, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Multiply.create(IA32_MUL, - new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), - new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), - new OPT_RegisterOperand(lowrhsReg, - ... [truncated message content] |
From: <mic...@us...> - 2007-06-11 15:48:23
|
Revision: 129 http://svn.sourceforge.net/pearcolator/?rev=129&view=rev Author: michael_baer Date: 2007-06-11 08:48:25 -0700 (Mon, 11 Jun 2007) Log Message: ----------- Removed superfluous imports Modified Paths: -------------- src/org/binarytranslator/Main.java Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-06-08 14:03:26 UTC (rev 128) +++ src/org/binarytranslator/Main.java 2007-06-11 15:48:25 UTC (rev 129) @@ -9,17 +9,11 @@ package org.binarytranslator; import java.io.File; -import java.io.IOException; import org.binarytranslator.generic.execution.DynamicTranslationController; import org.binarytranslator.generic.execution.ExecutionController; import org.binarytranslator.generic.execution.GdbController; import org.binarytranslator.generic.execution.InterpreterController; -import org.binarytranslator.generic.execution.ThreadedInterpretationController; -import org.binarytranslator.generic.execution.ThreadedInterpretationController2; -import org.binarytranslator.generic.execution.ThreadedInterpretationController3; -import org.binarytranslator.generic.execution.ThreadedInterpretationController4; -import org.binarytranslator.generic.execution.ThreadedInterpretationController5; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -68,7 +62,10 @@ DBT_Options.parseArguments(args); } catch (Exception e) { System.err.println("Error while parsing command line arguments."); - System.err.println(e.getMessage()); + + if (DBT_Options.debugRuntime) + e.printStackTrace(); + showUsage(); return; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-06-08 14:03:25
|
Revision: 128 http://svn.sourceforge.net/pearcolator/?rev=128&view=rev Author: michael_baer Date: 2007-06-08 07:03:26 -0700 (Fri, 08 Jun 2007) Log Message: ----------- Fixed bugs in the ARM translator when not using "Single-instruction-translation". Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X862IR.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/memory/AutoMappingMemory.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java src/org/binarytranslator/arch/arm/decoder/CountingInstructionFactory.java src/org/binarytranslator/arch/arm/hardware/ src/org/binarytranslator/arch/arm/hardware/Coprocessor.java src/org/binarytranslator/arch/arm/hardware/SystemControlCP.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-05-21 17:43:21 UTC (rev 127) +++ src/org/binarytranslator/DBT_Options.java 2007-06-08 14:03:26 UTC (rev 128) @@ -27,35 +27,25 @@ /** Debug binary loading */ public final static boolean debugLoader = true; - /** Are unimplemented system calls are fatal? */ + /** Are unimplemented system calls fatal? */ public final static boolean unimplementedSystemCallsFatal = false; - // -oO Translation settings Oo- - /** The file that is currently being executed. */ public static String executableFile; /** Arguments given to the executable.*/ public static String[] executableArguments = null; - /** - * The initial optimisation level - */ + /** The initial optimisation level */ public static int initialOptLevel = 0; - /** - * Instructions to translate for an optimisation level 0 trace - */ + /** Instructions to translate for an optimisation level 0 trace */ public static int instrOpt0 = 684; - /** - * Instructions to translate for an optimisation level 1 trace - */ + /** Instructions to translate for an optimisation level 1 trace */ public static int instrOpt1 = 1500; - /** - * Instructions to translate for an optimisation level 2 trace - */ + /** Instructions to translate for an optimisation level 2 trace */ public static int instrOpt2 = 1500; /** @@ -65,9 +55,7 @@ */ public final static boolean optimizeBackwardBranches = true; - /** - * Set this to true to record uncaught branch instructions - */ + /** Set this to true to record uncaught branch instructions */ public static boolean plantUncaughtBranchWatcher = false; /** Should direct branches be resolved before dynamic branches? */ @@ -101,69 +89,46 @@ */ public static boolean debugBranchResolution = true; - /** - * In PPC2IR, print cfg. - */ + /** During code translation, print information about the creation of basic blocks. */ public final static boolean debugCFG = false; - // -oO Runtime debugging options Oo- - - /** - * Debug using GDB? - */ + /** Debug using GDB? */ public static boolean gdbStub = false; - /** - * GDB stub port - */ + /** GDB stub port */ public static int gdbStubPort = 1234; + + /** Print debug information during the translation of instructions. */ + public static boolean debugTranslation = true; - /** - * In ProcessSpace, print syscall numbers. - */ + /** In ProcessSpace, print syscall numbers. */ public static boolean debugSyscall = false; - /** - * In ProcessSpace, print syscall numbers. - */ + /** In ProcessSpace, print syscall numbers. */ public static boolean debugSyscallMore = false; - /** - * Print out various messages about the emulator starting. - */ + /** Print out various messages about the emulator starting. */ public static boolean debugRuntime = true; - /** - * Print out messages from the memory system - */ + /** Print out messages from the memory system */ public static boolean debugMemory = false; - /** - * Print out process space between instructions - */ + /** Print out process space between instructions */ public final static boolean debugPS = false; - /** - * When printing process space, omit floating point registers. - */ + /** When printing process space, omit floating point registers. */ public final static boolean debugPS_OmitFP = false; - /** - * The user ID for the user running the command - */ + /** The user ID for the user running the command */ public final static int UID = 1000; - /** - * The group ID for the user running the command - */ + /** The group ID for the user running the command */ public final static int GID = 100; /** Stores the arguments given to the DBT by the user. These are NOT the arguments given to the executable. */ private final static HashMap<String, String> dbtArguments = new HashMap<String, String>(); - /** - * Read and parse the command line arguments. - */ + /** Read and parse the command line arguments. */ public static void parseArguments(String[] args) { try { Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-05-21 17:43:21 UTC (rev 127) +++ src/org/binarytranslator/Main.java 2007-06-08 14:03:26 UTC (rev 128) @@ -95,10 +95,10 @@ System.err.println("Error accesing file: " + args[0] + ". " + e.getMessage()); return; } - catch (Error e) { + /*catch (Error e) { System.err.println(e.getMessage()); return; - } + }*/ report("Sucessfully created process."); @@ -129,10 +129,10 @@ public static void onExit(int exitcode) { System.out.println("\nProgram has finished. Exitcode: " + exitcode); - try { - ps.branchInfo.saveAsXML("/tmp/profile.xml"); + /*try { + //ps.branchInfo.saveAsXML("/tmp/profile.xml"); } catch (IOException e) { e.printStackTrace(); - } + }*/ } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-21 17:43:21 UTC (rev 127) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-06-08 14:03:26 UTC (rev 128) @@ -372,7 +372,7 @@ @Override protected int translateInstruction(Laziness lazy, int pc) { - int nextAddr = translator.translateInstruction(pc, (ARM_Laziness)lazy); + int nextAddr = translator.translateInstruction(pc, (ARM_Laziness)lazy); return nextAddr; } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-05-21 17:43:21 UTC (rev 127) +++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-06-08 14:03:26 UTC (rev 128) @@ -227,6 +227,8 @@ return decode(instruction, _defaultFactory); } + public static int fastpathCount = 0; + /** * Decodes a binary ARM instruction. This method will use the supplied {@link ARM_InstructionFactory} * to create an object representation of the decoded instruction. @@ -241,8 +243,24 @@ */ static <T> T decode(int instruction, ARM_InstructionFactory<T> factory) { - int bits_27_25 = Utils.getBits(instruction, 25, 27); - return prefixDecoders[bits_27_25].decode(instruction, factory); + if (ARM_Options.DATAPROCESSING_DECODER_FASTPATH) { + + //Check condition!=never? + if ((instruction & 0xF0000000) != 0xF0000000) { + + if ((instruction & 0x0F000000) == 0x02000000) { + fastpathCount++; + return factory.createDataProcessing(instruction); + } + } + + int bits_27_25 = Utils.getBits(instruction, 25, 27); + return prefixDecoders[bits_27_25].decode(instruction, factory); + } + else { + int bits_27_25 = Utils.getBits(instruction, 25, 27); + return prefixDecoders[bits_27_25].decode(instruction, factory); + } } /** @@ -254,11 +272,11 @@ */ interface ARM_InstructionFactory<T> { T createDataProcessing(int instr); + T createSwap(int instr); T createSingleDataTransfer(int instr); T createBlockDataTransfer(int instr); T createIntMultiply(int instr); T createLongMultiply(int instr); - T createSwap(int instr); T createSoftwareInterrupt(int instr); T createBranch(int instr); T createBranchExchange(int instr); @@ -274,7 +292,7 @@ * A default implementation of the ARM instruction factory, which will create the * appropriate classes from the {@link ARM_Instructions} namespace. */ - static class DefaultFactory implements ARM_InstructionFactory<ARM_Instructions.Instruction> { + private static class DefaultFactory implements ARM_InstructionFactory<ARM_Instructions.Instruction> { public Instruction createBlockDataTransfer(int instr) { return new MultipleDataTransfer(instr); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-21 17:43:21 UTC (rev 127) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-06-08 14:03:26 UTC (rev 128) @@ -30,12 +30,12 @@ protected final ARM_Registers regs; /** The interpreter factory is creating the final instructions, which implement the Interpreter.Instruction interface. */ - protected final InterpreterFactory instructionFactory; + protected final ARM_InstructionFactory<ARM_Instruction> instructionFactory; public ARM_Interpreter(ARM_ProcessSpace ps) { this.ps = ps; this.regs = ps.registers; - instructionFactory = new InterpreterFactory(); + instructionFactory = new CountingInstructionFactory<ARM_Instruction>(new InterpreterFactory()); } /** Decodes the instruction at the given address.*/ @@ -51,7 +51,12 @@ return instruction; } + @Override + public String toString() { + return instructionFactory.toString(); + } + private abstract static class ResolvedOperand { protected int value; Added: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-06-08 14:03:26 UTC (rev 128) @@ -0,0 +1,6 @@ +package org.binarytranslator.arch.arm.decoder; + +public class ARM_Options { + public final static boolean FLAG_LAZINESS = false; + public final static boolean DATAPROCESSING_DECODER_FASTPATH = false; +} Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-21 17:43:21 UTC (rev 127) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-06-08 14:03:26 UTC (rev 128) @@ -1,6 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; @@ -44,7 +45,30 @@ this.pc = pc; this.lazy = lazy; - int instruction = ps.memory.loadInstruction32(pc); + int instruction; + try { + instruction = ps.memory.loadInstruction32(pc); + } + catch (NullPointerException e) { + if (DBT_Options.debugTranslation) + System.out.print(String.format("Exception while reading instruction from: 0x%x. ", pc)); + + if (arm2ir.getNumInstructions() == 0) { + if (DBT_Options.debugTranslation) + System.out.println("Planting exception instead."); + + arm2ir.appendThrowBadInstruction(lazy, pc); + return -1; + } + else { + if (DBT_Options.debugTranslation) + System.out.println("Planting return from trace instead."); + + arm2ir.appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); + return -1; + } + + } ARM_Instruction instr = ARM_InstructionDecoder.decode(instruction, translatorFactory); if (instr.getCondition() != Condition.AL) { @@ -120,7 +144,7 @@ OperandWrapper operand) { ResolvedOperand result = new ResolvedOperand_WithoutShifterCarryOut( translator, operand); - return result.getValue(); + return result.getValue().copy(); } /** @@ -240,19 +264,19 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(block2); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount.copy(), new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 - normal case translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstruction(Binary.create(INT_SHR, resultRegister, shiftedOperand.copy(), shiftAmount.copy())); translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 2 - shift >= 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); translator.arm2ir.appendInstruction(Binary.create( - INT_SHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(31))); + INT_SHR, resultRegister.copyRO(), shiftedOperand.copy(), new OPT_IntConstantOperand(31))); break; case LSL: @@ -266,18 +290,18 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(block2); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount.copy(), new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 - normal case translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Binary.create(INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstruction(Binary.create(INT_SHL, resultRegister, shiftedOperand.copy(), shiftAmount.copy())); translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 2 - shift >= 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister.copyRO(), new OPT_IntConstantOperand(0)) ); break; case LSR: @@ -293,25 +317,25 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(block2); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount.copy(), new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 - normal case translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand.copy(), shiftAmount.copy())); translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 2 - shift >= 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister.copyRO(), new OPT_IntConstantOperand(0)) ); break; case ROR: /* * return Integer.rotateRight(value, shiftAmount); */ - translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); + translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand.copy(), shiftAmount.copy()); break; case RRX: @@ -326,13 +350,13 @@ curBlock.deleteNormalOut(); curBlock.insertOut(nextBlock); curBlock.insertOut(block1); - translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); + 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())); //Block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Binary.create(INT_OR, resultRegister, resultRegister, new OPT_IntConstantOperand(0x80000000))); + translator.arm2ir.appendInstruction(Binary.create(INT_OR, resultRegister.copyRO(), resultRegister.copy(), new OPT_IntConstantOperand(0x80000000))); break; default: @@ -453,33 +477,33 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(block4); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block4.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block4.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 - shift != 0 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation.copyRO(), shiftAmount.copy(), new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 2 - shift < 32 && shift != 0 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount) ); - translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1)) ); - translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); + translator.arm2ir.appendInstruction(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount.copy()) ); + translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, shiftAmount.copy(), new OPT_IntConstantOperand(-1)) ); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp.copy()); translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 3 - shift >= 32 translator.arm2ir.setCurrentBlock(block3); block3.insertOut(nextBlock); translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 31); - translator.arm2ir.appendInstruction(Binary.create(INT_MUL, resultRegister, getShifterCarryOutTarget(), new OPT_IntConstantOperand(-1)) ); //creates either 0xFFFFFFFF if the bit is set, or 0 otherwise + translator.arm2ir.appendInstruction(Binary.create(INT_MUL, resultRegister.copyRO(), getShifterCarryOutTarget(), new OPT_IntConstantOperand(-1)) ); //creates either 0xFFFFFFFF if the bit is set, or 0 otherwise translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 4 - shift == 0 translator.arm2ir.setCurrentBlock(block4); block4.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, shiftedOperand)); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister.copyRO(), shiftedOperand.copy())); break; case LSL: @@ -497,26 +521,26 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block6); curBlock.insertOut(block1); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block6.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block6.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 - shift != 0 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation.copyRO(), shiftAmount.copy(), new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 2 - Shift != 0 && Shift < 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); translator.arm2ir.appendInstruction(Binary.create(INT_SUB, tmp, new OPT_IntConstantOperand(32), shiftAmount) ); - translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); - translator.arm2ir.appendInstruction(Binary.create(INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand.copy(), tmp.copy()); + translator.arm2ir.appendInstruction(Binary.create(INT_SHL, resultRegister, shiftedOperand.copy(), shiftAmount.copy())); translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 3 - Shift >= 32 translator.arm2ir.setCurrentBlock(block3); - translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.EQUAL(), block5.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister.copyRO(), new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation.copyRO(), shiftAmount.copy(), new OPT_IntConstantOperand(32), OPT_ConditionOperand.EQUAL(), block5.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); block3.insertOut(block4); block3.insertOut(block5); @@ -529,13 +553,13 @@ //block 5 - Shift == 32 translator.arm2ir.setCurrentBlock(block5); block5.insertOut(nextBlock); - translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 0); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand.copy(), 0); translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 6 - shift == 0 translator.arm2ir.setCurrentBlock(block6); block6.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, shiftedOperand)); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister.copyRO(), shiftedOperand.copy())); break; case LSR: @@ -554,26 +578,26 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block6); curBlock.insertOut(block1); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block6.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block6.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 - shift != 0 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation.copyRO(), shiftAmount.copy(), new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 2 - Shift != 0 && Shift < 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1))); - translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); - translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, shiftAmount.copy(), new OPT_IntConstantOperand(-1))); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand.copy(), tmp.copy()); + translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand.copy(), shiftAmount.copy())); translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 3 - Shift >= 32 translator.arm2ir.setCurrentBlock(block3); - translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.EQUAL(), block5.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister.copyRO(), new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation.copyRO(), shiftAmount.copy(), new OPT_IntConstantOperand(32), OPT_ConditionOperand.EQUAL(), block5.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); block3.insertOut(block4); block3.insertOut(block5); @@ -586,13 +610,13 @@ //block 5 - Shift == 32 translator.arm2ir.setCurrentBlock(block5); block5.insertOut(nextBlock); - translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 31); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand.copy(), 31); translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 6 - shift == 0 translator.arm2ir.setCurrentBlock(block6); block6.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, shiftedOperand)); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister.copyRO(), shiftedOperand.copy())); break; case ROR: @@ -606,20 +630,20 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(block2); - translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, shiftAmount.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); - translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1)) ); - translator.arm2ir.appendInstruction(Binary.create(INT_AND, tmp, tmp, new OPT_IntConstantOperand(0x1F)) ); - translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); + translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand.copy(), shiftAmount.copy()); + translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, shiftAmount.copy(), new OPT_IntConstantOperand(-1)) ); + translator.arm2ir.appendInstruction(Binary.create(INT_AND, tmp.copyRO(), tmp.copy(), new OPT_IntConstantOperand(0x1F)) ); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand.copy(), tmp.copy()); translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 2 translator.arm2ir.setCurrentBlock(block2); - translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, shiftedOperand)); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister.copyRO(), shiftedOperand.copy())); break; case RRX: @@ -633,17 +657,17 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand, 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(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())); //Block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstruction(Binary.create(INT_OR, resultRegister, resultRegister, new OPT_IntConstantOperand(0x80000000))); + translator.arm2ir.appendInstruction(Binary.create(INT_OR, resultRegister.copyRO(), resultRegister.copy(), new OPT_IntConstantOperand(0x80000000))); //nextBlock translator.arm2ir.setCurrentBlock(nextBlock); - translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 0); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand.copy(), 0); break; default: @@ -683,7 +707,6 @@ } public int getSuccessor(int pc) { - //if this instruction is not a jump, then we can tell what the next instruction will be. return pc + 4; } @@ -733,7 +756,7 @@ break; case LS: - translateCondition_LS(nextInstruction); + translateCondition_LS(nextInstruction, condBlock); break; case LT: @@ -798,19 +821,31 @@ arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, carry, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } - private void translateCondition_LS(OPT_BasicBlock nextInstruction) { + private void translateCondition_LS(OPT_BasicBlock nextInstruction, OPT_BasicBlock actualInstruction) { //return !regs.isCarrySet() || regs.isZeroSet(); OPT_Operand carry = arm2ir.getCarryFlag(); OPT_Operand zero = arm2ir.getZeroFlag(); - OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); - 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())); + OPT_RegisterOperand result = arm2ir.getTempInt(0); - arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + 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(), new OPT_BranchProfileOperand())); + +/* 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) { @@ -823,7 +858,7 @@ arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, negative, overflow, OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_LE(OPT_BasicBlock nextInstruction) { @@ -836,7 +871,7 @@ arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, negative, overflow, OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } public Condition getCondition() { @@ -901,7 +936,7 @@ arm2ir.appendTraceExit(lazy, result); } else { - arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result.copy()) ); } } @@ -917,19 +952,19 @@ 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(), lhs, rhs, OPT_ConditionOperand.CARRY_FROM_ADD(), new OPT_BranchProfileOperand())); + 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, rhs, OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); + 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, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + 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, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); } /** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/ @@ -952,7 +987,7 @@ arm2ir.appendTraceExit(lazy, result); } else { - arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result.copy()) ); } } @@ -969,19 +1004,19 @@ //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, rhs, notBorrowFromSub, new OPT_BranchProfileOperand())); + 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, rhs, OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); + 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, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + 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, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); } public int getSuccessor(int pc) { @@ -1039,7 +1074,7 @@ } } else { - arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result.copy()) ); } } @@ -1053,11 +1088,11 @@ //set the negative flag arm2ir.appendInstruction(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + 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, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); } } @@ -1178,7 +1213,7 @@ //Yes, the carry flag is set. Pre-increase the result by one to account for the carry. arm2ir.setCurrentBlock(addWithCarry); - arm2ir.appendInstruction(Binary.create(INT_ADD, result, result, new OPT_IntConstantOperand(1))); + arm2ir.appendInstruction(Binary.create(INT_ADD, result.copyRO(), result.copy(), new OPT_IntConstantOperand(1))); addWithCarry.insertOut(addWithoutCarry); //Finally, add the second operands to the result @@ -1209,7 +1244,7 @@ //No, the carry flag is not set. That means, we have to use the carry within the subtraction (weird arm logic). arm2ir.setCurrentBlock(subWithCarry); - arm2ir.appendInstruction(Binary.create(INT_SUB, result, result, new OPT_IntConstantOperand(1))); + arm2ir.appendInstruction(Binary.create(INT_SUB, result.copyRO(), result.copy(), new OPT_IntConstantOperand(1))); subWithCarry.insertOut(subWithoutCarry); //Finally, subtract the second operands from the result @@ -1359,7 +1394,7 @@ OPT_RegisterOperand tmp = arm2ir.getTempInt(0); arm2ir.appendInstruction(Unary.create(INT_NOT, tmp, operand2)); - arm2ir.appendInstruction(Binary.create(INT_AND, result, operand1, tmp)); + arm2ir.appendInstruction(Binary.create(INT_AND, result, operand1, tmp.copy())); setLogicalResult(result); } } @@ -1442,14 +1477,14 @@ OPT_RegisterOperand rotation = arm2ir.getTempInt(1); //rotation = (memAddr & 0x3) * 8 - arm2ir.appendInstruction(Binary.create(INT_AND, rotation, memAddr, new OPT_IntConstantOperand(0x3))); - arm2ir.appendInstruction(Binary.create(INT_SHL, rotation, rotation, new OPT_IntConstantOperand(3))); - arm2ir.appendRotateRight(result, tmp, rotation); + arm2ir.appendInstruction(Binary.create(INT_AND, rotation, memAddr.copy(), new OPT_IntConstantOperand(0x3))); + arm2ir.appendInstruction(Binary.create(INT_SHL, rotation.copyRO(), rotation.copy(), new OPT_IntConstantOperand(3))); + arm2ir.appendRotateRight(result, tmp.copy(), rotation.copy()); } else { - ps.memory.translateLoadUnsigned8(memAddr, tmp); + ps.memory.translateLoadUnsigned8(memAddr.copy(), tmp); ps.memory.translateStore8(memAddr, arm2ir.getRegister(Rm)); - arm2ir.appendInstruction(Move.create(INT_MOVE, result, tmp)); + arm2ir.appendInstruction(Move.create(INT_MOVE, result, tmp.copy())); } } @@ -1508,19 +1543,19 @@ //post-indexing, backward reading //startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; OPT_Operand offset = new OPT_IntConstantOperand((registerCount + (transferPC ? 1 : 0)) * 4); - arm2ir.appendInstruction(Binary.create(INT_SUB, startAddress, startAddress, offset)); + arm2ir.appendInstruction(Binary.create(INT_SUB, startAddress.copyRO(), startAddress.copy(), offset)); } else { //pre-indexing, backward-reading //startAddress -= (registerCount + (transferPC ? 2 : 1)) * 4 OPT_Operand offset = new OPT_IntConstantOperand((registerCount + (transferPC ? 2 : 1)) * 4); - arm2ir.appendInstruction(Binary.create(INT_SUB, startAddress, startAddress, offset)); + arm2ir.appendInstruction(Binary.create(INT_SUB, startAddress.copyRO(), startAddress.copy(), offset)); } } else { if (postIndexing) { //post-indexing, forward reading //startAddress -= 4; OPT_Operand offset = new OPT_IntConstantOperand(4); - arm2ir.appendInstruction(Binary.create(INT_SUB, startAddress, startAddress, offset)); + arm2ir.appendInstruction(Binary.create(INT_SUB, startAddress.copyRO(), startAddress.copyRO(), offset)); } else { //pre-indexing, forward reading //no need to adjust the start address @@ -1528,7 +1563,7 @@ } OPT_RegisterOperand nextAddress = arm2ir.getTempInt(1); - arm2ir.appendInstruction(Move.create(INT_MOVE, nextAddress, startAddress)); + arm2ir.appendInstruction(Move.create(INT_MOVE, nextAddress, startAddress.copy())); //are we supposed to load or store multiple registers? if (isLoad) { @@ -1536,7 +1571,7 @@ while (registersToTransfer[nextReg] != -1) { //nextAddress += 4; - arm2ir.appendInstruction(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); + arm2ir.appendInstruction(Binary.create(INT_ADD, nextAddress.copyRO(), nextAddress.copy(), new OPT_IntConstantOperand(4))); OPT_RegisterOperand target = arm2ir.getRegister(registersToTransfer[nextReg++]); ps.memory.translateLoad32(nextAddress, target); @@ -1545,13 +1580,13 @@ //if we also transferred the program counter if (transferPC) { //nextAddress += 4; - arm2ir.appendInstruction(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); + arm2ir.appendInstruction(Binary.create(INT_ADD, nextAddress.copyRO(), nextAddress.copy(), new OPT_IntConstantOperand(4))); OPT_RegisterOperand regPC = arm2ir.getRegister(ARM_Registers.PC); - ps.memory.translateLoad32(nextAddress, regPC); + ps.memory.translateLoad32(nextAddress.copy(), regPC); //first translate the register write back - translateWriteback(startAddress, nextAddress); + translateWriteback(startAddress.copyRO(), nextAddress.copyRO()); //shall we switch to thumb mode? OPT_BasicBlock finishInstruction = arm2ir.createBlockAfterCurrentNotInCFG(); @@ -1563,7 +1598,7 @@ currentBlock.deleteNormalOut(); currentBlock.insertOut(switchToARMBlock); currentBlock.insertOut(switchToThumbBlock); - arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), regPC, new OPT_IntConstantOperand(1), OPT_ConditionOperand.BIT_TEST(), switchToThumbBlock.makeJumpTarget(), OPT_BranchProfileOperand.never())); + 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 @@ -1577,7 +1612,7 @@ //No, don't switch to thumb mode arm2ir.setCurrentBlock(switchToARMBlock); switchToARMBlock.insertOut(finishInstruction); - arm2ir.appendInstruction(Binary.create(INT_AND, regPC, regPC, new OPT_IntConstantOperand(0xFFFFFFFE))); + 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); @@ -1593,18 +1628,18 @@ while (registersToTransfer[nextReg] != -1) { //nextAddress += 4; - arm2ir.appendInstruction(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); - ps.memory.translateStore32(nextAddress, arm2ir.getRegister(registersToTransfer[nextReg++])); + arm2ir.appendInstruction(Binary.create(INT_ADD, nextAddress.copyRO(), nextAddress.copy(), new OPT_IntConstantOperand(4))); + ps.memory.translateStore32(nextAddress.copy(), arm2ir.getRegister(registersToTransfer[nextReg++])); } //also transfer the program counter, if requested so if (transferPC) { - arm2ir.appendInstruction(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); - ps.memory.translateStore32(nextAddress, new OPT_IntConstantOperand(pc + 8)); + arm2ir.appendInstruction(Binary.create(INT_ADD, nextAddress.copyRO(), nextAddress.copy(), new OPT_IntConstantOperand(4))); + ps.memory.translateStore32(nextAddress.copy(), new OPT_IntConstantOperand(pc + 8)); } } - translateWriteback(startAddress, nextAddress); + translateWriteback(startAddress.copyRO(), nextAddress.copyRO()); } private void translateWriteback(OPT_RegisterOperand startAddress, OPT_RegisterOperand nextAddress) { @@ -1757,17 +1792,17 @@ if (accumulate) { OPT_Operand operand3 = arm2ir.getRegister(Rn); - arm2ir.appendInstruction(Binary.create(INT_ADD, result, result, operand3)); + arm2ir.appendInstruction(Binary.create(INT_ADD, result.copyRO(), result.copy(), operand3)); } if (updateConditionCodes) { //set the negative flag arm2ir.appendInstruction(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + 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, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); } } @@ -1799,35 +1834,35 @@ if (unsigned) { //treat the original ints as unsigned, so get rid of the signs for the longs - arm2ir.appendInstruction(Binary.create(LONG_AND, operand1, operand1, new OPT_LongConstantOperand(0xFFFFFFFF))); - arm2ir.appendInstruction(Binary.create(LONG_AND, operand2, operand2, new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstruction(Binary.create(LONG_AND, operand1.copyRO(), operand1.copy(), new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstruction(Binary.create(LONG_AND, operand2.copyRO(), operand2.copy(), new OPT_LongConstantOperand(0xFFFFFFFF))); } //multiply the two operands - arm2ir.appendInstruction(Binary.create(LONG_MUL, result, operand1, operand2)); + arm2ir.appendInstruction(Binary.create(LONG_MUL, result.copyRO(), operand1.copy(), operand2.copy())); if (accumulate) { //treat the accum. value as an unsigned value OPT_Operand operand3 = arm2ir.getRegister(getRdLow()); OPT_RegisterOperand tmp = arm2ir.getTempLong(0); arm2ir.appendInstruction(Unary.create(INT_2LONG, tmp, operand3)); - arm2ir.appendInstruction(Binary.create(LONG_AND, tmp, tmp, new OPT_LongConstantOperand(0xFFFFFFFF))); - arm2ir.appendInstruction(Binary.create(LONG_ADD, result, result, tmp)); + arm2ir.appendInstruction(Binary.create(LONG_AND, tmp.copyRO(), tmp.copy(), new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstruction(Binary.create(LONG_ADD, result.copyRO(), result.copy(), tmp.copy())); operand3 = arm2ir.getRegister(getRdHigh()); - arm2ir.appendInstruction(Unary.create(INT_2LONG, tmp, operand3)); - arm2ir.appendInstruction(Binary.create(LONG_SHL, tmp, tmp, new OPT_IntConstantOperand(32))); - arm2ir.appendInstruction(Binary.create(INT_ADD, result, result, operand3)); + arm2ir.appendInstruction(Unary.create(INT_2LONG, tmp.copyRO(), operand3)); + arm2ir.appendInstruction(Binary.create(LONG_SHL, tmp.copyRO(), tmp.copy(), new OPT_IntConstantOperand(32))); + arm2ir.appendInstruction(Binary.create(INT_ADD, result.copyRO(), result.copy(), operand3.copy())); } if (updateConditionCodes) { //set the negative flag arm2ir.appendInstruction(BooleanCmp.create( - BOOLEAN_CMP_LONG, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + BOOLEAN_CMP_LONG, arm2ir.getNegativeFlag(), 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, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + BOOLEAN_CMP_LONG, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); } } @@ -1897,7 +1932,8 @@ } public void translate() { - arm2ir.appendSystemCall(lazy, pc); + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.PC), new OPT_IntConstantOperand(pc))); + arm2ir.appendSystemCall(lazy); arm2ir.appendBranch(arm2ir.getRegister(ARM_Registers.PC), lazy, BranchType.INDIRECT_BRANCH); } @@ -1926,7 +1962,7 @@ else { OPT_RegisterOperand tmp = arm2ir.getTempInt(0); arm2ir.appendInstruction(Unary.create(INT_NEG, tmp, positiveOffset)); - return tmp; + return tmp.copy(); } } @@ -1948,7 +1984,7 @@ //add the offset to the base register OPT_RegisterOperand tmp = arm2ir.getTempInt(0); arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, base, resolveOffset())); - return tmp; + return tmp.copy(); } public void translate() { @@ -1989,12 +2025,12 @@ //make sure that we're not loosing the address due to the shifting OPT_RegisterOperand adrCopy = arm2ir.getTempInt(0); - arm2ir.appendInstruction(Move.create(INT_MOVE, adrCopy, address)); + arm2ir.appendInstruction(Move.create(INT_MOVE, adrCopy, address.copy())); //rotation = (address & 0x3) * 8 - arm2ir.appendInstruction(Binary.create(INT_AND, rotation, address, new OPT_IntConstantOperand(0x3))); - arm2ir.appendInstruction(Binary.create(INT_SHL, rotation, rotation, new OPT_IntConstantOperand(3))); - arm2ir.appendRotateRight(value, value, rotation); + arm2ir.appendInstruction(Binary.create(INT_AND, rotation, address.copy(), new OPT_IntConstantOperand(0x3))); + arm2ir.appendInstruction(Binary.create(INT_SHL, rotation.copyRO(), rotation.copy(), new OPT_IntConstantOperand(3))); + arm2ir.appendRotateRight(value.copyRO(), value.copy(), rotation.copy()); //allow further usage of the memory address address = adrCopy; @@ -2026,7 +2062,7 @@ case Word: OPT_RegisterOperand tmp = arm2ir.getTempInt(0); arm2ir.appendInstruction(Binary.create(INT_AND, tmp, address, new OPT_IntConstantOperand(0xFFFFFFFE))); - ps.memory.translateStore32(tmp, value); + ps.memory.translateStore32(tmp.copyRO(), value); break; case HalfWord: @@ -2055,7 +2091,7 @@ OPT_RegisterOperand writeBackTarget = arm2ir.getRegister(Rn); if (preIndexing) { - arm2ir.appendInstruction(Move.create(INT_MOVE, writeBackTarget, address)); + arm2ir.appendInstruction(Move.create(INT_MOVE, writeBackTarget, address.copy())); } else { //add... [truncated message content] |
From: <mic...@us...> - 2007-05-21 17:43:20
|
Revision: 127 http://svn.sourceforge.net/pearcolator/?rev=127&view=rev Author: michael_baer Date: 2007-05-21 10:43:21 -0700 (Mon, 21 May 2007) Log Message: ----------- - enabled load/storing a branch profile from file - added branch profiling in ARM interpreted code when DBT_Options.profileDuringInterpration is set - slightly changed handling of branch profile creation - Using a HashMap instead of a Weakhashmap in CodeCache to prevent a VM assertion - minor fixes Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java src/org/binarytranslator/generic/branch/BranchLogic.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/decoder/CodeCache.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/DBT_Options.java 2007-05-21 17:43:21 UTC (rev 127) @@ -19,16 +19,15 @@ public class DBT_Options { /** Remove features that will only work on jikes? */ - public final static boolean buildForSunVM = true; + public final static boolean buildForSunVM = false; - /** - * Debug binary loading - */ + /** Enable the profiling of application during interpretation? */ + public final static boolean profileDuringInterpretation = true; + + /** Debug binary loading */ public final static boolean debugLoader = true; - /** - * Are unimplemented system calls are fatal? - */ + /** Are unimplemented system calls are fatal? */ public final static boolean unimplementedSystemCallsFatal = false; // -oO Translation settings Oo- @@ -208,6 +207,8 @@ debugRuntime = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugBranchResolution")) { debugBranchResolution = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:debugMemory")) { + debugMemory = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscall")) { debugSyscall = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugSyscallMore")) { Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/Main.java 2007-05-21 17:43:21 UTC (rev 127) @@ -9,6 +9,7 @@ package org.binarytranslator; import java.io.File; +import java.io.IOException; import org.binarytranslator.generic.execution.DynamicTranslationController; import org.binarytranslator.generic.execution.ExecutionController; @@ -29,6 +30,8 @@ * */ public class Main { + private static ProcessSpace ps; + /** * Debug information * @@ -49,6 +52,8 @@ System.out .println("org.binarytranslator.Main [-X:dbt:...] <program> <args...>"); } + + /** * Main method @@ -81,8 +86,6 @@ return; } - ProcessSpace ps; - try { report("Loading " + DBT_Options.executableFile); Loader loader = Loader.getLoader(DBT_Options.executableFile); @@ -120,6 +123,16 @@ } controller.run(); - System.out.println("\nProgram has finished."); + System.out.println("\nExecution controller has exited."); } + + public static void onExit(int exitcode) { + System.out.println("\nProgram has finished. Exitcode: " + exitcode); + + try { + ps.branchInfo.saveAsXML("/tmp/profile.xml"); + } catch (IOException e) { + e.printStackTrace(); + } + } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-21 17:43:21 UTC (rev 127) @@ -1,6 +1,7 @@ package org.binarytranslator.arch.arm.decoder; import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder.ARM_InstructionFactory; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.OperandWrapper; import org.binarytranslator.arch.arm.decoder.ARM_Instructions.DataProcessing.Opcode; @@ -8,6 +9,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; import org.binarytranslator.arch.arm.os.process.ARM_Registers; import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; +import org.binarytranslator.generic.branch.BranchLogic.BranchType; import org.binarytranslator.generic.decoder.Interpreter; import com.sun.org.apache.bcel.internal.generic.InstructionFactory; @@ -457,7 +459,39 @@ } public abstract void execute(); + + /** + * Stores the result of adding <code>lhs</code> + <code>rhs</code> to <code>Rd</code> + * and sets the flags accordingly, if <code>updateConditionCodes</code> is set. + * @param lhs + * @param rhs + */ + protected final void setAddResult(int lhs, int rhs) { + setFlagsForAdd(lhs, rhs); + if (DBT_Options.profileDuringInterpretation && Rd == 15) { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs + rhs, BranchType.INDIRECT_BRANCH); + } + + regs.set(Rd, lhs + rhs); + } + + /** + * Stores the result of adding <code>lhs</code> - <code>rhs</code> to <code>Rd</code> + * and sets the flags accordingly, if <code>updateConditionCodes</code> is set. + * @param lhs + * @param rhs + */ + protected final void setSubResult(int lhs, int rhs) { + setFlagsForSub(lhs, rhs); + + if (DBT_Options.profileDuringInterpretation && Rd == 15) { + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), lhs - rhs, BranchType.INDIRECT_BRANCH); + } + + regs.set(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) { @@ -522,6 +556,21 @@ return super.resolveOperand2(); } } + + /** Stores the result of a logical operation to a register and, if <code>updateConditionFlags</code> + * 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) + 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); + setFlagsForLogicalOperator(result); + } /** Sets the condition field for logical operations. */ protected final void setFlagsForLogicalOperator(int result) { @@ -546,8 +595,7 @@ @Override public void execute() { int result = resolveOperand1() & resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -561,8 +609,7 @@ @Override public void execute() { int result = resolveOperand1() ^ resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -576,10 +623,8 @@ public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); - int result = operand1 + operand2; - - regs.set(Rd, result); - setFlagsForAdd(operand1, operand2); + + setAddResult(operand1, operand2); } } @@ -594,10 +639,7 @@ public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); - int result = operand1 - operand2; - - regs.set(Rd, result); - setFlagsForSub(operand1, operand2); + setSubResult(operand1, operand2); } } @@ -612,10 +654,7 @@ public void execute() { int operand1 = resolveOperand1(); int operand2 = resolveOperand2(); - int result = operand2 - operand1; - - regs.set(Rd, result); - setFlagsForSub(operand2, operand1); + setSubResult(operand2, operand1); } } @@ -646,11 +685,8 @@ return; } } - - int result = operand1 + operand2; - - regs.set(Rd, result); - setFlagsForAdd(operand1, operand2); + + setAddResult(operand1, operand2); } } @@ -679,10 +715,7 @@ } } - int result = operand1 - operand2; - - regs.set(Rd, result); - setFlagsForSub(operand1, operand2); + setSubResult(operand1, operand2); } } @@ -770,8 +803,7 @@ @Override public void execute() { int result = resolveOperand1() | resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -785,8 +817,7 @@ /** Moves a value into a register .*/ public void execute() { int result = resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -802,8 +833,7 @@ /** Clear bits in a register by a mask given by a second operand. */ public void execute() { int result = resolveOperand1() & (~resolveOperand2()); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -818,8 +848,7 @@ @Override public void execute() { int result = ~resolveOperand2(); - regs.set(Rd, result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -951,6 +980,9 @@ if (transferPC) { nextAddress += 4; int newpc = ps.memory.load32(nextAddress); + + if (DBT_Options.profileDuringInterpretation) + ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), newpc); if (forceUser) { //when we are transferring the PC with a forced-user transfer, then we also want to @@ -1040,8 +1072,16 @@ public void execute() { //if we're supposed to link, then write the previous address into the link register - if (link) + if (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); + } + else { + if (DBT_Options.profileDuringInterpretation) + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), regs.get(ARM_Registers.PC) + getOffset() + 8, BranchType.DIRECT_BRANCH); + } } public int getSuccessor(int pc) { @@ -1084,13 +1124,19 @@ + target.getType()); } + //if we're supposed to link, then write the previous address into the link register + if (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); - - //if we're supposed to link, then write the previous address into the link register - if (link) - regs.set(ARM_Registers.LR, previousAddress - 4); } public int getSuccessor(int pc) { @@ -1376,6 +1422,11 @@ //finally, write the variable into a register regs.set(Rd, value); + + if (DBT_Options.profileDuringInterpretation) { + if (Rd == 15) + ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), value, BranchType.INDIRECT_BRANCH); + } } else { //we are store a value from a register to memory. Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-21 17:43:21 UTC (rev 127) @@ -1663,7 +1663,10 @@ arm2ir.getCurrentBlock().deleteNormalOut(); } - arm2ir.appendBranch(pc + getOffset() + 8, lazy, link ? BranchType.CALL : BranchType.DIRECT_BRANCH); + if (link) + arm2ir.appendCall(pc + getOffset() + 8, lazy, pc + 4); + else + arm2ir.appendBranch(pc + getOffset() + 8, lazy, BranchType.DIRECT_BRANCH); } public int getSuccessor(int pc) { Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-21 17:43:21 UTC (rev 127) @@ -9,7 +9,6 @@ import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.generic.decoder.Interpreter; import org.binarytranslator.generic.memory.ByteAddressedMemory; -import org.binarytranslator.generic.memory.DebugMemory; import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_Trace; @@ -39,11 +38,7 @@ protected ARM_ProcessSpace() { registers = new ARM_Registers(); - - if (DBT_Options.buildForSunVM) - memory = new DebugMemory(); - else - memory = new ByteAddressedMemory(); + memory = new ByteAddressedMemory(); } /** Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-21 17:43:21 UTC (rev 127) @@ -11702,10 +11702,13 @@ plantBranchToBlockDependentOnCondition(ppc2ir, instructionEndBlock, lazy, BI, !branch_if_cond_true, likely_to_fallthrough); } + + if (LK == 0) + ppc2ir.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); + else + ppc2ir.appendCall(target_address, lazy, pc + 4); if ((LK == 0) || ppc2ir.traceContinuesAfterBranchAndLink(pc)) { - // Plant branch block - ppc2ir.appendBranch(target_address, lazy, LK != 0 ? BranchType.CALL : BranchType.DIRECT_BRANCH); // stop translation on branch always if (BO == 0x14) { @@ -11731,7 +11734,6 @@ } else { // This was a branch and link and the trace should stop, so end // gracefully - ppc2ir.appendBranch(target_address, lazy, BranchType.CALL); return -1; } } Modified: src/org/binarytranslator/generic/branch/BranchLogic.java =================================================================== --- src/org/binarytranslator/generic/branch/BranchLogic.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/generic/branch/BranchLogic.java 2007-05-21 17:43:21 UTC (rev 127) @@ -8,12 +8,29 @@ */ package org.binarytranslator.generic.branch; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; /** * Object capturing branches and jumps so that traces can avoid terminating on @@ -72,22 +89,12 @@ procedure = new ProcedureInformation(pc, ret, dest); procedures.put(dest, procedure); } + + registerBranch(pc, dest); } - - /** - * Register a call (branch and link) instruction - * - * @param pc - * the address of the branch instruction - * @param dest - * the destination of the branch instruction - */ - public void registerCall(int pc, int dest) { - registerCall(pc, dest, -1); - } /** - * Register a branch to the link register + * Register a function return. * * @param pc * the address of the branch instruction @@ -95,10 +102,14 @@ * the return address (value of the link register) */ public void registerReturn(int pc, int lr) { + ProcedureInformation procedure = getLikelyProcedure(pc); + if (procedure != null) { procedure.registerReturn(pc, lr); } + + registerBranch(pc, lr); } /** @@ -123,6 +134,7 @@ * Registers a branch from the address <code>origin</code> to the address <code>target</code>. * The type of branch is determined by <code>type</code>, which is an ordinal from the * {@link BranchType} enum. + * * @param origin * The address from which the branch occurs. * @param target @@ -130,24 +142,30 @@ * @param type * The most likely type of the branch. This is taken from the {@link BranchType} enum. */ - public void registerBranch(int origin, int target, int type) { - - if (DBT.VerifyAssertions) DBT._assert(type > 0 && type < BranchType.values().length); - - //Some branch types require a special registration (calls and returns) - switch (BranchType.values()[type]) { - case CALL: - registerCall(origin, target); - break; - - case RETURN: - registerReturn(origin, target); - break; - - default: - break; - } - + public void registerBranch(int origin, int target, BranchType type) { + + switch (type) { + case CALL: + throw new RuntimeException("Use the more specific registerCall() for these cases."); + + case RETURN: + registerReturn(origin, target); + break; + + default: + registerBranch(origin, target); + } + } + + /** + * Appends a recorded branch from <code>origin</code> to <code>target</code> to the branch profile. + * + * @param origin + * The address that the branch is taking place from. + * @param target + * The branch target address. + */ + private void registerBranch(int origin, int target) { //Perform the general branch registration, too Set<Integer> dests = branchSitesAndDestinations.get(origin); @@ -175,4 +193,126 @@ public Set<Integer> getKnownBranchTargets(int pc) { return branchSitesAndDestinations.get(pc); } + + public void loadFromXML(String filename) throws IOException { + + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + Document doc; + try { + DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); + doc = docBuilder.parse(filename); + } catch (ParserConfigurationException e) { + throw new RuntimeException("Error creating DocumentBuilder instance to read an XML file."); + } catch (SAXException e) { + throw new IOException("File " + filename + " is not a valid XML file."); + } + + if (DBT.VerifyAssertions) DBT._assert(doc != null); + + Element root = doc.getDocumentElement(); + + if (!root.getNodeName().equals("branch-profile")) + throw new IOException("File is not a valid XML branch profile."); + + Node branches = null; + + for (int i = 0; i < root.getChildNodes().getLength(); i++) { + Node node = root.getChildNodes().item(0); + + if (node.getNodeName().equals("branches")) { + branches = node; + break; + } + } + + if (branches == null) + throw new IOException("File is not a valid XML branch profile."); + + for (int i = 0; i < branches.getChildNodes().getLength(); i++) { + Node siteNode = branches.getChildNodes().item(i); + + if (!siteNode.getNodeName().equals("origin") || siteNode.getNodeType() != Node.ELEMENT_NODE) + throw new IOException("File is not a valid XML branch profile."); + + int pc = Integer.parseInt(((Element)siteNode).getAttribute("address")); + + for (int n = 0; n < siteNode.getChildNodes().getLength(); n++) { + Node target = siteNode.getChildNodes().item(n); + + if (!target.getNodeName().equals("target") || target.getNodeType() != Node.ELEMENT_NODE) + throw new IOException("File is not a valid XML branch profile."); + + int targetAddress = Integer.parseInt(((Element)target).getAttribute("address")); + registerBranch(pc, targetAddress); + } + } + } + + /** + * Saves the branch profile of the current process space to the give file in XML format. + * + * @param filename + * The name of the file to which the branch profile is saved. + * @throws IOException + * Thrown if there is an error while creating the file. + */ + public void saveAsXML(String filename) throws IOException { + + FileOutputStream outputStream; + + try { + File f = new File(filename); + + if (!f.exists()) + f.createNewFile(); + + outputStream = new FileOutputStream(f); + } + catch (FileNotFoundException e) { + //this should not happen, as we just created the file + throw new IOException("Error creating file: " + filename); + } + + //Create an XML representation of the branch profile + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder; + try { + docBuilder = docBuilderFactory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new IOException("Error creating parser to produce XML document."); + } + Document doc = docBuilder.newDocument(); + + Element root = doc.createElement("branch-profile"); + root.setAttribute("application", DBT_Options.executableFile); + doc.appendChild(root); + + Element branchesElement = doc.createElement("branches"); + root.appendChild(branchesElement); + + for (int pc : branchSitesAndDestinations.keySet()) { + Element branchSiteElement = doc.createElement("origin"); + branchesElement.appendChild(branchSiteElement); + branchSiteElement.setAttribute("address", Integer.toString(pc)); + + for (int target : getKnownBranchTargets(pc)) { + Element branchTargetElement = doc.createElement("target"); + branchSiteElement.appendChild(branchTargetElement); + branchTargetElement.setAttribute("address", Integer.toString(target)); + } + } + + //Output the resulting XML document + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer; + try { + transformer = tFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(outputStream); + transformer.transform(source, result); + + } catch (Exception e) { + e.printStackTrace(); + } + } } Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-21 14:20:19 UTC (rev 126) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-21 17:43:21 UTC (rev 127) @@ -74,18 +74,22 @@ * </dd> * </dl> */ -public abstract class AbstractCodeTranslator implements OPT_Constants, OPT_Operators { +public abstract class AbstractCodeTranslator implements OPT_Constants, + OPT_Operators { /** The trace that we're currently translating code for. */ protected final DBT_Trace trace; - + /** VM_TypeReference of org.binarytranslator.generic.os.process.ProcessSpace */ private static final VM_TypeReference psTref; /** Method ProcessSpace.doSysCall */ public static final VM_Method sysCallMethod; - /** VM_TypeReference of org.binarytranslator.generic.fault.BadInstructionException */ + /** + * VM_TypeReference of + * org.binarytranslator.generic.fault.BadInstructionException + */ public static final VM_Class badInstrKlass; /** Method BadInstructionException.<init> */ @@ -106,15 +110,17 @@ BadInstructionException.class).asClass(); VM_MethodReference badInstrKlassInitMethRef = (VM_MethodReference) VM_MemberReference - .findOrCreate(badInstrKlass.getTypeRef(), + .findOrCreate( + badInstrKlass.getTypeRef(), VM_Atom.findOrCreateAsciiAtom("<init>"), - VM_Atom.findOrCreateAsciiAtom("(ILorg/binarytranslator/generic/os/process/ProcessSpace;)V")); + VM_Atom + .findOrCreateAsciiAtom("(ILorg/binarytranslator/generic/os/process/ProcessSpace;)V")); badInstrKlassInitMethod = badInstrKlassInitMethRef.resolveInvokeSpecial(); VM_MethodReference recordUncaughtBranchMethRef = (VM_MethodReference) VM_MemberReference .findOrCreate(psTref, VM_Atom .findOrCreateAsciiAtom("recordUncaughtBranch"), VM_Atom - .findOrCreateAsciiAtom("(III)V")); + .findOrCreateAsciiAtom("(IIII)V")); recordUncaughtBranchMethod = recordUncaughtBranchMethRef .resolveInvokeSpecial(); } @@ -153,14 +159,18 @@ /** Map to locate HIR basic blocks to re-use translation within a trace */ protected final HashMap<Laziness.Key, OPT_BasicBlock> blockMap; - + private final static class UnresolvedJumpInstruction { public final OPT_Instruction instruction; + public final Laziness lazyStateAtJump; + public final int pc; + public final BranchType type; - - public UnresolvedJumpInstruction(OPT_Instruction instruction, Laziness lazyStateAtJump, int pc, BranchType type) { + + public UnresolvedJumpInstruction(OPT_Instruction instruction, + Laziness lazyStateAtJump, int pc, BranchType type) { this.instruction = instruction; this.lazyStateAtJump = lazyStateAtJump; this.pc = pc; @@ -168,27 +178,30 @@ } } - /** - * List of unresolved direct branches. The destinations of direct branches are already known at - * translation time.*/ + /** + * List of unresolved direct branches. The destinations of direct branches are + * already known at translation time. + */ private final ArrayList<UnresolvedJumpInstruction> unresolvedDirectBranches; - - /** - * List of unresolved dynamic branches. Dynamics branches have a destination address that is only - * determined at runtime. */ + + /** + * List of unresolved dynamic branches. Dynamics branches have a destination + * address that is only determined at runtime. + */ private final ArrayList<UnresolvedJumpInstruction> unresolvedDynamicBranches; /** * Constructor * * @param context - * The JRVM generation context for this trace. + * The JRVM generation context for this trace. */ - protected AbstractCodeTranslator(OPT_GenerationContext context, DBT_Trace trace) { - - //Store the trace that we're invoked from + protected AbstractCodeTranslator(OPT_GenerationContext context, + DBT_Trace trace) { + + // Store the trace that we're invoked from this.trace = trace; - + // Make copies of popular variables gc = context; ps = ((DBT_Trace) (gc.method)).ps; @@ -211,7 +224,7 @@ unresolvedDirectBranches = new ArrayList<UnresolvedJumpInstruction>(); unresolvedDynamicBranches = new ArrayList<UnresolvedJumpInstruction>(); } - + /** Returns the number of previously translated instructions within this trace. */ public int getNumInstructions() { return numberOfInstructions; @@ -230,10 +243,10 @@ if (!DBT_Options.resolveDirectBranchesFirst) { resolveAllDynamicBranchTargets(); } - - //Resolve all open direct first + + // Resolve all open direct first resolveAllDirectBranches(); - + if (DBT_Options.resolveDirectBranchesFirst) { resolveAllDynamicBranchTargets(); } @@ -263,15 +276,14 @@ // Create next block nextBlock = createBlockAfterCurrent(); // Finish block to return and exit - appendTraceExit(lazy, - new OPT_IntConstantOperand(pc)); + appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); // Move currentBlock along currentBlock = nextBlock; } else { do { if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); - + // Record mapping of this pc value and laziness to this block registerMapping(pc, lazy, currentBlock); @@ -285,7 +297,7 @@ // Move currentBlock along currentBlock = nextBlock; currentPC = pc; - + if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); @@ -370,22 +382,23 @@ gc.cfg.linkInCodeOrder(currentBlock, newBlock); gc.cfg.linkInCodeOrder(newBlock, nxtBlock); - /*if (DBT.VerifyAssertions) - DBT._assert(currentBlock.isOut(nxtBlock));*/ + /* + * if (DBT.VerifyAssertions) DBT._assert(currentBlock.isOut(nxtBlock)); + */ if (currentBlock.isOut(nxtBlock)) { currentBlock.deleteOut(nxtBlock); currentBlock.insertOut(newBlock); newBlock.insertOut(nxtBlock); - } - else { + } else { currentBlock.insertOut(newBlock); } if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, currentBlock)); + report(String.format("Created block (%s) after current (%s).", newBlock, + currentBlock)); } - + return newBlock; } @@ -404,7 +417,8 @@ gc.cfg.linkInCodeOrder(newBlock, nxtBlock); if (DBT_Options.debugCFG) { - report(String.format("Created non-cfg block (%s) after current (%s).", newBlock, currentBlock)); + report(String.format("Created non-cfg block (%s) after current (%s).", + newBlock, currentBlock)); } return newBlock; } @@ -414,7 +428,7 @@ * into the CFG and code ordering * * @param afterBlock - * The block after which the new block is to be created. + * The block after which the new block is to be created. * @return the new basic block */ public OPT_BasicBlock createBlockAfter(OPT_BasicBlock afterBlock) { @@ -432,9 +446,10 @@ newBlock.insertOut(nxtBlock); if (DBT_Options.debugCFG) { - report(String.format("Created block (%s) after current (%s).", newBlock, afterBlock)); + report(String.format("Created block (%s) after current (%s).", newBlock, + afterBlock)); } - + return newBlock; } @@ -442,7 +457,7 @@ * Append a HIR instruction to the current basic block * * @param i - * The instruciton that is to be appended to the current bloc. + * The instruciton that is to be appended to the current bloc. */ public void appendInstruction(OPT_Instruction i) { if (i.bcIndex == UNKNOWN_BCI) { @@ -461,7 +476,7 @@ * Generate a branch profile operand for the current instruction * * @param likely - * Does this branch have a likely hint? + * Does this branch have a likely hint? */ public OPT_BranchProfileOperand getConditionalBranchProfileOperand( boolean likely) { @@ -491,11 +506,11 @@ * Register a mapping between a pc and lazy and a hir block * * @param pc - * The program counter whose translation the basic bock represents. + * The program counter whose translation the basic bock represents. * @param lazy - * The lazy state that is assumed for this basic block. + * The lazy state that is assumed for this basic block. * @param hirBlock - * The block that is to be registered. + * The block that is to be registered. */ protected void registerMapping(int pc, Laziness lazy, OPT_BasicBlock hirBlock) { blockMap.put(lazy.makeKey(pc), hirBlock); @@ -505,175 +520,267 @@ * Find if there's already a translation for a given pc and laziness * * @param pc - * The program counter address at which the returned basic block shall start. + * The program counter address at which the returned basic block + * shall start. * @param lazy - * The lazy state assumed within the returned trace. - * @return - * An appropriate basic block or null if no translation exists. + * The lazy state assumed within the returned trace. + * @return An appropriate basic block or null if no translation exists. */ protected OPT_BasicBlock findMapping(int pc, Laziness lazy) { return blockMap.get(lazy.makeKey(pc)); } /** - * Create a HIR Goto instruction that jumps to the address <code>targetPc</code>. There's - * a caveat on using this that there are no other out edges for this BB. + * Create a HIR Goto instruction that jumps to the address + * <code>targetPc</code>. There's a caveat on using this that there are no + * other out edges for this BB. * * @param targetPC - * The address where we shall jump to. + * The address where we shall jump to. * @param targetLaziness - * The current at the point of jump. + * The current at the point of jump. * @param branchType - * The type of branch that best describes this jump. + * The type of branch that best describes this jump. */ public void appendBranch(int targetPC, Laziness targetLaziness, BranchType branchType) { - //Place a GOTO instruction at this point. However, this instruction - //serves more as a placeholder and might be mutated later on. + if (DBT.VerifyAssertions && branchType == BranchType.CALL) throw new RuntimeException("Use the more specific appendCall to create dynamic calls."); + + appendStaticBranch(targetPC, targetLaziness, branchType, -1); + } + + /** + * Create a HIR Goto instruction that jumps to the address + * <code>targetPc</code>. There's a caveat on using this that there are no + * other out edges for this BB. + * + * @param targetPC + * The address where we shall jump to. + * @param targetLaziness + * The current at the point of jump. + * @param branchType + * The type of branch that best describes this jump. + */ + public void appendCall(int targetPC, Laziness targetLaziness, int retAddr) { + + appendStaticBranch(targetPC, targetLaziness, BranchType.CALL, retAddr); + } + + private void appendStaticBranch(int targetPC, Laziness targetLaziness, BranchType branchType, int retAddr) { + // Place a GOTO instruction at this point. However, this instruction + // serves more as a placeholder and might be mutated later on. OPT_Instruction jump = Goto.create(GOTO, null); appendInstruction(jump); - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(jump, (Laziness)targetLaziness.clone(), targetPC, branchType); + UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction( + jump, (Laziness) targetLaziness.clone(), targetPC, BranchType.CALL); unresolvedDirectBranches.add(unresolvedJump); - //Notify the branch profile about certain types of branches - switch (branchType) { - case CALL: - ps.branchInfo.registerCall(currentPC, targetPC); - return; - - case RETURN: + if (branchType == BranchType.CALL) + ps.branchInfo.registerCall(currentPC, targetPC, retAddr); + else + if (branchType == BranchType.RETURN) ps.branchInfo.registerReturn(currentPC, targetPC); - return; + else + ps.branchInfo.registerBranch(currentPC, targetPC, branchType); + } + + /** + * Append a dynamic jump (a jump whose target address is not known at translation time) to the + * current basic block. + * + * @param targetAddress + * The target address of the jump. + * @param lazyStateAtJump + * The lazy state at the point the jump was added. + * @param retAddr + * The address, to which the function call will (most likely) return. + */ + public void appendCall(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, int retAddr) { + + appendDynamicBranch(targetAddress, lazyStateAtJump, BranchType.CALL, retAddr); + } + + /** + * Append a dynamic jump (a jump whose target address is not known at translation time) to the + * current basic block. + * + * @param targetAddress + * The target address of the jump. + * @param lazyStateAtJump + * The lazy state at the point the jump was added. + * @param branchType + * The type of jump. + */ + public void appendBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType) { + + if (DBT.VerifyAssertions && branchType == BranchType.CALL) throw new RuntimeException("Use the more specific appendCall to create dynamic calls."); + + appendDynamicBranch(targetAddress, lazyStateAtJump, branchType, -1); + } - default: - return; - } + /** + * Append a dynamic jump (a jump whose target address is not known at translation time) to the + * current basic block. + * + * @param targetAddress + * The target address of the jump. + * @param lazyStateAtJump + * The lazy state at the point the jump was added. + * @param branchType + * The type of jump. + * @param retAddr + * The address, to which the function call will (most likely) return or an arbitrary value, if + * branchType is not BranchType.CALL. + */ + private void appendDynamicBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType, int retAddr) { + + OPT_BasicBlock fallThrough = createBlockAfterCurrent(); + OPT_Instruction switchInstr; + switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress, null, null, fallThrough.makeJumpTarget(), null, 0); + appendInstruction(switchInstr); + + UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, branchType); + unresolvedDynamicBranches.add(unresolvedInfo); + + setCurrentBlock(fallThrough); + appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType, retAddr); + appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); + } - /** Resolve all unresolved direct branch instructions. */ + /** Resolve all unresolved direct branch instructions. */ private void resolveAllDirectBranches() { - + for (int i = 0; i < unresolvedDirectBranches.size(); i++) { - - //Get the jump that we're supposed to resolve - UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches.remove(unresolvedDirectBranches.size() - 1); + + // Get the jump that we're supposed to resolve + UnresolvedJumpInstruction unresolvedInstr = unresolvedDirectBranches + .remove(unresolvedDirectBranches.size() - 1); int targetPc = unresolvedInstr.pc; Laziness lazyStateAtJump = unresolvedInstr.lazyStateAtJump; OPT_Instruction gotoInstr = unresolvedInstr.instruction; - - if (DBT.VerifyAssertions) DBT._assert(Goto.conforms(gotoInstr)); - - OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, lazyStateAtJump, unresolvedInstr.type); - + + if (DBT.VerifyAssertions) + DBT._assert(Goto.conforms(gotoInstr)); + + OPT_BasicBlock targetBB = resolveBranchTarget(targetPc, lazyStateAtJump, + unresolvedInstr.type); + if (DBT_Options.debugBranchResolution) { - report("Resolving goto " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); + report("Resolving goto " + lazyStateAtJump.makeKey(targetPc) + " " + + targetBB); } - + // Fix up instruction Goto.setTarget(gotoInstr, targetBB.makeJumpTarget()); gotoInstr.getBasicBlock().insertOut(targetBB); - + if (DBT_Options.debugBranchResolution) { - report("Properly resolving goto in block " - + gotoInstr.getBasicBlock() + " to " + lazyStateAtJump.makeKey(targetPc) + " " - + targetBB); + report("Properly resolving goto in block " + gotoInstr.getBasicBlock() + + " to " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); } } } /** - * Resolves a branch target to an actual basic block. In case the jump target is not yet part - * of this trace, this method also takes a decision about whether the target shall be translated - * into the trace. + * Resolves a branch target to an actual basic block. In case the jump target + * is not yet part of this trace, this method also takes a decision about + * whether the target shall be translated into the trace. * - * Notice that, when {@link DBT_Options#singleInstrTranslation} is turned on, - * this method will always end the current trace, just returning the address of the next instruction. + * Notice that, when {@link DBT_Options#singleInstrTranslation} is turned on, + * this method will always end the current trace, just returning the address + * of the next instruction. * * @param targetPc - * The address of the target basic block that. + * The address of the target basic block that. * @param lazyStateAtJump - * The lazy state with which we would be entering the block. - * @return - * A basic block that is equivalent to the program counter address <code>targetPc</code> in the - * original binary. + * The lazy state with which we would be entering the block. + * @return A basic block that is equivalent to the program counter address + * <code>targetPc</code> in the original binary. */ - private OPT_BasicBlock resolveBranchTarget(int targetPc, Laziness lazyStateAtJump, BranchType branchtype) { - //Resolve the address of the target block + private OPT_BasicBlock resolveBranchTarget(int targetPc, + Laziness lazyStateAtJump, BranchType branchtype) { + // Resolve the address of the target block OPT_BasicBlock targetBB = findMapping(targetPc, lazyStateAtJump); - - //If the target is already part of this trace, then just use the precompiled target + + // If the target is already part of this trace, then just use the + // precompiled target if (targetBB != null) return targetBB; - - /* The target Block is not yet translated. - * We do not want to translate it into the current trace if - * a) DBT_Options.singleInstrTranslation is enabled - * b) The jump target has already been compiled as a separate method within the code cache - * c) The trace is already too long - * d) the branch is supposedly a CALL or RETURN + + /* + * The target Block is not yet translated. We do not want to translate it + * into the current trace if a) DBT_Options.singleInstrTranslation is + * enabled b) The jump target has already been compiled as a separate method + * within the code cache c) The trace is already too long d) the branch is + * supposedly a CALL or RETURN */ - if (DBT_Options.singleInstrTranslation == true || - ps.codeCache.tryGet(targetPc) != null || - shallTraceStop() || - branchtype == BranchType.CALL || - branchtype == BranchType.RETURN) { - - //Just exit the trace and continue at the target address in a new trace + if (DBT_Options.singleInstrTranslation == true + || ps.codeCache.tryGet(targetPc) != null || shallTraceStop() + || branchtype == BranchType.CALL || branchtype == BranchType.RETURN) { + + // Just exit the trace and continue at the target address in a new trace if (currentBlock.getNumberOfRealInstructions() != 0) { currentBlock = createBlockAfterCurrentNotInCFG(); - - if (DBT_Options.debugBranchResolution) System.out.println("Resolving branch to next block."); + + if (DBT_Options.debugBranchResolution) + System.out.println("Resolving branch to next block."); } targetBB = currentBlock; appendTraceExit(lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); registerMapping(targetPc, lazyStateAtJump, targetBB); - } - else { - //Otherwise we will translate the jump into the trace + } else { + // Otherwise we will translate the jump into the trace translateSubTrace((Laziness) lazyStateAtJump.clone(), targetPc); targetBB = findMapping(targetPc, lazyStateAtJump); } - - if (DBT.VerifyAssertions) DBT._assert(targetBB != null); - + + if (DBT.VerifyAssertions) + DBT._assert(targetBB != null); + return targetBB; } /** - * Resolves all dynamic branches that have been added with + * Resolves all dynamic branches that have been added with * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. */ private void resolveDynamicBranches() { for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.get(i); + + UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches + .get(i); Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - + resolveSingleDynamicJump(unresolvedSwitch, branchDests); } } - /** - * Resolves a single dynamic jump that has previously been created with + /** + * Resolves a single dynamic jump that has previously been created with * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. * * @param lazy - * The lazy state of the jump that is to be resolved. + * The lazy state of the jump that is to be resolved. * @param lookupswitch - * Each dynamic jump is converted to a switch statement. This is the switch statement for the current jump. + * Each dynamic jump is converted to a switch statement. This is the + * switch statement for the current jump. * @param destinations - * A list of known destinations that this dynamic jumps branches to. + * A list of known destinations that this dynamic jumps branches to. */ - private void resolveSingleDynamicJump(UnresolvedJumpInstruction unresolvedJump, Set<Integer> destinations) throws Error { - - if (DBT.VerifyAssertions) DBT._assert(LookupSwitch.conforms(unresolvedJump.instruction)); - + private void resolveSingleDynamicJump( + UnresolvedJumpInstruction unresolvedJump, Set<Integer> destinations) + throws Error { + + if (DBT.VerifyAssertions) + DBT._assert(LookupSwitch.conforms(unresolvedJump.instruction)); + OPT_Instruction lookupswitch = unresolvedJump.instruction; OPT_BranchOperand default_target = LookupSwitch.getDefault(lookupswitch); OPT_Operand value = LookupSwitch.getValue(lookupswitch); - + if (destinations != null) { if ((destinations.size() > 1) || (lookupswitch.getBasicBlock().nextBasicBlockInCodeOrder() != default_target.target @@ -685,24 +792,28 @@ .size() * 3); int match_no = 0; for (int dest_pc : destinations) { - - OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump.lazyStateAtJump, unresolvedJump.type); - LookupSwitch.setMatch(lookupswitch, match_no, new OPT_IntConstantOperand(dest_pc)); - LookupSwitch.setTarget(lookupswitch, match_no, target .makeJumpTarget()); - LookupSwitch.setBranchProfile(lookupswitch, match_no, new OPT_BranchProfileOperand(branchProb)); + OPT_BasicBlock target = resolveBranchTarget(dest_pc, + unresolvedJump.lazyStateAtJump, unresolvedJump.type); + + LookupSwitch.setMatch(lookupswitch, match_no, + new OPT_IntConstantOperand(dest_pc)); + LookupSwitch.setTarget(lookupswitch, match_no, target + .makeJumpTarget()); + LookupSwitch.setBranchProfile(lookupswitch, match_no, + new OPT_BranchProfileOperand(branchProb)); lookupswitch.getBasicBlock().insertOut(target); match_no++; } } else { int dest_pc = destinations.iterator().next(); - - OPT_BasicBlock target = resolveBranchTarget(dest_pc, unresolvedJump.lazyStateAtJump, unresolvedJump.type); + OPT_BasicBlock target = resolveBranchTarget(dest_pc, + unresolvedJump.lazyStateAtJump, unresolvedJump.type); + IfCmp.mutate(lookupswitch, INT_IFCMP, null, value, - new OPT_IntConstantOperand(dest_pc), - OPT_ConditionOperand.EQUAL(), target.makeJumpTarget(), - OPT_BranchProfileOperand.likely()); + new OPT_IntConstantOperand(dest_pc), OPT_ConditionOperand.EQUAL(), + target.makeJumpTarget(), OPT_BranchProfileOperand.likely()); lookupswitch.getBasicBlock().insertOut(target); } } else { @@ -710,44 +821,20 @@ lookupswitch.remove(); } } - - /** - * Append a dynamic jump (a jump whose target address is not known at translation time) to the - * current basic block. - * - * @param targetAddress - * The target address of the jump. - * @param lazyStateAtJump - * The lazy state at the point the jump was added. - * @param branchType - * The type of jump. - */ - public void appendBranch(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType) { - - OPT_BasicBlock fallThrough = createBlockAfterCurrent(); - OPT_Instruction switchInstr; - switchInstr = LookupSwitch.create(LOOKUPSWITCH, targetAddress, null, null, fallThrough.makeJumpTarget(), null, 0); - appendInstruction(switchInstr); - - UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, branchType); - unresolvedDynamicBranches.add(unresolvedInfo); - setCurrentBlock(fallThrough); - appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType); - appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); - } - /** - * Resolves all dynamic jump targets by making sure the respective basic blocks exist. + * Resolves all dynamic jump targets by making sure the respective basic + * blocks exist. */ private void resolveAllDynamicBranchTargets() { for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.get(i); - + + UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches + .get(i); + Laziness lazy = unresolvedSwitch.lazyStateAtJump; Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - + if (branchDests != null) { for (int dest_pc : branchDests) { resolveBranchTarget(dest_pc, lazy, unresolvedSwitch.type); @@ -765,31 +852,29 @@ * instruction to translate) */ public void appendTraceExit(Laziness laziness, OPT_Operand nextPc) { - - //nextBlock = createBlockAfterCurrentNotInCFG(); - + // Copy the value into the register specified by gc.resultReg. - appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(gc.resultReg, VM_TypeReference.Int), nextPc)); + appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand( + gc.resultReg, VM_TypeReference.Int), nextPc)); resolveLaziness(laziness); appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget())); currentBlock.deleteNormalOut(); currentBlock.insertOut(finishBlock); if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfNormalOut() == 1); - - //currentBlock = nextBlock; } /** - * Should the trace be stopped as soon as possible? This function can be used to steer how large a single - * trace may be. Return true if the target size for the trace is about to be or has been exceeded. + * Should the trace be stopped as soon as possible? This function can be used + * to steer how large a single trace may be. Return true if the target size + * for the trace is about to be or has been exceeded. * * @return true => try to stop the trace */ protected boolean shallTraceStop() { if (DBT_Options.singleInstrTranslation && (numberOfInstructions >= 1)) { return true; - } else { + } else { switch (gc.options.getOptLevel()) { case 0: return numberOfInstructions > DBT_Options.instrOpt0; @@ -805,23 +890,23 @@ * Register a branch and link instruction * * @param pc - * the address of the branch instruction + * the address of the branch instruction * @param ret - * the address returned to + * the address returned to * @param dest - * the destination of the branch instruction + * the destination of the branch instruction */ public void registerBranchAndLink(int pc, int ret, int dest) { ps.branchInfo.registerCall(pc, ret, dest); } /** - * Returns a vector of likely branch targets for the branch at address <code>pc</code>. + * Returns a vector of likely branch targets for the branch at address + * <code>pc</code>. * * @param pc - * The location at which the branch occurs. - * @return - * A set of likely destinations for that jump. + * The location at which the branch occurs. + * @return A set of likely destinations for that jump. */ private Set<Integer> getLikelyJumpTargets(int pc) { return ps.branchInfo.getKnownBranchTargets(pc); @@ -832,7 +917,7 @@ * the trace? * * @param pc - * the address of the branch and link instruction + * the address of the branch and link instruction * @return whether the trace should continue */ public boolean traceContinuesAfterBranchAndLink(int pc) { @@ -886,13 +971,14 @@ * Appends a system call to the current basic block. * * @param lazy - * current translation laziness + * current translation laziness * @param pc - * address of system call instruction + * address of system call instruction */ public void appendSystemCall(Laziness lazy, int pc) { - //We need to make sure that all registers contain their latest values, before - //performing the actual system call. + // We need to make sure that all registers contain their latest values, + // before + // performing the actual system call. resolveLaziness(lazy); spillAllRegisters(); @@ -904,7 +990,7 @@ OPT_Operand psRef = gc.makeLocal(1, psTref); Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer for - // doSysCall + // doSysCall Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); Call.setAddress(s, @@ -921,13 +1007,14 @@ * Plant a throw of a bad instruction exception * * @param lazy - * current translation laziness + * current translation laziness * @param pc - * the program counter of the bad instruction + * the program counter of the bad instruction */ public void appendThrowBadInstruction(Laziness lazy, int pc) { - //We need to make sure that all registers contain their latest values, before - //throwing the bad instruction exception. + // We need to make sure that all registers contain their latest values, + // before + // throwing the bad instruction exception. resolveLaziness(lazy); spillAllRegisters(); @@ -946,7 +1033,7 @@ n.position = gc.inlineSequence; n.bcIndex = DBT_Trace.BAD_INSTRUCTION_NEW; appendInstruction(n); - + OPT_Operand psRef = gc.makeLocal(1, psTref); OPT_Instruction c = Call.create(CALL, null, null, null, null, 3); OPT_MethodOperand methOp = OPT_MethodOperand.SPECIAL( @@ -971,8 +1058,7 @@ appendInstruction(t); - appendTraceExit(lazy, - new OPT_IntConstantOperand(0xEBADC0DE)); + appendTraceExit(lazy, new OPT_IntConstantOperand(0xEBADC0DE)); } /** @@ -980,28 +1066,31 @@ * for call * * @param pc - * the address of the branch instruction + * the address of the branch instruction * @param destination - * the register operand holding the destination - * @param code - * a code that can be a hint of the branch type + * the register operand holding the destination + * @param branchType + * The type of the uncaught branch + * @param retAddr + * An optional return address, in case the branch is a call. Otherwise, this value is ignored. */ - private void appendRecordUncaughtBranch(int pc, OPT_RegisterOperand destination, BranchType branchType) { + private void appendRecordUncaughtBranch(int pc, OPT_RegisterOperand destination, BranchType branchType, int retAddr) { // Is it sensible to record this information? if ((gc.options.getOptLevel() > 0) && (DBT_Options.plantUncaughtBranchWatcher)) { // Plant call - OPT_Instruction s = Call.create(CALL, null, null, null, null, 4); + OPT_Instruction s = Call.create(CALL, null, null, null, null, 5); OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL( recordUncaughtBranchMethod.getMemberRef().asMethodReference(), recordUncaughtBranchMethod); OPT_Operand psRef = gc.makeLocal(1, psTref); Call.setParam(s, 0, psRef); // Reference to ps, sets 'this' pointer Call.setParam(s, 1, new OPT_IntConstantOperand(pc)); // Address of branch - // instruction + // instruction Call.setParam(s, 2, destination); // Destination of branch value - Call.setParam(s, 3, new OPT_IntConstantOperand(branchType.ordinal())); // Branch code - // value + Call.setParam(s, 3, new OPT_IntConstantOperand(branchType.ordinal())); // Branch type + Call.setParam(s, 4, new OPT_IntConstantOperand(retAddr)); // return address + // value Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); Call.setAddress(s, new OPT_AddressConstantOperand( @@ -1135,7 +1224,8 @@ * Get/create a temporary validation variable * * @param num - * a hint to allow for reuse of temps across instructions */ + * a hint to allow for reuse of temps across instructions + */ public OPT_RegisterOperand getTempValidation(int num) { if (DBT.VerifyAssertions) DBT._assert(num == 0); @@ -1149,100 +1239,108 @@ return new OPT_RegisterOperand(result, VM_TypeReference.VALIDATION_TYPE); } } - + /** - * Inserts code into the current block that will use the process space's interpreter - * to execute the given instructions. - * + * Inserts ... [truncated message content] |
From: <mic...@us...> - 2007-05-21 14:20:22
|
Revision: 126 http://svn.sourceforge.net/pearcolator/?rev=126&view=rev Author: michael_baer Date: 2007-05-21 07:20:19 -0700 (Mon, 21 May 2007) Log Message: ----------- - Added interface to change memory protections after initial mapping - Implemented system call mprotect - restoring correctly protected memory map after dynamic linking Modified Paths: -------------- src/org/binarytranslator/generic/memory/AutoMappingMemory.java src/org/binarytranslator/generic/memory/ByteAddressedMemory.java src/org/binarytranslator/generic/memory/IntAddressedMemory.java src/org/binarytranslator/generic/memory/Memory.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/loader/elf/ELF_File.java src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java Removed Paths: ------------- src/org/binarytranslator/generic/memory/DebugMemory.java Modified: src/org/binarytranslator/generic/memory/AutoMappingMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-05-21 14:20:19 UTC (rev 126) @@ -2,7 +2,9 @@ import java.io.RandomAccessFile; +import org.binarytranslator.DBT; + /** * A memory implementation that will automatically map pages into memory, as soon * as they are requested. Therefore, this memory never fails with an exception @@ -22,6 +24,8 @@ public AutoMappingMemory(Memory memoryImplementation) { super(AutoMappingMemory.class); + if (DBT.VerifyAssertions) DBT._assert(mem != null); + this.mem = memoryImplementation; } @@ -168,4 +172,9 @@ public void unmap(int addr, int len) { mem.unmap(addr, len); } + + @Override + public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) { + mem.changeProtection(address, len, newRead, newWrite, newExec); + } } Modified: src/org/binarytranslator/generic/memory/ByteAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-05-21 14:20:19 UTC (rev 126) @@ -34,48 +34,32 @@ * </pre> */ public class ByteAddressedMemory extends CallBasedMemory { - /** - * The size of pages - */ + + /** The size of a single page in bytes. */ private static final int PAGE_SIZE = 4096; - /** - * Bits in offset - */ + /** Bits in offset */ private static final int OFFSET_BITS = 12; - /** - * The number of pages - */ + /** The number of pages */ private static final int NUM_PAGES = 0x100000; - /** - * The maximum amount of RAM available - */ - private static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES; + /** The maximum amount of RAM available */ + protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES; - /** - * The memory backing store - */ + /** The memory backing store */ private byte readableMemory[][]; - private byte writableMemory[][]; - private byte executableMemory[][]; - /** - * Do we have more optimal nio mmap operation? - */ + /** Do we have more optimal nio mmap operation? */ private boolean HAVE_java_nio_FileChannelImpl_nio_mmap_file = false; /** * Constructor - used when this is the instatiated class */ public ByteAddressedMemory() { - super(ByteAddressedMemory.class); - readableMemory = new byte[NUM_PAGES][]; - writableMemory = new byte[NUM_PAGES][]; - executableMemory = new byte[NUM_PAGES][]; + this(null); } /** @@ -85,7 +69,7 @@ * the name of the over-riding class */ protected ByteAddressedMemory(Class classType) { - super(classType); + super(classType != null ? classType : ByteAddressedMemory.class); readableMemory = new byte[NUM_PAGES][]; writableMemory = new byte[NUM_PAGES][]; executableMemory = new byte[NUM_PAGES][]; @@ -114,13 +98,11 @@ */ private final int findFreePages(int pages) { starting_page_search: for (int i = 0; i < NUM_PAGES; i++) { - if ((readableMemory[i] == null) && (writableMemory[i] == null) - && (executableMemory[i] == null)) { + if (getPage(i) == null) { int start = i; int end = i + pages; for (; i <= end; i++) { - if ((readableMemory[i] != null) || (writableMemory[i] != null) - || (executableMemory[i] != null)) { + if (getPage(i) != null) { continue starting_page_search; } } @@ -152,39 +134,38 @@ if ((addr % PAGE_SIZE) != 0) { MemoryMapException.unalignedAddress(addr); } + // Create memory int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; byte pages[][] = new byte[num_pages][PAGE_SIZE]; + // Find address if not specified if (addr == 0) { addr = findFreePages(num_pages); } + if (DBT_Options.debugMemory) { - System.err.println("Anonymous mapping: addr=0x" + System.out.println("Anonymous mapping: addr=0x" + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-")); } + // Get page table entry int pte = getPTE(addr); for (int i = 0; i < num_pages; i++) { + // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { + if (getPage(pte + i) != null) { throw new Error("Memory map of already mapped location addr=0x" + Integer.toHexString(addr) + " len=" + len); } + // Allocate pages - if (read) { - readableMemory[pte + i] = pages[i]; - } - if (write) { - writableMemory[pte + i] = pages[i]; - } - if (exec) { - executableMemory[pte + i] = pages[i]; - } + readableMemory[pte + i] = read ? pages[i] : null; + writableMemory[pte + i] = write ? pages[i] : null; + executableMemory[pte + i] = exec ? pages[i] : null; } + return addr; } @@ -210,12 +191,11 @@ if ((addr % PAGE_SIZE) != 0) { MemoryMapException.unalignedAddress(addr); } + // Check file offset is page aligned - /* if ((offset % PAGE_SIZE) != 0) { MemoryMapException.unalignedFileOffset(offset); } - */ // Calculate number of pages int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; @@ -224,7 +204,7 @@ addr = findFreePages(num_pages); } if (DBT_Options.debugMemory) { - System.err.println("Mapping file " + file + " offset=" + offset + System.out.println("Mapping file " + file + " offset=" + offset + " addr=0x" + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-")); } @@ -237,9 +217,7 @@ file.seek(offset); for (int i = 0; i < num_pages; i++) { // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { + if (getPage(pte + i) != null) { throw new Error("Memory map of already mapped location addr=0x" + Integer.toHexString(addr) + " len=" + len); } @@ -252,25 +230,19 @@ } else { file.read(page); } - if (read) { - readableMemory[pte + i] = page; - } - if (write) { - writableMemory[pte + i] = page; - } - if (exec) { - executableMemory[pte + i] = page; - } + + readableMemory[pte + i] = read ? page : null; + writableMemory[pte + i] = write ? page : null; + executableMemory[pte + i] = exec ? page : null; } } else { for (int i = 0; i < num_pages; i++) { // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { + if (getPage(pte + i) != null) { throw new Error("Memory map of already mapped location addr=0x" + Integer.toHexString(addr) + " len=" + len); } + // Allocate page if (read && write) { readableMemory[pte + i] = file.getChannel().map( @@ -303,6 +275,29 @@ throw new Error(e); } } + + /** + * Returns the page currently mapped at the given page table entry. + * + * @param pte + * The page table entry, for which a page is to be retrieved. + * @return + * The page mapped at the given page table entry or null, if no page is currently mapped + * to that entry. + */ + private byte[] getPage(int pte) { + + if (readableMemory[pte] != null) + return readableMemory[pte]; + + if (writableMemory[pte] != null) + return writableMemory[pte]; + + if (executableMemory[pte] != null) + return executableMemory[pte]; + + return null; + } /** * Unmap a page of memory @@ -314,20 +309,14 @@ */ public void unmap(int addr, int len) { for (int i = 0; i < len; i += PAGE_SIZE) { - boolean unmapped_something = false; - if (readableMemory[getPTE(addr + i)] != null) { - readableMemory[getPTE(addr + i)] = null; - unmapped_something = true; + + int pte = getPTE(addr + i); + if (getPage(pte) != null) { + readableMemory[pte] = null; + writableMemory[pte] = null; + executableMemory[pte] = null; } - if (writableMemory[getPTE(addr + i)] != null) { - writableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (executableMemory[getPTE(addr + i)] != null) { - executableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (unmapped_something == false) { + else { throw new Error("Unmapping memory that's not mapped addr=0x" + Integer.toHexString(addr) + " len=" + len); } @@ -340,9 +329,7 @@ * @return true => memory is mapped */ public boolean isMapped(int addr) { - return ((readableMemory[getPTE(addr)] != null) || - (writableMemory[getPTE(addr)] != null) || - (executableMemory[getPTE(addr)] != null)); + return getPage(getPTE(addr)) != null; } /** @@ -536,4 +523,23 @@ throw new SegmentationFault(addr); } } + + @Override + public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) { + + while (len > 0) { + int pte = getPTE(address); + byte[] page = getPage(pte); + + if (page == null) + throw new SegmentationFault(address); + + readableMemory[pte] = newRead ? page : null; + writableMemory[pte] = newWrite ? page : null; + executableMemory[pte] = newExec ? page : null; + + address += PAGE_SIZE; + len -= PAGE_SIZE; + } + } } Deleted: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-05-21 14:20:19 UTC (rev 126) @@ -1,598 +0,0 @@ -/* - * This file is part of binarytranslator.org. The binarytranslator.org - * project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright Ian Rogers, The University of Manchester 2003-2006 - */ -package org.binarytranslator.generic.memory; - -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; - -import org.binarytranslator.DBT_Options; -import org.binarytranslator.generic.decoder.AbstractCodeTranslator; -import org.jikesrvm.compilers.opt.ir.OPT_Operand; -import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; - -/** - * A copy of byte-addressed memory, that does not allow the translation of accesses to bytecode. - * This is stricly for debugging purposes, as it allows the Pearcolator interpreter to be executed - * in a windows environment. - */ -public class DebugMemory extends Memory { - /** - * The size of pages - */ - private static final int PAGE_SIZE = 4096; - - /** - * Bits in offset - */ - private static final int OFFSET_BITS = 12; - - /** - * The number of pages - */ - private static final int NUM_PAGES = 0x100000; - - /** - * The maximum amount of RAM available - */ - protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES; - - /** - * The memory backing store - */ - private byte readableMemory[][]; - - private byte writableMemory[][]; - - private byte executableMemory[][]; - - /** - * Do we have more optimal nio mmap operation? - */ - private boolean HAVE_java_nio_FileChannelImpl_nio_mmap_file = false; - - /** - * Constructor - used when this is the instatiated class - */ - public DebugMemory() { - readableMemory = new byte[NUM_PAGES][]; - writableMemory = new byte[NUM_PAGES][]; - executableMemory = new byte[NUM_PAGES][]; - } - - /** - * Return the offset part of the address - */ - private static final int getOffset(int address) { - return address & (PAGE_SIZE - 1); - } - - /** - * Return the page table entry part of the address - */ - private static final int getPTE(int address) { - return address >>> OFFSET_BITS; - } - - /** - * Ensure memory between start and end is mapped - * @param startAddr starting address for mapped memory - * @param endAddr ending address for mapped memory - */ - @Override - public void ensureMapped(int startAddr, int endAddr) throws MemoryMapException { - startAddr = truncateToPage(startAddr); - endAddr = truncateToNextPage(endAddr); - for (;startAddr < endAddr; startAddr += getPageSize()) { - if (!isMapped(startAddr)) { - map(startAddr, getPageSize(), true, true, true); - } - } - } - - /** - * Find free consecutive pages - * - * @param pages - * the number of pages required - * @return the address found - */ - private final int findFreePages(int pages) { - starting_page_search: for (int i = 0; i < NUM_PAGES; i++) { - if ((readableMemory[i] == null) && (writableMemory[i] == null) - && (executableMemory[i] == null)) { - int start = i; - int end = i + pages; - for (; i <= end; i++) { - if ((readableMemory[i] != null) || (writableMemory[i] != null) - || (executableMemory[i] != null)) { - continue starting_page_search; - } - } - return start << OFFSET_BITS; - } - } - throw new Error( - "No mappable consecutive pages found for an anonymous map of size" - + (pages * PAGE_SIZE)); - } - - /** - * Map an anonymous page of memory - * - * @param addr - * the address to map or NULL if don't care - * @param len - * the amount of memory to map - * @param read - * is the page readable - * @param write - * is the page writable - * @param exec - * is the page executable - * @return - * The start address of the mapped memory. - */ - public int map(int addr, int len, boolean read, boolean write, boolean exec) - throws MemoryMapException { - // Check that the address is page aligned - if ((addr % PAGE_SIZE) != 0) { - MemoryMapException.unalignedAddress(addr); - - /* - // if it is not, truncate the address down to the next page boundary and - // start mapping from there - int validPageCount = addr / PAGE_SIZE; - int oldStartAddress = addr; - addr = validPageCount * PAGE_SIZE; - - if (DBT.VerifyAssertions) - DBT._assert(oldStartAddress > addr); - - // we have to map more more memory now to reach the same end address - len += (oldStartAddress - addr);*/ - } - - // Create memory - int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; - byte pages[][] = new byte[num_pages][PAGE_SIZE]; - // Find address if not specified - if (addr == 0) { - addr = findFreePages(num_pages); - } - if (DBT_Options.debugMemory) { - System.err.println("Anonymous mapping: addr=0x" - + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -") - + (write ? "w" : "-") + (exec ? "x" : "-")); - } - // Get page table entry - int pte = getPTE(addr); - for (int i = 0; i < num_pages; i++) { - // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { - throw new Error("Memory map of already mapped location addr=0x" - + Integer.toHexString(addr) + " len=" + len); - } - // Allocate pages - if (read) { - readableMemory[pte + i] = pages[i]; - } - if (write) { - writableMemory[pte + i] = pages[i]; - } - if (exec) { - executableMemory[pte + i] = pages[i]; - } - } - return addr; - } - - /** - * Map a page of memory from file - * - * @param file - * the file map in from - * @param addr - * the address to map or NULL if don't care - * @param len - * the amount of memory to map - * @param read - * is the page readable - * @param write - * is the page writable - * @param exec - * is the page executable - */ - public int map(RandomAccessFile file, long offset, int addr, int len, - boolean read, boolean write, boolean exec) throws MemoryMapException { - // Check address is page aligned - if ((addr % PAGE_SIZE) != 0) { - MemoryMapException.unalignedAddress(addr); - } - - // Calculate number of pages - int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; - - // Find address if not specified - /*if (addr == 0) { - addr = findFreePages(num_pages); - }*/ - - if (DBT_Options.debugMemory) { - System.err.println("Mapping file " + file + " offset=" + offset - + " addr=0x" + Integer.toHexString(addr) + " len=" + len - + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-")); - } - try { - // Get page table entry - int pte = getPTE(addr); - // Can we optimise the reads to use mmap? - if (!HAVE_java_nio_FileChannelImpl_nio_mmap_file) { - // Sub-optimal - file.seek(offset); - for (int i = 0; i < num_pages; i++) { - - byte page[]; - - // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { - - /*page = readableMemory[pte + i]; - - if (page == null) - page = writableMemory[pte + i]; - - if (page == null) - page = executableMemory[pte + i]; - - if (DBT.VerifyAssertions) DBT._assert(page != null);*/ - - throw new Error("Memory map of already mapped location addr=0x" - + Integer.toHexString(addr) + " len=" + len); - } - else - page = new byte[PAGE_SIZE]; //Allocate page - - if (i == 0) { // first read, start from offset upto a page length - file.read(page, getOffset(addr), PAGE_SIZE - getOffset(addr)); - } else if (i == (num_pages - 1)) { // last read - file.read(page, 0, ((len - getOffset(addr)) % PAGE_SIZE)); - } else { - file.read(page); - } - - if (read) { - readableMemory[pte + i] = page; - } - if (write) { - writableMemory[pte + i] = page; - } - if (exec) { - executableMemory[pte + i] = page; - } - } - } else { - for (int i = 0; i < num_pages; i++) { - // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { - throw new Error("Memory map of already mapped location addr=0x" - + Integer.toHexString(addr) + " len=" + len); - } - - System.out.println("Unexpected page mapping!!!!!!!!!!!!!!!!!!!!"); - - byte[] page; - - if (write) - page = file.getChannel().map(FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE), PAGE_SIZE).array(); - else - page = file.getChannel().map(FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE), PAGE_SIZE).array(); - - if (write) { - writableMemory[pte + i] = page; - } - - if (read) { - readableMemory[pte + i] = page; - } - - if (exec) { - executableMemory[pte + i] = page; - } - } - } - return addr; - } catch (java.io.IOException e) { - throw new Error(e); - } - } - - /** - * Unmap a page of memory - * - * @param addr - * the address to unmap - * @param len - * the amount of memory to unmap - */ - public void unmap(int addr, int len) { - for (int i = 0; i < len; i += PAGE_SIZE) { - boolean unmapped_something = false; - if (readableMemory[getPTE(addr + i)] != null) { - readableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (readableMemory[getPTE(addr + i)] != null) { - writableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (readableMemory[getPTE(addr + i)] != null) { - executableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (unmapped_something == false) { - throw new Error("Unmapping memory that's not mapped addr=0x" - + Integer.toHexString(addr) + " len=" + len); - } - } - } - - /** - * Is the given address mapped into memory? - * @param addr to check - * @return true => memory is mapped - */ - public boolean isMapped(int addr) { - return ((readableMemory[getPTE(addr)] != null) || - (writableMemory[getPTE(addr)] != null) || - (executableMemory[getPTE(addr)] != null)); - } - - /** - * @return the size of a page - */ - public int getPageSize() { - return PAGE_SIZE; - } - - /** - * Is the given address aligned on a page boundary? - * - * @param addr - * the address to check - * @return whether the address is aligned - */ - public boolean isPageAligned(int addr) { - return (addr % PAGE_SIZE) == 0; - } - - /** - * Make the given address page aligned to the page beneath it - * - * @param addr - * the address to truncate - * @return the truncated address - */ - public int truncateToPage(int addr) { - return (addr >> OFFSET_BITS) << OFFSET_BITS; - } - - /** - * Make the given address page aligned to the page above it - * - * @param addr - * the address to truncate - * @return the truncated address - */ - public int truncateToNextPage(int addr) { - return ((addr + PAGE_SIZE - 1) >> OFFSET_BITS) << OFFSET_BITS; - } - - /** - * Perform a byte load where the sign extended result fills the return value - * - * @param addr - * the address of the value to load - * @return the sign extended result - */ - final public int loadSigned8(int addr) { - try { - if (DBT_Options.debugMemory) - System.err.println("LoadS8 address: 0x" + Integer.toHexString(addr) - + " val: " + readableMemory[getPTE(addr)][getOffset(addr)]); - return readableMemory[getPTE(addr)][getOffset(addr)]; - } catch (NullPointerException e) { - System.err.println("Null pointer exception at address: 0x" - + Integer.toHexString(addr)); - throw e; - } - } - - /** - * Perform a byte load where the zero extended result fills the return value - * - * @param addr - * the address of the value to load - * @return the zero extended result - */ - final public int loadUnsigned8(int addr) { - try { - if (DBT_Options.debugMemory) - System.err.println("LoadU8 address: 0x" + Integer.toHexString(addr) - + " val: " + readableMemory[getPTE(addr)][getOffset(addr)]); - return readableMemory[getPTE(addr)][getOffset(addr)] & 0xFF; - } catch (NullPointerException e) { - System.err.println("Null pointer exception at address: 0x" - + Integer.toHexString(addr)); - throw e; - } - } - - /** - * Perform a 16bit load where the sign extended result fills the return value - * - * @param addr - * the address of the value to load - * @return the sign extended result - */ - public int loadSigned16(int addr) { - return (loadSigned8(addr + 1) << 8) | loadUnsigned8(addr); - } - - /** - * Perform a 16bit load where the zero extended result fills the return value - * - * @param addr - * the address of the value to load - * @return the zero extended result - */ - public int loadUnsigned16(int addr) { - return (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr); - } - - /** - * Perform a 32bit load - * - * @param addr - * the address of the value to load - * @return the result - */ - public int load32(int addr) { - return (loadUnsigned8(addr + 3) << 24) | (loadUnsigned8(addr + 2) << 16) - | (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr); - } - - /** - * Perform a 8bit load from memory that must be executable - * - * @param addr - * the address of the value to load - * @return the result - */ - public int loadInstruction8(int addr) { - if (DBT_Options.debugMemory) - System.err.println("LoadI8 address: 0x" + Integer.toHexString(addr) - + " val: " + executableMemory[getPTE(addr)][getOffset(addr)]); - return executableMemory[getPTE(addr)][getOffset(addr)] & 0xFF; - } - - /** - * Perform a 32bit load from memory that must be executable - * - * @param addr - * the address of the value to load - * @return the result - */ - public int loadInstruction32(int addr) { - return (loadInstruction8(addr + 3) << 24) - | (loadInstruction8(addr + 2) << 16) - | (loadInstruction8(addr + 1) << 8) | loadInstruction8(addr); - } - - /** - * Perform a byte store - * - * @param value - * the value to store - * @param addr - * the address of where to store - */ - public final void store8(int addr, int value) { - if (DBT_Options.debugMemory) - System.err.println("Store8 address: 0x" + Integer.toHexString(addr) - + " val: 0x" + Integer.toHexString(value & 0xFF)); - writableMemory[getPTE(addr)][getOffset(addr)] = (byte) value; - } - - /** - * Perform a 16bit store - * - * @param value - * the value to store - * @param addr - * the address of where to store - */ - public void store16(int addr, int value) { - store8(addr + 1, value >> 8); - store8(addr, value); - } - - /** - * Perform a 32bit store - * - * @param value - * the value to store - * @param addr - * the address of where to store - */ - public void store32(int addr, int value) { - store8(addr + 3, value >> 24); - store8(addr + 2, value >> 16); - store8(addr + 1, value >> 8); - store8(addr, value); - } - - @Override - public void initTranslate(AbstractCodeTranslator helper) { - throw new UnsupportedOperationException(); - } - - @Override - public void translateLoad32(OPT_Operand addr, OPT_RegisterOperand dest) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateLoadSigned16(OPT_Operand addr, OPT_RegisterOperand dest) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateLoadSigned8(OPT_Operand addr, OPT_RegisterOperand dest) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateLoadUnsigned16(OPT_Operand addr, OPT_RegisterOperand dest) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateLoadUnsigned8(OPT_Operand addr, OPT_RegisterOperand dest) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateStore16(OPT_Operand addr, OPT_Operand src) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateStore32(OPT_Operand addr, OPT_Operand src) { - throw new UnsupportedOperationException(); - - } - - @Override - public void translateStore8(OPT_Operand addr, OPT_Operand src) { - throw new UnsupportedOperationException(); - - } -} Modified: src/org/binarytranslator/generic/memory/IntAddressedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-05-21 14:20:19 UTC (rev 126) @@ -12,6 +12,7 @@ import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; +import org.binarytranslator.generic.fault.SegmentationFault; import org.jikesrvm.VM_Configuration; /** @@ -65,10 +66,7 @@ * Constructor - used when this is the instatiated class */ public IntAddressedMemory() { - super(IntAddressedMemory.class); - readableMemory = new int[NUM_PAGES][]; - writableMemory = new int[NUM_PAGES][]; - executableMemory = new int[NUM_PAGES][]; + this(null); } /** @@ -78,7 +76,7 @@ * the type of the over-riding class */ protected IntAddressedMemory(Class classType) { - super(classType); + super(classType != null ? classType : IntAddressedMemory.class); readableMemory = new int[NUM_PAGES][]; writableMemory = new int[NUM_PAGES][]; executableMemory = new int[NUM_PAGES][]; @@ -104,9 +102,7 @@ * @return true => memory is mapped */ public boolean isMapped(int addr) { - return ((readableMemory[getPTE(addr)] != null) || - (writableMemory[getPTE(addr)] != null) || - (executableMemory[getPTE(addr)] != null)); + return getPage(getPTE(addr)) != null; } /** @@ -158,13 +154,11 @@ */ private final int findFreePages(int pages) { starting_page_search: for (int i = 0; i < NUM_PAGES; i++) { - if ((readableMemory[i] == null) && (writableMemory[i] == null) - && (executableMemory[i] == null)) { + if (getPage(i) == null) { int start = i; int end = i + pages; for (; i <= end; i++) { - if ((readableMemory[i] != null) || (writableMemory[i] != null) - || (executableMemory[i] != null)) { + if (getPage(i) != null) { continue starting_page_search; } } @@ -224,27 +218,61 @@ int pte = getPTE(addr); for (int i = 0; i < num_pages; i++) { // Check pages aren't already allocated - if ((readableMemory[pte + i] != null) - || (writableMemory[pte + i] != null) - || (executableMemory[pte + i] != null)) { + if (getPage(pte + i) != null) { throw new Error("Memory map of already mapped location addr=0x" + Integer.toHexString(addr) + " len=" + len); } - // Allocate pages - if (read) { - readableMemory[pte + i] = pages[i]; - } - if (write) { - writableMemory[pte + i] = pages[i]; - } - if (exec) { - executableMemory[pte + i] = pages[i]; - } + + readableMemory[pte+i] = read ? pages[i] : null; + writableMemory[pte+i] = write ? pages[i] : null; + executableMemory[pte+i] = exec ? pages[i] : null; } return addr; } /** + * Returns the page currently mapped at the given page table entry. + * + * @param pte + * The page table entry, for which a page is to be retrieved. + * @return + * The page mapped at the given page table entry or null, if no page is currently mapped + * to that entry. + */ + private int[] getPage(int pte) { + + if (readableMemory[pte] != null) + return readableMemory[pte]; + + if (writableMemory[pte] != null) + return writableMemory[pte]; + + if (executableMemory[pte] != null) + return executableMemory[pte]; + + return null; + } + + @Override + public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) { + + while (len > 0) { + int pte = getPTE(address); + int[] page = getPage(pte); + + if (page == null) + throw new SegmentationFault(address); + + readableMemory[pte] = newRead ? page : null; + writableMemory[pte] = newWrite ? page : null; + executableMemory[pte] = newExec ? page : null; + + address += PAGE_SIZE; + len -= PAGE_SIZE; + } + } + + /** * Read an int from RandomAccessFile ensuring that a byte swap isn't performed * * @param file @@ -292,20 +320,19 @@ + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-")); } addr = map(addr, len, read, write, exec); - try { + + try { file.seek(offset); for (int i = 0; i < len; i += 4) { - int value = readInt(file); - if (read) { - readableMemory[getPTE(addr + i)][getOffset(addr + i)] = value; - } else if (write) { - writableMemory[getPTE(addr + i)][getOffset(addr + i)] = value; - } else if (exec) { - executableMemory[getPTE(addr + i)][getOffset(addr + i)] = value; - } + + int[] page = getPage(getPTE(addr + i)); + page[getOffset(addr + i)] = readInt(file); } + return addr; - } catch (java.io.IOException e) { + + } + catch (java.io.IOException e) { throw new Error(e); } } @@ -320,20 +347,15 @@ */ public final void unmap(int addr, int len) { for (int i = 0; i < len; i += PAGE_SIZE) { - boolean unmapped_something = false; - if (readableMemory[getPTE(addr + i)] != null) { - readableMemory[getPTE(addr + i)] = null; - unmapped_something = true; + + int pte = getPTE(addr + i); + + if (getPage(pte) != null) { + readableMemory[pte] = null; + writableMemory[pte] = null; + executableMemory[pte] = null; } - if (readableMemory[getPTE(addr + i)] != null) { - writableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (readableMemory[getPTE(addr + i)] != null) { - executableMemory[getPTE(addr + i)] = null; - unmapped_something = true; - } - if (unmapped_something == false) { + else { throw new Error("Unmapping memory that's not mapped addr=0x" + Integer.toHexString(addr) + " len=" + len); } Modified: src/org/binarytranslator/generic/memory/Memory.java =================================================================== --- src/org/binarytranslator/generic/memory/Memory.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/memory/Memory.java 2007-05-21 14:20:19 UTC (rev 126) @@ -43,6 +43,26 @@ public abstract int map(RandomAccessFile file, long offset, int addr, int len, boolean read, boolean write, boolean exec) throws MemoryMapException; + + /** + * Changes the protection of a region of memory. Note that this function only guarantees + * protection to be changed on a page level. Therefore, if <code>address</code> is not page + * aligned or len is not a muliple of {@link #getPageSize()}, then the function may + * change the protection of a larger memory range than initally requested. + * + * @param address + * The start address of a memory block, whose protection shall be changed. + * @param len + * The length of the memory block. + * @param newRead + * Set to true to allow reading from this memory block, false otherwise. + * @param newWrite + * Set to true to allow writing to this memory block, false otherwise. + * @param newExec + * Set to true to allow executing code from this memory block, false otherwise. + */ + public abstract void changeProtection(int address, int len, boolean newRead, + boolean newWrite, boolean newExec); /** * Unmap a page of memory Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-21 14:20:19 UTC (rev 126) @@ -31,6 +31,7 @@ import org.binarytranslator.generic.os.abi.linux.filesystem.ReadonlyFilesystem; import org.binarytranslator.generic.os.abi.linux.filesystem.TempFileSystem; import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider.FileMode; +import org.binarytranslator.generic.os.process.ProcessSpace; /** * Linux system call handling class @@ -206,9 +207,8 @@ * Unknown System Call */ private class UnknownSystemCall extends SystemCall { - /** - * Handle a system call - */ + + @Override public void doSysCall() { if (!DBT_Options.unimplementedSystemCallsFatal) { src.setSysCallError(errno.ENOSYS); @@ -223,6 +223,8 @@ * Exit system call */ public class SysExit extends SystemCall { + + @Override public void doSysCall() { int status = arguments.nextInt(); System.exit(status); @@ -233,6 +235,8 @@ * Read from a file */ public class SysRead extends SystemCall { + + @Override public void doSysCall() { int fd = arguments.nextInt(); int buf = arguments.nextInt(); @@ -265,6 +269,8 @@ * Write to a file */ public class SysWrite extends SystemCall { + + @Override public void doSysCall() { int fd = arguments.nextInt(); int buf = arguments.nextInt(); @@ -296,6 +302,8 @@ * Write data into multiple buffers */ public class SysWriteV extends SystemCall { + + @Override public void doSysCall() { int fd = arguments.nextInt(); int vector = arguments.nextInt(); @@ -334,6 +342,8 @@ } public class SysOpen extends SystemCall { + + @Override public void doSysCall() { int pathname = arguments.nextInt(); int flags = arguments.nextInt(); @@ -406,6 +416,8 @@ } public class SysClose extends SystemCall { + + @Override public void doSysCall() { int fd = arguments.nextInt(); @@ -421,30 +433,40 @@ } public class SysGetEUID extends SystemCall { + + @Override public void doSysCall() { src.setSysCallReturn(DBT_Options.UID); } } public class SysGetUID extends SystemCall { + + @Override public void doSysCall() { src.setSysCallReturn(DBT_Options.UID); } } public class SysGetEGID extends SystemCall { + + @Override public void doSysCall() { src.setSysCallReturn(DBT_Options.GID); } } public class SysGetGID extends SystemCall { + + @Override public void doSysCall() { src.setSysCallReturn(DBT_Options.GID); } } public class SysBrk extends SystemCall { + + @Override public void doSysCall() { int newBrk = arguments.nextInt(); if (newBrk != 0) { @@ -458,6 +480,8 @@ } public class SysFstat64 extends SystemCall { + + @Override public void doSysCall() { int fd = arguments.nextInt(); int structAddr = arguments.nextInt(); @@ -506,6 +530,8 @@ } public class SysFcntl64 extends SystemCall { + + @Override public void doSysCall() { // This is complicated so fudge it for now. int fd = arguments.nextInt(); @@ -519,6 +545,8 @@ } public class SysUname extends SystemCall { + + @Override public void doSysCall() { // Simple uname support int addr = arguments.nextInt(); @@ -556,6 +584,8 @@ } public class SysMmap extends SystemCall { + + @Override public void doSysCall() { int addr = arguments.nextInt(); @@ -589,8 +619,27 @@ } } } + + public class SysMRemap extends SystemCall { + @Override + public void doSysCall() { + int addr = arguments.nextInt(); + int len = arguments.nextInt(); + int prot = arguments.nextInt(); + + ProcessSpace ps = src.getProcessSpace(); + ps.memory.changeProtection(addr, len, (prot & mman.PROT_READ) != 0, + (prot & mman.PROT_WRITE) != 0, (prot & mman.PROT_EXEC) != 0); + + src.setSysCallReturn(0); + } + + } + public class SysMunmap extends SystemCall { + + @Override public void doSysCall() { int start = arguments.nextInt(); @@ -602,6 +651,8 @@ } public class SysExitGroup extends SystemCall { + + @Override public void doSysCall() { // For now, equivalent to SysExit System.exit(arguments.nextInt()); Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_File.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-05-21 14:20:19 UTC (rev 126) @@ -29,9 +29,7 @@ /** Header of ELF file */ private Header header; - /** - * Program segment headers - */ + /** Program segment headers */ private SegmentHeader segmentHeaders[]; /** @@ -1409,7 +1407,7 @@ * @param write is segment writable * @param exec is segment executable */ - public void createSegment(Memory memory, RandomAccessFile file, + private void createSegment(Memory memory, RandomAccessFile file, long offset, int address, int filesize, int memsize, boolean read, boolean write, boolean exec) throws MemoryMapException { // Sanity check @@ -1439,12 +1437,14 @@ alignedOffset = offset - delta; alignedFilesize = filesize + delta; } - memory.map(file, alignedOffset, alignedAddress, alignedFilesize, read, - write, exec); + + memory.map(file, alignedOffset, alignedAddress, alignedFilesize, read, write, exec); + // Do we need to map in some blank pages at the end of the segment? if (filesize < memsize) { alignedAddress = memory.truncateToNextPage(address + filesize); - memory.map(alignedAddress, memsize - filesize, read, write, exec); + int delta = alignedAddress - (address + filesize); + memory.map(alignedAddress, memsize - filesize - delta, read, write, exec); } } } Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-05-21 14:20:19 UTC (rev 126) @@ -81,7 +81,7 @@ System.out.println("ELF has segments:"); for (ELF_File.SegmentHeader segment : segments) { - System.out.println(" - " + segment.toString()); + System.out.println(" " + segment.toString()); } } Modified: src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-05-19 15:21:09 UTC (rev 125) +++ src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-05-21 14:20:19 UTC (rev 126) @@ -29,7 +29,7 @@ private LinkedList<SharedObject> libraries = new LinkedList<SharedObject>(); /** A list of the star addres of all init routines, that we're supposed to execute. */ - public LinkedList<Integer> initMethods = new LinkedList<Integer>(); + private LinkedList<Integer> initMethods = new LinkedList<Integer>(); /** The address of the memory block that is going to be allocated to the next library*/ private int nextMemoryBlock = 1024*1024*1024; //start mapping libraries at 1GB (0x40000000) @@ -59,6 +59,11 @@ /** Other libraries, that this library depends upon. */ private SharedObject[] dependencies = null; + /** + * A list of segments that have additionally received write protection to allow + * relocations within the segment, although the segment was originally write protected. */ + private LinkedList<SegmentHeader> removedWriteProtection = new LinkedList<SegmentHeader>(); + public SharedObject(String filename) { this.filename = filename; this.hasFixedLoadOffset = false; @@ -135,6 +140,15 @@ //relocate all dynamic libraries relocateLibRecursively(programfile); + + //Add write protections to all segments from which we removed it during relocation + for (SharedObject lib : libraries) { + for (SegmentHeader segment : lib.removedWriteProtection) { + boolean read = (segment.p_flags & SegmentHeader.PF_R) != 0; + boolean exec = (segment.p_flags & SegmentHeader.PF_X) != 0; + ps.memory.changeProtection(segment.p_vaddr + lib.loadedAt, segment.p_filesz, read, false, exec); + } + } //Call the init routines that were registered by the different libraries callInitRoutines(); @@ -325,7 +339,7 @@ */ private void loadSingleLibrary(SharedObject lib) { - if (DBT.VerifyAssertions) DBT._assert(lib.loadedAt == 0); + if (DBT.VerifyAssertions) DBT._assert(lib.loadedAt == 0 || lib.hasFixedLoadOffset()); if (!lib.hasFixedLoadOffset()) { // load the library to the next available address @@ -340,15 +354,24 @@ //the highest offset from nextMemoryBlock that this shared object uses long highestUsedAddress = 1; + + if (DBT_Options.debugLoader) + System.out.println(String.format("Loading Shared Object: %s to 0x%x", lib, lib.loadedAt)); for (int i = 0; i < segments.length; i++) { + + SegmentHeader segment = segments[i]; + if (DBT_Options.debugLoader) System.out.println(" Loading Segment: " + segment); - //TODO: This is only a hack. We are making this segment writeable, because we need to relocate within it... - if (needRelocText) - segments[i].p_flags |= ELF_File.SegmentHeader.PF_W; + if (needRelocText && (segment.p_flags & ELF_File.SegmentHeader.PF_W) == 0) { + //We are making this segment writeable, because we need to relocate inside of it. + //Remember that segment to remove the write protection later on + lib.removedWriteProtection.add(segment); + segment.p_flags |= ELF_File.SegmentHeader.PF_W; + } //create the actual segment - segments[i].create(ps, lib.loadedAt); + segment.create(ps, lib.loadedAt); long thisAddress = segments[i].p_vaddr; thisAddress += segments[i].p_memsz; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-19 15:21:07
|
Revision: 125 http://svn.sourceforge.net/pearcolator/?rev=125&view=rev Author: michael_baer Date: 2007-05-19 08:21:09 -0700 (Sat, 19 May 2007) Log Message: ----------- Added file missing from previous commit Added Paths: ----------- src/org/binarytranslator/generic/os/loader/elf/RuntimeLinker.java Added: src/org/binarytranslator/generic/os/loader/elf/RuntimeLinker.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/RuntimeLinker.java (rev 0) +++ src/org/binarytranslator/generic/os/loader/elf/RuntimeLinker.java 2007-05-19 15:21:09 UTC (rev 125) @@ -0,0 +1,35 @@ +package org.binarytranslator.generic.os.loader.elf; + +import java.io.IOException; + +import org.binarytranslator.arch.arm.os.process.loader.ARM_RuntimeLinker; +import org.binarytranslator.generic.os.process.ProcessSpace; + +public abstract class RuntimeLinker { + + /** + * This function is the main entry point into the dynamic linker and will steer the whole + * linking process. + */ + public abstract void link() throws IOException; + + /** + * Creates a new ELF runtime linker for dynamically linking the file loaded by the + * <code>loader</code>. + * @param ps + * The process space that we're loading the file to. + * @param loader + * The loader that is in need of a runtime linker. + * @return + * A runtime linker instance. + */ + public static RuntimeLinker create(ProcessSpace ps, ELF_Loader loader) throws Error { + switch (loader.getISA()) { + case ARM: + return new ARM_RuntimeLinker(ps, loader); + + default: + throw new Error("Unable to create a runtime linker for the platform " + loader.getISA()); + } + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |