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-05-19 15:20:18
|
Revision: 124 http://svn.sourceforge.net/pearcolator/?rev=124&view=rev Author: michael_baer Date: 2007-05-19 08:20:17 -0700 (Sat, 19 May 2007) Log Message: ----------- - Introduced a working version of dynamic linking for ARM Modified Paths: -------------- src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/os/loader/Loader.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/image/ImageLoader.java src/org/binarytranslator/generic/os/process/ProcessSpace.java Added Paths: ----------- src/org/binarytranslator/arch/arm/os/process/loader/ src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java Removed Paths: ------------- src/org/binarytranslator/generic/os/loader/elf/RuntimeLinker.java Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/Main.java 2007-05-19 15:20:17 UTC (rev 124) @@ -89,8 +89,13 @@ ps = loader.readBinary(DBT_Options.executableFile); } catch (java.io.IOException e) { - throw new Error("Error accessing file: " + args[0], e); + System.err.println("Error accesing file: " + args[0] + ". " + e.getMessage()); + return; } + catch (Error e) { + System.err.println(e.getMessage()); + return; + } report("Sucessfully created process."); Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-05-19 15:20:17 UTC (rev 124) @@ -79,8 +79,8 @@ } @Override - public void initialise(Loader loader, int pc, int brk) { - registers.set(ARM_Registers.PC, pc); + public void initialise(Loader loader) { + registers.set(ARM_Registers.PC, loader.getEntryPoint()); } } Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-05-19 15:20:17 UTC (rev 124) @@ -46,9 +46,9 @@ } @Override - public void initialise(Loader loader, int pc, int brk) { - registers.set(ARM_Registers.PC, pc); - sysCalls.initialize(brk); + public void initialise(Loader loader) { + registers.set(ARM_Registers.PC, loader.getEntryPoint()); + sysCalls.initialize(loader.getBrk()); // initialize the stack auxVector = new int[] { Added: src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java 2007-05-19 15:20:17 UTC (rev 124) @@ -0,0 +1,139 @@ +package org.binarytranslator.arch.arm.os.process.loader; + +import java.io.IOException; + +import org.binarytranslator.DBT; +import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace; +import org.binarytranslator.arch.arm.os.process.ARM_Registers; +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.os.loader.elf.ELF_File; +import org.binarytranslator.generic.os.loader.elf.ELF_Loader; +import org.binarytranslator.generic.os.loader.elf.JavaRuntimeLinker; +import org.binarytranslator.generic.os.loader.elf.ELF_File.RelocationTable; +import org.binarytranslator.generic.os.loader.elf.ELF_File.StringTable; +import org.binarytranslator.generic.os.loader.elf.ELF_File.SymbolTable; +import org.binarytranslator.generic.os.process.ProcessSpace; + +public class ARM_RuntimeLinker extends JavaRuntimeLinker { + + /** Introduce symbolic names for the different ARM relocation types. */ + private final static int R_ARM_ABS32 = 2; + private final static int R_ARM_GLOB_DAT = 21; + private final static int R_ARM_JUMP_SLOT = 22; + private final static int R_ARM_RELATIVE = 23; + + public ARM_RuntimeLinker(ProcessSpace ps, ELF_Loader loader) { + super(ps, loader); + + //TODO: Introduce some kind of class for ELF library managements + String libDir = "C:\\0Dateien\\University of Manchester\\MSc Thesis\\ARM Executables\\Dynamically Linked\\Hello World\\"; + libNames.put("libc.so.6", libDir + "libc-2.2.5.so"); + libNames.put("ld-linux.so.2", libDir + "ld-linux.so.2"); + } + + @Override + protected void relocate(SharedObject lib, ELF_File.RelocationTable reloc) throws IOException { + + if (reloc.hasAddends) + throw new Error("ARM should not encounter RELA sections when runtime linking executable files."); + + //get the symbol table for this library + SymbolTable symtab = lib.getDynamicSection().findSymbolTable(); + + //get the library's string table + StringTable strTab = lib.getDynamicSection().findStringTable(); + + //now start processing the library's relocation entries + for (RelocationTable.Entry entry : reloc.entries) { + + //where shall we store the resolved symbol + int resolveToAddress = entry.offset + lib.getLoadOffset(); + + switch (entry.relocationType) { + case R_ARM_ABS32: + { + SymbolTable.Entry symbol = symtab.getEntry(entry.symbolIndex); + + if (DBT.VerifyAssertions) DBT._assert(!symbol.isUndefined()); + + //this a local symbol that we can easily resolve + int offset = ps.memory.load32(resolveToAddress); + ps.memory.store32(resolveToAddress, symbol.value + lib.getLoadOffset() + offset); + } + break; + + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + { + SymbolTable.Entry symbol = symtab.getEntry(entry.symbolIndex); + int value; + + if (symbol.isUndefined()) { + String symbolName = strTab.lookup(symbol.nameIdx); + value = resolveSymbolAddress(symbolName); + + if (value == -1) { + //we allow only weak symbols to be unresolved + if (symbol.binding != SymbolTable.STB_WEAK) { + throw new RuntimeException("Unable to resolve: " + symbolName + " in " + lib); + } + + continue; + } + } + else { + //this a local symbol that is already resolved. Just relocate it + value = symbol.value + lib.getLoadOffset(); + } + + //store the resolved symbol + ps.memory.store32(resolveToAddress, value); + } + break; + + case R_ARM_RELATIVE: + { + //R_ARM_RELATIVE + int address = ps.memory.load32(resolveToAddress); + ps.memory.store32(resolveToAddress, address + lib.getLoadOffset()); + } + break; + + default: + throw new RuntimeException("Unknown relocation type: " + entry.relocationType); + } + } + } + + @Override + protected void runInitRoutine(int startPC) { + + int pc = startPC; + ps.setCurrentInstructionAddress(startPC); + + Interpreter interpreter = ps.createInstructionInterpreter(); + + ((ARM_ProcessSpace)ps).registers.set(ARM_Registers.LR, startPC); + + while (!ps.finished) { + + Interpreter.Instruction instruction = interpreter.decode(pc); + instruction.execute(); + pc = instruction.getSuccessor(pc); + + if (pc == -1) + pc = ps.getCurrentInstructionAddress(); + else + ps.setCurrentInstructionAddress(pc); + + //we're done running the init method + if (pc == startPC) + break; + } + + if (ps.finished) { + throw new RuntimeException("ProcessSpace exited while running the INIT routine of a dynamically linked library."); + } + } + +} Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-05-19 15:20:17 UTC (rev 124) @@ -60,17 +60,12 @@ /** * Initialise the process space, called after the binary has been loaded * - * @param pc - * the entry point - * @param brk - * the initial value for the top of BSS - * @param args - * command line arguments */ - public void initialise(Loader loader, int pc, int brk) { - this.pc = pc; + @Override + public void initialise(Loader loader) { + this.pc = loader.getEntryPoint(); this.r1 = initialiseStack(loader, pc); - syscalls.initialize(brk); + syscalls.initialize(loader.getBrk()); } /** Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-05-19 15:20:17 UTC (rev 124) @@ -64,10 +64,11 @@ * @param brk the initial value for the top of BSS * @param args command line arguments */ - public void initialise(Loader loader, int pc, int brk) { - registers.eip = pc; + @Override + public void initialise(Loader loader) { + registers.eip = loader.getEntryPoint(); - registers.writeGP32(X86_Registers.ESP, initialiseStack(loader, pc)); + registers.writeGP32(X86_Registers.ESP, initialiseStack(loader)); if (useSysInfoPage) { try { memory.map(0xffffe000, 8192, true, true, true); @@ -79,13 +80,14 @@ memory.store8(0xffffe400, 0xC3); // RET } - syscalls.initialize(brk); + syscalls.initialize(loader.getBrk()); } /** * Initialise the stack */ - private int initialiseStack(Loader loader, int pc) { + private int initialiseStack(Loader loader) { + auxVector = new int[] { LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x078bfbff, LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, @@ -94,7 +96,7 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, ((ELF_Loader)loader).getNumberOfProgramSegmentHeaders(), LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, - LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, pc, + LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, loader.getEntryPoint(), LinuxStackInitializer.AuxiliaryVectorType.AT_UID, DBT_Options.UID, LinuxStackInitializer.AuxiliaryVectorType.AT_EUID, DBT_Options.UID, Modified: src/org/binarytranslator/generic/os/loader/Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/Loader.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/generic/os/loader/Loader.java 2007-05-19 15:20:17 UTC (rev 124) @@ -33,11 +33,6 @@ System.out.println(s); } } - - /* - * Abstract methods defined by the relavent binary loader - */ - /** * Create a process space, load the binary into it and initialise the stack, * etc. @@ -69,6 +64,12 @@ /** Shall return the Application Binary Interface that is required to load this executable. */ public abstract ABI getABI(); + + /** Shall return the top of the stack. */ + public abstract int getBrk(); + + /** Shall return the address at which execution of the program starts. */ + public abstract int getEntryPoint(); /** * Open and read the start of the file to determine the appropriate file Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_File.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-05-19 15:20:17 UTC (rev 124) @@ -23,14 +23,10 @@ public class ELF_File { - /** - * Wrapper class used for reading the ELF file with the required endianness - */ + /** Wrapper class used for reading the ELF file with the required endianness */ private BinaryReader reader; - /** - * Header of ELF file - */ + /** Header of ELF file */ private Header header; /** @@ -835,7 +831,7 @@ this.sectionIndex = sectionIndex; } - final boolean isUndefined() { + public final boolean isUndefined() { return sectionIndex == SHN_UNDEF; } } @@ -1112,9 +1108,9 @@ if (tabLocation == null || tabSize == null || entrySize == null | entryType == null) return null; - relaTab = new RelocationTable(tabLocation.value, tabSize.value, entrySize.value, entryType.value == DT_RELA); + RelocationTable jmpRel= new RelocationTable(tabLocation.value, tabSize.value, entrySize.value, entryType.value == DT_RELA); - return relaTab; + return jmpRel; } public RelocationTable findRelaTable() throws IOException { Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-05-19 15:20:17 UTC (rev 124) @@ -2,18 +2,30 @@ import java.io.IOException; -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.linux.ARM_LinuxProcessSpace; -import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.os.loader.Loader; -import org.binarytranslator.generic.os.loader.elf.ELF_File.DynamicSection; import org.binarytranslator.generic.os.process.ProcessSpace; public class ELF_Loader extends Loader { + /** The file that we're trying to load. */ private ELF_File file; - private ELF_File loader; + + /** The top of the stack segment. */ + private int brk; + + /** The entry point at which execution of the program starts. */ + private int entryPoint; + + @Override + public int getEntryPoint() { + return entryPoint; + } + + @Override + public int getBrk() { + return brk; + } @Override public ABI getABI() { @@ -25,18 +37,34 @@ return file.getHeader().getISA(); } + /** Returns the file that we're trying to load. */ + public ELF_File getFile() { + return file; + } + + /** Returns the address at which the executable's program header has been mapped into memory. */ public int getProgramHeaderAddress() { return file.getProgramHeaderAddress(); } + /** Returns the number of program headers within the executable. */ public int getNumberOfProgramSegmentHeaders() { return file.getHeader().getNumberOfProgramSegmentHeaders(); } - + + /** Returns the size of a single program header within memory. */ public int getProgramSegmentHeaderSize() { return file.getHeader().getProgramSegmentHeaderSize(); } + /** + * Checks if the given file is in ELF format. + * + * @param filename + * The name of the file that is to be checked. + * @return + * True if the file is an ELF file, false otherwise. + */ public static boolean conforms(String filename) { return ELF_File.conforms(filename); } @@ -48,62 +76,41 @@ ProcessSpace ps = ProcessSpace.createProcessSpaceFromBinary(this); ELF_File.SegmentHeader[] segments = file.getProgramSegmentHeaders(); - - System.out.println("ELF has segments:"); - for (ELF_File.SegmentHeader header : segments) { - System.out.println(header.toString()); - header.create(ps); + + if (DBT_Options.debugLoader) { + System.out.println("ELF has segments:"); + + for (ELF_File.SegmentHeader segment : segments) { + System.out.println(" - " + segment.toString()); + } } - int brk; - if (segments.length > 1) - brk = segments[1].getEnd(); - else - brk = segments[0].getEnd(); + //Determine the top of the stack. + //NB: I just copied that code from the old ELF loader. Is this really correct? + brk = segments[segments.length > 1 ? 1 : 0].getEnd(); - if (file.getDynamicSection() != null && file.getHeader().getABI() == ABI.ARM) { + //determine the entry point to the program + entryPoint = file.getHeader().getEntryPoint(); + + if (file.getDynamicSection() != null) { + + if (DBT_Options.debugLoader) System.out.println("Executable is dynamically linked."); - ARM_ProcessSpace armps = (ARM_ProcessSpace)ps; - - //invoke the runtime linker - RuntimeLinker ld = new RuntimeLinker(file, ps); + //This is a dynamically linked file, so hand over control to the runtime linker + RuntimeLinker ld = RuntimeLinker.create(ps, this); ld.link(); + } + else { + if (DBT_Options.debugLoader) System.out.println("Executable is statically linked."); - ps.initialise(this, file.getHeader().getEntryPoint(), brk); - int startInstruction = ps.getCurrentInstructionAddress(); - - //call the INITs - Interpreter interpreter = ps.createInstructionInterpreter(); - for (Integer init : ld.initMethods) { - int pc = init; - - ps.setCurrentInstructionAddress(init); - armps.registers.set(ARM_Registers.LR, init); - - while (!ps.finished) { - - Interpreter.Instruction instruction = interpreter.decode(pc); - System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); - - instruction.execute(); - pc = instruction.getSuccessor(pc); - - if (pc == -1) - pc = ps.getCurrentInstructionAddress(); - else - ps.setCurrentInstructionAddress(pc); - - //we're done running the init method - if (pc == init) - break; - } + //this is a statically linked file. We simply need to map all of its segments into memory + for (ELF_File.SegmentHeader segment : segments) { + segment.create(ps); } - ld._tmpRestore(); - ps.setCurrentInstructionAddress(startInstruction); + //and then initialize the process space + ps.initialise(this); } - else - ps.initialise(this, file.getHeader().getEntryPoint(), brk); return ps; } Copied: src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java (from rev 106, src/org/binarytranslator/generic/os/loader/elf/RuntimeLinker.java) =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java (rev 0) +++ src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-05-19 15:20:17 UTC (rev 124) @@ -0,0 +1,412 @@ +package org.binarytranslator.generic.os.loader.elf; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; + +import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; +import org.binarytranslator.generic.os.loader.elf.ELF_File.DynamicSection; +import org.binarytranslator.generic.os.loader.elf.ELF_File.SegmentHeader; +import org.binarytranslator.generic.os.loader.elf.ELF_File.StringTable; +import org.binarytranslator.generic.os.loader.elf.ELF_File.SymbolTable; +import org.binarytranslator.generic.os.process.ProcessSpace; + +public abstract class JavaRuntimeLinker extends RuntimeLinker { + + /** The process space that we're linking the file in. */ + protected final ProcessSpace ps; + + /** The loader that triggered the runtime linking. */ + private final ELF_Loader loader; + + /** the file that we're ultimately trying to link */ + private ELF_File file; + + /** A list of all libraries that are referenced within the loading process. */ + 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>(); + + /** 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) + + /** Maps a library name to a filename. */ + protected final HashMap<String, String> libNames = new HashMap<String, String>();; + + public static class SharedObject { + /** The libary's name. */ + private final String filename; + + /** The elf file that this library can be loaded from. */ + private ELF_File file = null; + + /** The dynamic section of this library */ + private ELF_File.DynamicSection dynamicSection = null; + + /** Is the library already relocated? */ + private boolean relocated = false; + + /** Stores if a library can only be loaded at a specific load offset. This is generally only true for the program file. */ + private final boolean hasFixedLoadOffset; + + /** The address at which this library has been loaded. */ + private int loadedAt; + + /** Other libraries, that this library depends upon. */ + private SharedObject[] dependencies = null; + + public SharedObject(String filename) { + this.filename = filename; + this.hasFixedLoadOffset = false; + } + + public SharedObject(String filename, int fixedLoadOffset) { + this.filename = filename; + this.loadedAt = fixedLoadOffset; + this.hasFixedLoadOffset = true; + } + + /** The elf file that this library can be loaded from. */ + public ELF_File getFile() throws IOException { + if (file == null) + file = new ELF_File(filename); + + return file; + } + + /** Returns the dynamic section of this library */ + public ELF_File.DynamicSection getDynamicSection() throws IOException { + if (dynamicSection == null) { + dynamicSection = getFile().getDynamicSection(); + } + + return dynamicSection; + } + + /** Returns the address at which this library has been loaded. */ + public int getLoadOffset() { + return loadedAt; + } + + /** Returns true if a libary can only be loaded at a fixed offset in memory. False otherwise. */ + public boolean hasFixedLoadOffset() { + return hasFixedLoadOffset; + } + + @Override + public String toString() { + File f = new File(filename); + return f.getName(); + } + } + + public JavaRuntimeLinker(ProcessSpace ps, ELF_Loader loader) { + this.ps = ps; + this.loader = loader; + this.file = loader.getFile(); + } + + /** + * This function is the main entry point into the dynamic linker and will steer the whole + * linking process. + */ + public final void link() throws IOException { + ELF_File.DynamicSection dynSection = file.getDynamicSection(); + + //align the library start address to a page + nextMemoryBlock = ps.memory.truncateToPage(nextMemoryBlock); + + if (dynSection == null) { + System.out.println("Unable to find dynamic linking segment."); + throw new UnsupportedOperationException("Trying to runtime-link a static executable."); + } + + //Create a representation for the program file, which is then treated like any other shared object + SharedObject programfile = new SharedObject("<Program File>", 0); + programfile.file = file; + libraries.add(programfile); + + //load the program file and all its dependend libraries + loadLibRecursively(programfile); + + //relocate all dynamic libraries + relocateLibRecursively(programfile); + + //Call the init routines that were registered by the different libraries + callInitRoutines(); + + //prepare to start the real program + ps.setCurrentInstructionAddress(loader.getEntryPoint()); + } + + /** + * Resolves a library, given by its <code>name</code> into a {@link SharedObject} object. + * If the library is referenced for the first time, it is added to the global list + * of available {@link #libraries}. + * + * @param name + * The name of the library that is to be resolved. + * @return + * A library object representing that library. + */ + private SharedObject resolveLibraryByName(String name) { + + String originalName = name; + name = libNames.get(name); + + if (name == null) + throw new RuntimeException("SharedObject not present: " + originalName); + + for (int i = 0; i < libraries.size(); i++) { + SharedObject lib = libraries.get(i); + + if (lib.filename.equals(name)) + return lib; + } + + SharedObject lib = new SharedObject(name); + libraries.addLast(lib); + return lib; + } + + /** + * Calls {@link #runInitRoutine(int)} several times to run all INIT routines for all loaded + * libraries. + */ + protected void callInitRoutines() throws IOException { + //the linker has a special symbol that determines if we're currently starting up + int dl_starting_up = resolveSymbolAddress("_dl_starting_up"); + + if (dl_starting_up != -1) + ps.memory.store32(dl_starting_up, 1); + + //Initialize the process space + ps.initialise(loader); + + //call the INIT functions + for (int init : initMethods) { + runInitRoutine(init); + } + + //note that we're done running the inits + if (dl_starting_up != -1) + ps.memory.store32(dl_starting_up, 0); + } + + /** + * Loads the library <code>lib</code> and all its dependencies into memory. + * All newly found dependencies (i.e. libraries that have to be loaded) are + * put into the global library collection. + * + * @param lib + * The library that is to be loaded. + */ + private void loadLibRecursively(SharedObject lib) throws IOException { + + //skip libraries, if their dependencies have already been resolved + if (lib.dependencies != null) + return; + + //get a few essential elements within the library (.dynamic section, string table etc.) + if (DBT_Options.debugLoader) System.out.println("Resolving dependencies for: " + lib); + DynamicSection libDynamicSection = lib.getDynamicSection(); + + if (libDynamicSection == null) + throw new RuntimeException("SharedObject " + lib + "is not a shared library."); + + StringTable libStrTab = libDynamicSection.findStringTable(); + + if (libStrTab == null) + throw new RuntimeException("Unable to find String table of shared library."); + + //resolve the library's dependencies + ELF_File.DynamicSection.Entry[] libDepends = libDynamicSection.getEntriesByType(ELF_File.DynamicSection.DT_NEEDED); + lib.dependencies = new SharedObject[libDepends.length]; + + //add all the libraries that this one depends on + for (int i = 0; i < libDepends.length; i++) { + String dependencyName = libStrTab.lookup(libDepends[i].value); + if (DBT_Options.debugLoader) System.out.println(" Depends on: " + dependencyName); + + //note the dependency + lib.dependencies[i] = resolveLibraryByName(dependencyName); + + //and also resolve their dependencies + loadLibRecursively(lib.dependencies[i]); + } + + //load the library to memory + loadSingleLibrary(lib); + } + + /** + * Relocate a library recursively by first relocating its dependencies and then + * relocating the library itself. + * + * @param lib + * The library that is to be relocated. + */ + private void relocateLibRecursively(SharedObject lib) throws IOException { + + //nothing to do if the library is already loaded + if (lib.relocated) { + return; + } + + //to avoid recursion due to circular dependencies, mark this library as loaded + lib.relocated = true; + + //load its dependencies + for (int i = 0; i < lib.dependencies.length; i++) + relocateLibRecursively(lib.dependencies[i]); + + //relocate the library itself + relocateSingleLib(lib); + + //Remember to execute it's INIT function later on + ELF_File.DynamicSection.Entry initMethod = lib.getDynamicSection().getEntryByType(ELF_File.DynamicSection.DT_INIT); + + if (initMethod != null) { + initMethods.add(initMethod.value + lib.loadedAt); + } + } + + /** + * Relocates a single library, but none of its dependencies. + * + * @param lib + * The library that is to be relocated. + */ + private void relocateSingleLib(SharedObject lib) throws IOException { + + DynamicSection libDynamicSection = lib.getDynamicSection(); + ELF_File.RelocationTable relTable = libDynamicSection.findRelTable(); + + if (DBT_Options.debugLoader) System.out.println("Performing relocation for: " + lib); + + if (relTable == null) { + if (DBT_Options.debugLoader) System.out.println(" No REL in " + lib); + } + else { + if (DBT_Options.debugLoader) System.out.println(" Performing REL in " + lib); + relocate(lib, relTable); + } + + relTable = libDynamicSection.findRelaTable(); + + if (relTable == null) { + if (DBT_Options.debugLoader) System.out.println(" No RELA in " + lib); + } + else { + if (DBT_Options.debugLoader) System.out.println(" Performing RELA in " + lib); + relocate(lib, relTable); + } + + relTable = libDynamicSection.findJmpRelTable(); + + if (relTable == null) { + if (DBT_Options.debugLoader) System.out.println(" No JMPREL in " + lib); + } + else { + if (DBT_Options.debugLoader) System.out.println(" Performing JMPREL in " + lib); + relocate(lib, relTable); + } + } + + /** + * Loads all segments belong to the library <code>lib</code> into memory. + * + * @param lib + * The library that shall be loaded to memory. + */ + private void loadSingleLibrary(SharedObject lib) { + + if (DBT.VerifyAssertions) DBT._assert(lib.loadedAt == 0); + + if (!lib.hasFixedLoadOffset()) { + // load the library to the next available address + lib.loadedAt = nextMemoryBlock; + } + + //do we need to write into the text segment? + boolean needRelocText = !lib.hasFixedLoadOffset() && lib.dynamicSection.getEntryByType(ELF_File.DynamicSection.DT_TEXTREL) != null; + + //start by mapping the library into memory + SegmentHeader segments[] = lib.file.getProgramSegmentHeaders(); + + //the highest offset from nextMemoryBlock that this shared object uses + long highestUsedAddress = 1; + + for (int i = 0; i < segments.length; i++) { + + //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; + + //create the actual segment + segments[i].create(ps, lib.loadedAt); + + long thisAddress = segments[i].p_vaddr; + thisAddress += segments[i].p_memsz; + + if (thisAddress >= highestUsedAddress) + highestUsedAddress = thisAddress + 1; + } + + if (!lib.hasFixedLoadOffset()) { + //page-align the next memory block + nextMemoryBlock = ps.memory.truncateToNextPage((int)(highestUsedAddress + nextMemoryBlock + 5000)); + } + } + + /** + * Resolves the given <code>symbol</code> name into the address, to which the symbol + * has been relocated. + * + * @param symbol + * The name of the symbol that is to be resolved. + * @return + * The address of the symbol or -1, if the symbol's address could not be resolved. + */ + protected final int resolveSymbolAddress(String symbol) throws IOException { + Iterator<SharedObject> libs = libraries.iterator(); + + //iterate over the symbol table of every library that we already loaded + while (libs.hasNext()) { + SharedObject lib = libs.next(); + ELF_File.SymbolHashTable hashTab = lib.dynamicSection.findHashTable(); + + //see if <symbol> is defined within this library + SymbolTable.Entry entry = hashTab.lookup(symbol); + + if (entry != null && !entry.isUndefined()) + return entry.value + lib.loadedAt; + } + + return -1; + } + + /** + * This function is called as a request to run a libraries INIT routine. + * Implementations shall run the init routine, which is starting at address <code>startPC</code>. + * + * @param startPC + * The address at which the INIT routine is starting. + */ + protected abstract void runInitRoutine(int startPC); + + /** + * This function is called as a request to relocate the entries in <code>relocations</code> + * which belong to <code>library</code>. + * + * @param library + * The library that is to be relocated. + * @param relocations + * A table of relocation entries that are to be processed to relocate the library. + */ + protected abstract void relocate(SharedObject library, ELF_File.RelocationTable relocations) throws IOException; +} Deleted: src/org/binarytranslator/generic/os/loader/elf/RuntimeLinker.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/RuntimeLinker.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/generic/os/loader/elf/RuntimeLinker.java 2007-05-19 15:20:17 UTC (rev 124) @@ -1,434 +0,0 @@ -package org.binarytranslator.generic.os.loader.elf; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; - -import org.binarytranslator.DBT; -import org.binarytranslator.generic.os.loader.elf.ELF_File.RelocationTable; -import org.binarytranslator.generic.os.loader.elf.ELF_File.SegmentHeader; -import org.binarytranslator.generic.os.loader.elf.ELF_File.StringTable; -import org.binarytranslator.generic.os.loader.elf.ELF_File.SymbolTable; -import org.binarytranslator.generic.os.process.ProcessSpace; - -public class RuntimeLinker { - - /** */ - private final ProcessSpace ps; - - /** the file that we're ultimately trying to link */ - private ELF_File file; - - /** A list of all libraries that are referenced within the loading process. */ - private LinkedList<Library> libraries = new LinkedList<Library>(); - - /** A list of the star addres of all init routines, that we're supposed to execute. */ - public 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) - - /** Maps a library name to a filename. */ - private static HashMap<String, String> libNames; - - static { - String libDir = "C:\\0Dateien\\University of Manchester\\MSc Thesis\\ARM Executables\\Dynamically Linked\\Hello World\\"; - - libNames = new HashMap<String, String>(); - libNames.put("libc.so.6", libDir + "libc-2.2.5.so"); - libNames.put("ld-linux.so.2", libDir + "ld-linux.so.2"); - } - - private static class Library { - /** The libary's name. */ - public String filename; - - /** The elf file that this library can be loaded from. */ - public ELF_File file = null; - - /** The dynamic section of this library */ - public ELF_File.DynamicSection dynamicSection = null; - - /** Is the library already relocated? */ - public boolean relocated = false; - - /** The address at which this library has been loaded. */ - public int relocatedTo; - - /** Other libraries, that this library depends upon. */ - public Library[] dependencies = null; - - public Library(String filename) { - this.filename = filename; - } - - @Override - public String toString() { - File f = new File(filename); - return f.getName(); - } - } - - public RuntimeLinker(ELF_File file, ProcessSpace ps) { - this.file = file; - this.ps = ps; - } - - private Library addLibByName(String name) { - - String originalName = name; - name = libNames.get(name); - - if (name == null) - throw new RuntimeException("Library not present: " + originalName); - - for (int i = 0; i < libraries.size(); i++) { - Library lib = libraries.get(i); - - if (lib.filename.equals(name)) - return lib; - } - - Library lib = new Library(name); - libraries.addLast(lib); - return lib; - } - - public void link() throws IOException { - ELF_File.DynamicSection dynSection = file.getDynamicSection(); - - //align the library start address to a page - nextMemoryBlock = ps.memory.truncateToPage(nextMemoryBlock); - - if (dynSection == null) { - System.out.println("Unable to find dynamic linking segment."); - throw new UnsupportedOperationException("Trying to runtime-link a static executable."); - } - - System.out.println(dynSection); - - ELF_File.DynamicSection.Entry[] neededLibs = dynSection.getEntriesByType(ELF_File.DynamicSection.DT_NEEDED); - ELF_File.StringTable strTab = dynSection.findStringTable(); - - //grab the libraries that are needed by this executable - for (int i = 0; i < neededLibs.length; i++) { - String libName = strTab.lookup(neededLibs[i].value); - System.out.println("Needs lib: " + libName); - - Library lib = addLibByName(libName); - loadLibAndRecordDependencies(lib); - } - - //finally, link the remaining symbols from the executable - Library programfile = new Library("<Program File>"); - programfile.file = file; - programfile.dynamicSection = dynSection; - programfile.dependencies = new Library[0]; - libraries.add(programfile); - - //load the dynamic libraries - Iterator<Library> libs = libraries.listIterator(); - - while (libs.hasNext()) { - Library lib = libs.next(); - - if (!lib.relocated) - relocateLibRecursively(lib); - } - - System.out.println("Resolving undefined symbols in executable."); - - RelocationTable relTab = dynSection.findRelTable(); - if (relTab != null) { - System.out.println("Resolving REL in executable."); - relocate(programfile, relTab); - } - else - System.out.println("Could not find REL table in executable."); - - relTab = dynSection.findRelaTable(); - - if (relTab != null) { - System.out.println("Resolving RELA in executable."); - relocate(programfile, relTab); - } - else - System.out.println("Could not find RELA table in executable."); - - relTab = dynSection.findJmpRelTable(); - - if (relTab != null) { - System.out.println("Resolving JMPREL in executable."); - relocate(programfile, relTab); - } - else - System.out.println("Could not find JMPREL table in executable."); - - //Does the program file have a init method? If yes, call it later - ELF_File.DynamicSection.Entry initMethod = dynSection.getEntryByType(ELF_File.DynamicSection.DT_INIT); - - if (initMethod != null) { - initMethods.add(initMethod.value); - } - - - int symAddr = resolveSymbolAddress("_dl_starting_up"); - - DBT._assert(symAddr != -1); - ps.memory.store32(symAddr, 1); - - - } - - //TODO: Remove - public void _tmpRestore() throws IOException { - int symAddr = resolveSymbolAddress("_dl_starting_up"); - - DBT._assert(symAddr != -1); - ps.memory.store32(symAddr, 0); - } - - private void loadLibAndRecordDependencies(Library lib) throws IOException { - - //skip libraries, if their dependencies have already been resolved - if (lib.dependencies != null) - return; - - //get a few essential elements within the library (.dynamic section, string table etc.) - System.out.println("Resolving dependencies for: " + lib); - lib.file = new ELF_File(lib.filename); - lib.dynamicSection = lib.file.getDynamicSection(); - - if (lib.dynamicSection == null) - throw new RuntimeException("Library is not a shared library."); - - StringTable libStrTab = lib.dynamicSection.findStringTable(); - - if (libStrTab == null) - throw new RuntimeException("Unable to find String table of shared library."); - - //resolve the library's dependencies - ELF_File.DynamicSection.Entry[] libDepends = lib.dynamicSection.getEntriesByType(ELF_File.DynamicSection.DT_NEEDED); - lib.dependencies = new Library[libDepends.length]; - - - - //add all the libraries that this one depends on - for (int i = 0; i < libDepends.length; i++) { - String libName = libStrTab.lookup(libDepends[i].value); - System.out.println(" Depends on: " + libName); - - //note the dependency - lib.dependencies[i] = addLibByName(libName); - - //and also resolve their dependencies - loadLibAndRecordDependencies(lib.dependencies[i]); - } - - //load the library to memory - loadLibToMemory(lib); - - - } - - /** Load a library recursively by first loading its dependencies and then the library itself*/ - private void relocateLibRecursively(Library lib) throws IOException { - - //nothing to do if the library is already loaded - if (lib.relocated) { - return; - } - - //to avoid recursion due to circular dependencies, mark this library as loaded - lib.relocated = true; - - //load its dependencies - for (int i = 0; i < lib.dependencies.length; i++) - relocateLibRecursively(lib.dependencies[i]); - - //relocate the library itself - relocateSingleLib(lib); - - //Remember to execute it's INIT function later on - ELF_File.DynamicSection.Entry initMethod = lib.dynamicSection.getEntryByType(ELF_File.DynamicSection.DT_INIT); - - if (initMethod != null) { - initMethods.add(initMethod.value + lib.relocatedTo); - } - } - - /** Loads and relocates a single library (none of the dependencies). */ - private void relocateSingleLib(Library lib) throws IOException { - - ELF_File.RelocationTable relTable = lib.dynamicSection.findRelTable(); - - if (relTable == null) - System.out.println("Did not find a REL table in " + lib); - else { - System.out.println("Performing REL relocation in " + lib); - relocate(lib, relTable); - } - - relTable = lib.dynamicSection.findRelaTable(); - - if (relTable == null) - System.out.println("Did not find a RELA table in " + lib); - else { - System.out.println("Performing RELA relocation in " + lib); - relocate(lib, relTable); - } - - relTable = lib.dynamicSection.findJmpRelTable(); - - if (relTable == null) - System.out.println("Did not find a JMPREL table in " + lib); - else { - System.out.println("Performing JMPREL relocation in " + lib); - relocate(lib, relTable); - } - } - - private void loadLibToMemory(Library lib) { - - if (DBT.VerifyAssertions) DBT._assert(lib.relocatedTo == 0); - - //load the library to the next available address - lib.relocatedTo = nextMemoryBlock; - - //do we need to write into the text segment? - boolean needRelocText = lib.dynamicSection.getEntryByType(ELF_File.DynamicSection.DT_TEXTREL) != null; - - //start by mapping the library into memory - SegmentHeader segments[] = lib.file.getProgramSegmentHeaders(); - - //the highest offset from nextMemoryBlock that this shared object uses - long highestUsedAddress = 1; - - for (int i = 0; i < segments.length; i++) { - - //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; - - //create the actual segment - segments[i].create(ps, lib.relocatedTo); - - long thisAddress = segments[i].p_vaddr; - thisAddress += segments[i].p_memsz; - - if (thisAddress >= highestUsedAddress) - highestUsedAddress = thisAddress + 1; - } - - //page-align the next memory block - nextMemoryBlock = ps.memory.truncateToNextPage((int)(highestUsedAddress + nextMemoryBlock + 5000)); - } - - private int resolveSymbolAddress(String symbol) throws IOException { - Iterator<Library> libs = libraries.iterator(); - - //iterate over the symbol table of every library that we already loaded - while (libs.hasNext()) { - Library lib = libs.next(); - ELF_File.SymbolHashTable hashTab = lib.dynamicSection.findHashTable(); - - //see if <symbol> is defined within this library - SymbolTable.Entry entry = hashTab.lookup(symbol); - - if (entry != null && !entry.isUndefined()) - return entry.value + lib.relocatedTo; - } - - return -1; - } - - private void relocate(Library lib, ELF_File.RelocationTable reloc) throws IOException { - - if (reloc.hasAddends) - throw new RuntimeException("Not yet implemented"); - - //get the symbol table for this library - SymbolTable symtab = lib.dynamicSection.findSymbolTable(); - - //get the library's string table - StringTable strTab = lib.dynamicSection.findStringTable(); - - //now start processing the library's relocation entries - for (RelocationTable.Entry entry : reloc.entries) { - //SegmentHeader segment = lib.file.virtualAddressToSegment(entry.offset); - //int offsetFromSegment = entry.offset - segment.p_vaddr; - //int addr = segment.p_paddr + offsetFromSegment; - int addr = entry.offset + lib.relocatedTo; - - switch (entry.relocationType) { - case 21: - { - //R_ARM_GLOB_DAT - SymbolTable.Entry symbol = symtab.getEntry(entry.symbolIndex); - String symbolName = strTab.lookup(symbol.nameIdx); - System.out.println(symbolName); - if (symbol.isUndefined()) { - - int symAddr = resolveSymbolAddress(symbolName); - - if (symAddr == -1) { - //we allow only weak symbols to be unresolved - if (symbol.binding != SymbolTable.STB_WEAK && symAddr == -1) { - throw new RuntimeException("Unable to resolve: " + symbolName + " in " + lib); - } - - continue; - } - - //store the resolved symbol - ps.memory.store32(entry.offset + lib.relocatedTo, symAddr); - } - else { - //this a local symbol that is already resolved - ps.memory.store32(entry.offset + lib.relocatedTo, symbol.value + lib.relocatedTo); - } - } - break; - - case 22: - { - //R_ARM_JUMP_SLOT - SymbolTable.Entry symbol = symtab.getEntry(entry.symbolIndex); - String symbolName = strTab.lookup(symbol.nameIdx); - System.out.println(symbolName); - if (symbol.isUndefined()) { - - int symAddr = resolveSymbolAddress(symbolName); - - //we allow only weak symbols to be unresolved - if (symbol.binding != SymbolTable.STB_WEAK && symAddr == -1) { - throw new RuntimeException("Unable to resolve: " + symbolName + " in " + lib); - } - - //store the resolved symbol - ps.memory.store32(entry.offset + lib.relocatedTo, symAddr); - } - else { - //this a local symbol that we can easily resolve - ps.memory.store32(entry.offset + lib.relocatedTo, symbol.value + lib.relocatedTo); - } - } - break; - case 23: - { - //R_ARM_RELATIVE - int address = ps.memory.load32(addr); - //System.out.println(address); - ps.memory.store32(addr, address + lib.relocatedTo); - } - break; - - - default: - break; - } - } - } -} Modified: src/org/binarytranslator/generic/os/loader/image/ImageLoader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/image/ImageLoader.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/generic/os/loader/image/ImageLoader.java 2007-05-19 15:20:17 UTC (rev 124) @@ -99,7 +99,7 @@ return null; } - ps.initialise(this, 0, -1); + ps.initialise(this); return ps; } @@ -133,4 +133,14 @@ System.out.println(s); } } + + @Override + public int getBrk() { + return -1; + } + + @Override + public int getEntryPoint() { + return 0; + } } Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java =================================================================== --- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) +++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-05-19 15:20:17 UTC (rev 124) @@ -116,7 +116,7 @@ * @param brk * the initial value for the top of BSS */ - public abstract void initialise(Loader loader, int pc, int brk); + public abstract void initialise(Loader loader); /** * Constructor This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-18 17:15:07
|
Revision: 123 http://svn.sourceforge.net/pearcolator/?rev=123&view=rev Author: michael_baer Date: 2007-05-18 10:13:21 -0700 (Fri, 18 May 2007) Log Message: ----------- Further refined branch resolution: - centralized the decision on whether to include a branch target into the trace or not - harmonized the way branch targets are resolved and the call interface to the decoder - re-introduced a code cache in the ProcessSpace class Misc. changes: - allowing custom functions calls within traces (untested) ARM changes: - fixed a bug where flags in RSBS would be set incorrectly 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_Translator.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.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/os/process/X86_ProcessSpace.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/execution/DynamicTranslationController.java src/org/binarytranslator/generic/memory/CallBasedMemory.java src/org/binarytranslator/generic/memory/DebugMemory.java src/org/binarytranslator/generic/memory/MemoryMapException.java src/org/binarytranslator/generic/os/process/ProcessSpace.java src/org/binarytranslator/vmInterface/DBT_Trace.java Added Paths: ----------- src/org/binarytranslator/generic/decoder/CodeCache.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/DBT_Options.java 2007-05-18 17:13:21 UTC (rev 123) @@ -17,8 +17,10 @@ * Options for controlling the emulator */ public class DBT_Options { - // -oO Runtime settings Oo- + /** Remove features that will only work on jikes? */ + public final static boolean buildForSunVM = true; + /** * Debug binary loading */ @@ -69,19 +71,10 @@ */ public static boolean plantUncaughtBranchWatcher = false; - /** - * Should all branches (excluding to lr and ctr) be resolved in one big go or - * one at at a time - */ - public static boolean resolveBranchesAtOnce = true; + /** Should direct branches be resolved before dynamic branches? */ + public static boolean resolveDirectBranchesFirst = true; /** - * Should procedures (branches to ctr and lr) be given precedent over more - * local branches - */ - public static boolean resolveProceduresBeforeBranches = true; - - /** * Use global branch information rather than local (within the trace) * information when optimisation level is greater than or equal to this value */ @@ -231,14 +224,8 @@ instrOpt2 = Integer.parseInt(value); } else if (arg.equalsIgnoreCase("-X:dbt:singleInstrTranslation")) { singleInstrTranslation = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:resolveBranchesAtOnce")) { - resolveBranchesAtOnce = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:resolveBranchesAtOnce")) { - resolveBranchesAtOnce = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:resolveProceduresBeforeBranches")) { - resolveProceduresBeforeBranches = Boolean.parseBoolean(value); - } else if (arg.equalsIgnoreCase("-X:dbt:resolveProceduresBeforeBranches")) { - resolveProceduresBeforeBranches = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:resolveDirectBranchesFirst")) { + resolveDirectBranchesFirst = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:gdbStub")) { gdbStub = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:gdbStubPort")) { Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/Main.java 2007-05-18 17:13:21 UTC (rev 123) @@ -10,11 +10,15 @@ import java.io.File; -import org.binarytranslator.arch.arm.decoder.Utils; 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; @@ -98,15 +102,18 @@ //Create an execution controller and pass execution on to it ExecutionController controller; - if (DBT_Options.gdbStub) { - controller = new GdbController(DBT_Options.gdbStubPort, ps); + if (DBT_Options.buildForSunVM) { + controller = new InterpreterController(ps); } else { - controller = new DynamicTranslationController(ps); + if (DBT_Options.gdbStub) { + controller = new GdbController(DBT_Options.gdbStubPort, ps); + } + else { + controller = new DynamicTranslationController(ps); + } } - - //controller = new InterpreterController(ps); controller.run(); System.out.println("\nProgram has finished."); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-18 17:13:21 UTC (rev 123) @@ -9,6 +9,7 @@ import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode; import org.binarytranslator.generic.decoder.AbstractCodeTranslator; import org.binarytranslator.generic.decoder.Laziness; +import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_FieldReference; import org.jikesrvm.classloader.VM_MemberReference; @@ -129,8 +130,8 @@ if (DBT.VerifyAssertions) DBT._assert(registers_overflowFlag_Fref != null); } - public ARM2IR(OPT_GenerationContext context) { - super(context); + public ARM2IR(OPT_GenerationContext context, DBT_Trace trace) { + super(context, trace); translator = new ARM_Translator((ARM_ProcessSpace)ps, this); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-18 17:13:21 UTC (rev 123) @@ -889,16 +889,16 @@ } else { OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); - arm2ir.appendInstruction(s); + arm2ir.appendCustomCall(s); } } if (Rd == 15) { if (updateConditionCodes) - arm2ir.appendDynamicJump(result, lazy, BranchType.INDIRECT_BRANCH); + arm2ir.appendBranch(result, lazy, BranchType.INDIRECT_BRANCH); else - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + arm2ir.appendTraceExit(lazy, result); } else { arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); @@ -941,16 +941,15 @@ } else { OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); - arm2ir.appendInstruction(s); + arm2ir.appendCustomCall(s); } } if (Rd == 15) { - if (updateConditionCodes) - arm2ir.appendDynamicJump(result, lazy, BranchType.INDIRECT_BRANCH); + arm2ir.appendBranch(result, lazy, BranchType.INDIRECT_BRANCH); else - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + arm2ir.appendTraceExit(lazy, result); } else { arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); @@ -968,9 +967,9 @@ */ protected final void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { //set the carry flag to not(Borrow) + OPT_ConditionOperand notBorrowFromSub = OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(); arm2ir.appendInstruction(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); - arm2ir.appendInstruction(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); + BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, notBorrowFromSub, new OPT_BranchProfileOperand())); //set the overflow flag arm2ir.appendInstruction(BooleanCmp.create( @@ -1021,15 +1020,13 @@ setLogicalFlags(result); } else { OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); - arm2ir.appendInstruction(s); + arm2ir.appendCustomCall(s); } } - - if (Rd == 15) { if (updateConditionCodes) { - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + arm2ir.appendTraceExit(lazy, result); } else { BranchType branchType = BranchType.INDIRECT_BRANCH; @@ -1038,7 +1035,7 @@ if (opcode == Opcode.MOV && operand2.getType() == OperandWrapper.Type.Register && operand2.getRegister() == ARM_Registers.LR) branchType = BranchType.RETURN; - arm2ir.appendDynamicJump(result, lazy, branchType); + arm2ir.appendBranch(result, lazy, branchType); } } else { @@ -1284,6 +1281,7 @@ OPT_Operand operand1 = resolveOperand1(); OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2)); setSubFlags(result, operand1, operand2); } @@ -1302,6 +1300,7 @@ OPT_Operand operand1 = resolveOperand1(); OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstruction(Binary.create(INT_ADD, result, operand1, operand2)); setAddFlags(result, operand1, operand2); } @@ -1358,6 +1357,7 @@ OPT_RegisterOperand result = getResultRegister(); OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + arm2ir.appendInstruction(Unary.create(INT_NOT, tmp, operand2)); arm2ir.appendInstruction(Binary.create(INT_AND, result, operand1, tmp)); setLogicalResult(result); @@ -1494,7 +1494,7 @@ //This instruction gets very complex when forceUser is set, which is why we are interpreting that special and rare instruction if (forceUser) { arm2ir.appendInterpretedInstruction(pc, lazy); - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, arm2ir.getRegister(ARM_Registers.PC)); + arm2ir.appendTraceExit(lazy, arm2ir.getRegister(ARM_Registers.PC)); return; } @@ -1571,7 +1571,7 @@ switchToThumbBlock.insertOut(finishInstruction); OPT_Instruction call_setThumbMode = createCallToRegisters("setThumbMode", "(Z)V", 1); Call.setParam(call_setThumbMode, 1, new OPT_IntConstantOperand(1)); - arm2ir.appendInstruction(call_setThumbMode); + arm2ir.appendCustomCall(call_setThumbMode); arm2ir.appendInstruction(Goto.create(GOTO, finishInstruction.makeJumpTarget())); //No, don't switch to thumb mode @@ -1580,12 +1580,12 @@ arm2ir.appendInstruction(Binary.create(INT_AND, regPC, regPC, new OPT_IntConstantOperand(0xFFFFFFFE))); OPT_Instruction call_setArmMode = createCallToRegisters("setThumbMode", "(Z)V", 1); Call.setParam(call_setArmMode, 1, new OPT_IntConstantOperand(0)); - arm2ir.appendInstruction(call_setArmMode); + arm2ir.appendCustomCall(call_setArmMode); arm2ir.appendInstruction(Goto.create(GOTO, finishInstruction.makeJumpTarget())); //according to the APCS, these types of instructions are usually function returns arm2ir.setCurrentBlock(finishInstruction); - arm2ir.appendDynamicJump(regPC, lazy, BranchType.RETURN); + arm2ir.appendBranch(regPC, lazy, BranchType.RETURN); return; } } else { @@ -1658,9 +1658,12 @@ if (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(); + } - arm2ir.getCurrentBlock().deleteNormalOut(); - arm2ir.appendGoto(pc + getOffset() + 8, lazy, link ? BranchType.CALL : BranchType.DIRECT_BRANCH); + arm2ir.appendBranch(pc + getOffset() + 8, lazy, link ? BranchType.CALL : BranchType.DIRECT_BRANCH); } public int getSuccessor(int pc) { @@ -1718,11 +1721,11 @@ //set the correct processor mode (thumb or not) OPT_Instruction s = createCallToRegisters("setThumbMode", "(Z)V", 1); Call.setParam(s, 1, enableThumb); - arm2ir.appendInstruction(s); + arm2ir.appendCustomCall(s); //jump to the target address. Because we might have switched to thumb mode, we are //ending the trace with this method - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, targetAddress); + arm2ir.appendTraceExit(lazy, targetAddress); } public int getSuccessor(int pc) { @@ -1856,7 +1859,7 @@ } Call.setResult(call, psrValue); - arm2ir.appendInstruction(call); + arm2ir.appendCustomCall(call); } public int getSuccessor(int pc) { @@ -1892,7 +1895,7 @@ public void translate() { arm2ir.appendSystemCall(lazy, pc); - arm2ir.appendDynamicJump(arm2ir.getRegister(ARM_Registers.PC), lazy, BranchType.INDIRECT_BRANCH); + arm2ir.appendBranch(arm2ir.getRegister(ARM_Registers.PC), lazy, BranchType.INDIRECT_BRANCH); } public int getSuccessor(int pc) { @@ -1957,12 +1960,12 @@ currentOperatingMode = arm2ir.getTempOperatingMode(); Call.setResult(call_getOperatingMode, currentOperatingMode); - arm2ir.appendInstruction(call_getOperatingMode); + arm2ir.appendCustomCall(call_getOperatingMode); OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1); Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, arm2ir.getTempOperatingMode(OperatingMode.USR)); - arm2ir.appendInstruction(call_setOperatingModeWithoutRegisterLayout); + arm2ir.appendCustomCall(call_setOperatingModeWithoutRegisterLayout); } //get the address of the memory, that we're supposed access @@ -2040,7 +2043,7 @@ if (forceUserMode) { OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1); Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, currentOperatingMode); - arm2ir.appendInstruction(call_setOperatingModeWithoutRegisterLayout); + arm2ir.appendCustomCall(call_setOperatingModeWithoutRegisterLayout); } //should the memory address, which we accessed, be written back into a register? @@ -2060,7 +2063,7 @@ if (isLoad && Rd == ARM_Registers.PC) { //we are actually loading to the program counter here - arm2ir.appendDynamicJump(arm2ir.getRegister(Rd), lazy, BranchType.INDIRECT_BRANCH); + arm2ir.appendBranch(arm2ir.getRegister(Rd), lazy, BranchType.INDIRECT_BRANCH); } } Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) @@ -8,9 +8,11 @@ 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.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; import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; import org.vmmagic.pragma.Uninterruptible; @@ -37,7 +39,11 @@ protected ARM_ProcessSpace() { registers = new ARM_Registers(); - memory = new DebugMemory(); + + if (DBT_Options.buildForSunVM) + memory = new DebugMemory(); + else + memory = new ByteAddressedMemory(); } /** @@ -48,8 +54,8 @@ * the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { - return new ARM2IR(context); + public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + return new ARM2IR(context, trace); } /** Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-05-18 17:13:21 UTC (rev 123) @@ -17,6 +17,7 @@ import org.binarytranslator.generic.decoder.AbstractCodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; +import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_FieldReference; import org.jikesrvm.classloader.VM_MemberReference; @@ -253,8 +254,8 @@ * Construct the PPC2IR object for the generation context; then we'll be ready * to start generating the HIR. */ - public PPC2IR(OPT_GenerationContext context) { - super(context); + public PPC2IR(OPT_GenerationContext context, DBT_Trace trace) { + super(context, trace); // Create register maps PPC -> OPT_Register intRegMap = new OPT_Register[32]; intRegInUseMap = new boolean[32]; Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-18 17:13:21 UTC (rev 123) @@ -4026,7 +4026,7 @@ branchAddress = ppc2ir.getLRRegister(); } - ppc2ir.appendDynamicJump(branchAddress, lazy, BranchLogic.BranchType.RETURN); + ppc2ir.appendBranch(branchAddress, lazy, BranchLogic.BranchType.RETURN); // stop translation on branch always if (BO == 0x14) { @@ -4672,7 +4672,7 @@ } OPT_RegisterOperand branchAddress = ppc2ir.getCTRRegister(); - ppc2ir.appendDynamicJump(branchAddress, lazy, BranchType.INDIRECT_BRANCH); + ppc2ir.appendBranch(branchAddress, lazy, BranchType.INDIRECT_BRANCH); // stop translation on branch always @@ -11705,7 +11705,7 @@ if ((LK == 0) || ppc2ir.traceContinuesAfterBranchAndLink(pc)) { // Plant branch block - ppc2ir.appendGoto(target_address, lazy, LK != 0 ? BranchType.CALL : BranchType.DIRECT_BRANCH); + ppc2ir.appendBranch(target_address, lazy, LK != 0 ? BranchType.CALL : BranchType.DIRECT_BRANCH); // stop translation on branch always if (BO == 0x14) { @@ -11724,14 +11724,14 @@ ppc2ir.setCurrentBlock(instructionEndBlock); ppc2ir.setNextBlock(ppc2ir.createBlockAfterCurrent()); - ppc2ir.appendGoto(pc + 4, lazy, BranchType.DIRECT_BRANCH); + ppc2ir.appendBranch(pc + 4, lazy, BranchType.DIRECT_BRANCH); return target_address; } } } else { // This was a branch and link and the trace should stop, so end // gracefully - ppc2ir.appendGoto(target_address, lazy, BranchType.CALL); + ppc2ir.appendBranch(target_address, lazy, BranchType.CALL); return -1; } } @@ -11804,7 +11804,7 @@ if (ppc2ir.traceContinuesAfterBranchAndLink(pc)) { return target_addr; } else { - ppc2ir.setReturnValueResolveLazinessAndBranchToFinish( + ppc2ir.appendTraceExit( (PPC_Laziness) lazy.clone(), new OPT_IntConstantOperand(target_addr)); return -1; Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) @@ -20,6 +20,7 @@ import org.binarytranslator.generic.os.loader.Loader; import org.binarytranslator.generic.os.process.ProcessSpace; 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; @@ -139,8 +140,8 @@ * the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { - return new PPC2IR(context); + public OPT_HIRGenerator createHIRGenerator(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-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/x86/decoder/X862IR.java 2007-05-18 17:13:21 UTC (rev 123) @@ -16,6 +16,7 @@ import org.binarytranslator.generic.decoder.AbstractCodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.vmInterface.DBT_OptimizingCompilerException; +import org.binarytranslator.vmInterface.DBT_Trace; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_BootstrapClassLoader; import org.jikesrvm.classloader.VM_FieldReference; @@ -100,8 +101,8 @@ /** * Constructor */ - public X862IR(OPT_GenerationContext context) { - super(context); + public X862IR(OPT_GenerationContext context, DBT_Trace trace) { + super(context, trace); // Create the registers SegReg = new OPT_Register[6]; @@ -147,7 +148,7 @@ appendInstruction(Binary.create(INT_ADD, esp, esp.copyRO(), new OPT_IntConstantOperand(4))); // Branch - setReturnValueResolveLazinessAndBranchToFinish((X86_Laziness) lazy.clone(), temp.copyRO()); + appendTraceExit((X86_Laziness) lazy.clone(), temp.copyRO()); return -1; } Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-05-18 17:13:21 UTC (rev 123) @@ -3649,7 +3649,7 @@ stack.writeValue(translationHelper, lazy, temp.copyRO()); // Branch - translationHelper.appendDynamicJump(destOp.copyRO(), lazy, BranchType.CALL); + translationHelper.appendBranch(destOp.copyRO(), lazy, BranchType.CALL); return -1; } @@ -3770,7 +3770,7 @@ translationHelper.appendInstruction(Binary.create(INT_ADD, esp, esp.copyRO(), new OPT_IntConstantOperand(4 + immediate))); // Branch - translationHelper.setReturnValueResolveLazinessAndBranchToFinish( + translationHelper.appendTraceExit( (X86_Laziness) lazy.clone(), temp.copyRO()); return -1; } @@ -4035,7 +4035,7 @@ translationHelper.appendInstruction(gotoInstr); translationHelper.setCurrentBlock(executeBranch); - translationHelper.appendGoto(target_address, lazy, BranchType.DIRECT_BRANCH); + translationHelper.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); translationHelper.setCurrentBlock(fallThrough); return pc + length; @@ -4169,7 +4169,7 @@ if (modrm == null) { target_address = absolute ? immediate : pc + length + immediate; translationHelper.getCurrentBlock().deleteNormalOut(); - translationHelper.appendGoto(target_address, lazy, BranchType.DIRECT_BRANCH); + translationHelper.appendBranch(target_address, lazy, BranchType.DIRECT_BRANCH); } else { int operandSize; if (prefix3 == null) { @@ -4210,7 +4210,7 @@ * ppc2ir.setCurrentBlock(fallThrough); * ppc2ir.plantRecordUncaughtBcctr(pc, branchAddress.copyRO()); */ - translationHelper.setReturnValueResolveLazinessAndBranchToFinish( + translationHelper.appendTraceExit( (X86_Laziness) lazy.clone(), branchAddress.copyRO()); } return -1; Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-05-18 17:13:21 UTC (rev 123) @@ -19,7 +19,6 @@ import org.binarytranslator.generic.memory.ByteAddressedMemory; import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.fault.BadInstructionException; -import org.binarytranslator.arch.ppc.decoder.PPC_InstructionDecoder; import org.binarytranslator.arch.x86.os.process.linux.X86_LinuxProcessSpace; import org.binarytranslator.arch.x86.decoder.X862IR; import org.binarytranslator.arch.x86.decoder.X86_InstructionDecoder; @@ -150,8 +149,8 @@ * @param context the generation context for the HIR generation * @return a HIR generator */ - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { - return new X862IR(context); + public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context, DBT_Trace trace) { + return new X862IR(context, trace); } /** Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-18 17:13:21 UTC (rev 123) @@ -21,6 +21,7 @@ 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; @@ -75,30 +76,22 @@ */ public abstract class AbstractCodeTranslator implements OPT_Constants, OPT_Operators { - /** - * VM_TypeReference of org.binarytranslator.generic.os.process.ProcessSpace - */ + /** 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 - */ + /** 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> - */ + /** Method BadInstructionException.<init> */ public static final VM_Method badInstrKlassInitMethod; - /** - * Method ProcessSpace.recordUncaughtBranchBadInstructionException.<init> - */ + /** Method ProcessSpace.recordUncaughtBranchBadInstructionException.<init> */ public static final VM_Method recordUncaughtBranchMethod; static { @@ -165,20 +158,25 @@ 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) { + public UnresolvedJumpInstruction(OPT_Instruction instruction, Laziness lazyStateAtJump, int pc, BranchType type) { this.instruction = instruction; this.lazyStateAtJump = lazyStateAtJump; this.pc = pc; + this.type = type; } } - /** List of unresolved Goto instructions */ - private final ArrayList<UnresolvedJumpInstruction> unresolvedGoto; - + /** + * 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 jumps */ - private final ArrayList<UnresolvedJumpInstruction> unresolvedDynamicJumps; + /** + * List of unresolved dynamic branches. Dynamics branches have a destination address that is only + * determined at runtime. */ + private final ArrayList<UnresolvedJumpInstruction> unresolvedDynamicBranches; /** * Constructor @@ -186,7 +184,11 @@ * @param context * The JRVM generation context for this trace. */ - protected AbstractCodeTranslator(OPT_GenerationContext context) { + 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; @@ -202,14 +204,12 @@ // Create preFillBlock, currentBlock and finishBlock gc.prologue.insertOut(gc.epilogue); preFillBlock = createBlockAfter(gc.prologue); - currentBlock = createBlockAfter(preFillBlock); - finishBlock = createBlockAfterCurrent(); // Fix up stores - unresolvedGoto = new ArrayList<UnresolvedJumpInstruction>(); - unresolvedDynamicJumps = new ArrayList<UnresolvedJumpInstruction>(); + unresolvedDirectBranches = new ArrayList<UnresolvedJumpInstruction>(); + unresolvedDynamicBranches = new ArrayList<UnresolvedJumpInstruction>(); } /** Returns the number of previously translated instructions within this trace. */ @@ -227,27 +227,19 @@ // Translating the subtrace finished so resolve any unresolved // branches - do { - if (DBT_Options.resolveProceduresBeforeBranches) { - resolveAllDynamicJumpTargets(); - } - if (DBT_Options.resolveBranchesAtOnce) { - do { - resolveGoto(); - - } while (unresolvedGoto.size() != 0); - } else { - resolveGoto(); - - } - if (!DBT_Options.resolveProceduresBeforeBranches) { - resolveAllDynamicJumpTargets(); - } - } while (((unresolvedGoto.size() == 0) - && areDynamicJumpsReadyToResolve()) == false); + if (!DBT_Options.resolveDirectBranchesFirst) { + resolveAllDynamicBranchTargets(); + } + //Resolve all open direct first + resolveAllDirectBranches(); + + if (DBT_Options.resolveDirectBranchesFirst) { + resolveAllDynamicBranchTargets(); + } + // Resolve unresolved dynamic jumps - resolveDynamicJumps(); + resolveDynamicBranches(); // Finish up the trace finishTrace(); @@ -265,13 +257,13 @@ */ private void translateSubTrace(Laziness lazy, int pc) { currentPC = pc; - if (suitableToStop()) { + 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 - setReturnValueResolveLazinessAndBranchToFinish(lazy, + appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); // Move currentBlock along currentBlock = nextBlock; @@ -279,6 +271,7 @@ do { if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfRealInstructions() == 0); + // Record mapping of this pc value and laziness to this block registerMapping(pc, lazy, currentBlock); @@ -292,14 +285,14 @@ // 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) { - setReturnValueResolveLazinessAndBranchToFinish(lazy, - new OPT_IntConstantOperand(pc)); + appendTraceExit(lazy, new OPT_IntConstantOperand(pc)); } break; @@ -377,16 +370,22 @@ 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));*/ - currentBlock.deleteOut(nxtBlock); - currentBlock.insertOut(newBlock); - newBlock.insertOut(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; } @@ -527,88 +526,69 @@ * @param branchType * The type of branch that best describes this jump. */ - public void appendGoto(int targetPC, Laziness targetLaziness, BranchType branchType) { + public void appendBranch(int targetPC, Laziness targetLaziness, BranchType branchType) { - //see if we already compiled the target address - OPT_BasicBlock target = findMapping(targetPC, targetLaziness); + //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); + unresolvedDirectBranches.add(unresolvedJump); - //if yes, just jump directly to it - if (target != null) { + //Notify the branch profile about certain types of branches + switch (branchType) { + case CALL: + ps.branchInfo.registerCall(currentPC, targetPC); + return; - if (DBT_Options.debugBranchResolution) - System.out.println(String.format("Found precompiled mapping for pc 0x%x: %s", targetPC, target)); - - OPT_Instruction jump = Goto.create(GOTO, target.makeJumpTarget()); - getCurrentBlock().insertOut(target); - appendInstruction(jump); - } - else { - //otherwise, we have to decide whether to compile that address into the trace or to compile - //it as a separate trace. We use the branchType hint for that... - - switch (branchType) { - case CALL: - //exit the trace on a call - ps.branchInfo.registerCall(currentPC, targetPC); - setReturnValueResolveLazinessAndBranchToFinish(targetLaziness, new OPT_IntConstantOperand(targetPC)); - break; - - case RETURN: - //exit the trace - ps.branchInfo.registerReturn(currentPC, targetPC); - setReturnValueResolveLazinessAndBranchToFinish(targetLaziness, new OPT_IntConstantOperand(targetPC)); - break; + case RETURN: + ps.branchInfo.registerReturn(currentPC, targetPC); + return; - default: - //compile the jump directly into the trace. - OPT_Instruction jump = Goto.create(GOTO, null); - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(jump, (Laziness)targetLaziness.clone(), targetPC); - unresolvedGoto.add(unresolvedJump); - } + default: + return; } - - } - /** Resolve a single goto instruction */ - private void resolveGoto() { + /** Resolve all unresolved direct branch instructions. */ + private void resolveAllDirectBranches() { - if (unresolvedGoto.size() == 0) - return; + for (int i = 0; i < unresolvedDirectBranches.size(); i++) { - //Get the jump that we're supposed to resolve - UnresolvedJumpInstruction unresolvedInstr = unresolvedGoto.remove(unresolvedGoto.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 = resolveJumpTarget(targetPc, lazyStateAtJump); - - if (DBT_Options.debugBranchResolution) { - report("Resolving goto " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); + //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_Options.debugBranchResolution) { + 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); + } } - - // Fix up instruction - Goto.setTarget(gotoInstr, targetBB.makeJumpTarget()); - gotoInstr.getBasicBlock().insertOut(targetBB); - - if (DBT.VerifyAssertions) DBT._assert(gotoInstr.getBasicBlock().getNumberOfNormalOut() == 1); - - if (DBT_Options.debugBranchResolution) { - report("Properly resolving goto in block " - + gotoInstr.getBasicBlock() + " to " + lazyStateAtJump.makeKey(targetPc) + " " - + targetBB); - } } /** - * Resolves a jump target to an actual basic block. This method usually tries to compile the trace - * for any target addresses that have not yet been compiled. However, when - * {@link DBT_Options#singleInstrTranslation} is turned on, then this method will end the curren trace, - * just returning the address of the next instruction. + * 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 lazyStateAtJump @@ -617,28 +597,42 @@ * A basic block that is equivalent to the program counter address <code>targetPc</code> in the * original binary. */ - private OPT_BasicBlock resolveJumpTarget(int targetPc, Laziness lazyStateAtJump) { + private OPT_BasicBlock resolveBranchTarget(int targetPc, Laziness lazyStateAtJump, BranchType branchtype) { //Resolve the address of the target block - OPT_BasicBlock targetBB; - if (DBT_Options.singleInstrTranslation == true) { - //In Single instruction mode, the target block just ends the trace + OPT_BasicBlock targetBB = findMapping(targetPc, 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) { + + //Just exit the trace and continue at the target address in a new trace if (currentBlock.getNumberOfRealInstructions() != 0) { currentBlock = createBlockAfterCurrentNotInCFG(); - System.out.println("Resolving branch to next block."); + + if (DBT_Options.debugBranchResolution) System.out.println("Resolving branch to next block."); } targetBB = currentBlock; - setReturnValueResolveLazinessAndBranchToFinish(lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); - } + appendTraceExit(lazyStateAtJump, new OPT_IntConstantOperand(targetPc)); + registerMapping(targetPc, lazyStateAtJump, targetBB); + } else { - //Try to find if block has now been translated + //Otherwise we will translate the jump into the trace + translateSubTrace((Laziness) lazyStateAtJump.clone(), targetPc); targetBB = findMapping(targetPc, lazyStateAtJump); - - if (targetBB == null) { - // Block not translated so translate - translateSubTrace((Laziness) lazyStateAtJump.clone(), targetPc); - targetBB = findMapping(targetPc, lazyStateAtJump); - } } if (DBT.VerifyAssertions) DBT._assert(targetBB != null); @@ -647,26 +641,23 @@ } /** - * Resolves all dynamic jumps that have been added with - * {@link #appendDynamicJump(OPT_RegisterOperand, Laziness, BranchType)}. + * Resolves all dynamic branches that have been added with + * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. */ - private void resolveDynamicJumps() { + private void resolveDynamicBranches() { - for (int i = 0; i < unresolvedDynamicJumps.size(); i++) { + for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicJumps.get(i); - - Laziness lazy = unresolvedSwitch.lazyStateAtJump; - OPT_Instruction lookupswitch = unresolvedSwitch.instruction; + UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicBranches.get(i); Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - resolveSingleDynamicJump(lazy, lookupswitch, branchDests); + resolveSingleDynamicJump(unresolvedSwitch, branchDests); } } /** * Resolves a single dynamic jump that has previously been created with - * {@link #appendDynamicJump(OPT_RegisterOperand, Laziness, BranchType)}. + * {@link #appendBranch(OPT_RegisterOperand, Laziness, BranchType)}. * * @param lazy * The lazy state of the jump that is to be resolved. @@ -675,7 +666,11 @@ * @param destinations * A list of known destinations that this dynamic jumps branches to. */ - private void resolveSingleDynamicJump(Laziness lazy, OPT_Instruction lookupswitch, Set<Integer> destinations) throws Error { + 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); @@ -691,28 +686,19 @@ int match_no = 0; for (int dest_pc : destinations) { - OPT_BasicBlock target = findMapping(dest_pc, lazy); - if (target == null) { - throw new Error("Failed to find trace for " + dest_pc - + " with laziness " + lazy); - } - 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 = findMapping(dest_pc, lazy); - if (target == null) { - throw new Error("Failed to find trace for " + dest_pc - + " with laziness " + lazy); - } + 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(), @@ -725,7 +711,6 @@ } } - /** * Append a dynamic jump (a jump whose target address is not known at translation time) to the * current basic block. @@ -737,100 +722,71 @@ * @param branchType * The type of jump. */ - public void appendDynamicJump(OPT_RegisterOperand targetAddress, Laziness lazyStateAtJump, BranchType branchType) { + 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); - unresolvedDynamicJumps.add(unresolvedInfo); + UnresolvedJumpInstruction unresolvedInfo = new UnresolvedJumpInstruction(switchInstr, (Laziness)lazyStateAtJump.clone(), currentPC, branchType); + unresolvedDynamicBranches.add(unresolvedInfo); setCurrentBlock(fallThrough); appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType); - setReturnValueResolveLazinessAndBranchToFinish((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); + appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress.copyRO()); } /** - * Checks if all dynamic jumps are ready to be resolved (because their target blocks have - * been resolved). - * - * @return - * True if all dynamic jumps can be resolved, false otherwise. - */ - private boolean areDynamicJumpsReadyToResolve() { - for (int i = 0; i < unresolvedDynamicJumps.size(); i++) { - - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicJumps.get(i); - Laziness lazy = unresolvedSwitch.lazyStateAtJump; - Set<Integer> branchDests = getLikelyJumpTargets(unresolvedSwitch.pc); - - if (branchDests != null) { - for (int dest_pc : branchDests) { - if (findMapping(dest_pc, lazy) == null) { - return false; - } - } - } - } - return true; - } - - /** * Resolves all dynamic jump targets by making sure the respective basic blocks exist. */ - private void resolveAllDynamicJumpTargets() { - for (int i = 0; i < unresolvedDynamicJumps.size(); i++) { + private void resolveAllDynamicBranchTargets() { + for (int i = 0; i < unresolvedDynamicBranches.size(); i++) { - UnresolvedJumpInstruction unresolvedSwitch = unresolvedDynamicJumps.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) { - if (findMapping(dest_pc, lazy) == null) { - // Block not translated so translate - translateSubTrace((Laziness) lazy.clone(), dest_pc); - } + resolveBranchTarget(dest_pc, lazy, unresolvedSwitch.type); } } } } - - /** * 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 value + * @param nextPc * return value for translated code (the PC value of the next * instruction to translate) */ - public void setReturnValueResolveLazinessAndBranchToFinish(Laziness laziness, - OPT_Operand value) { + public void appendTraceExit(Laziness laziness, OPT_Operand nextPc) { - nextBlock = createBlockAfterCurrent(); + //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), value)); + appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(gc.resultReg, VM_TypeReference.Int), nextPc)); resolveLaziness(laziness); - appendInstruction(Goto.create(GOTO, finishBlock - .makeJumpTarget())); + appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget())); currentBlock.deleteNormalOut(); currentBlock.insertOut(finishBlock); if (DBT.VerifyAssertions) DBT._assert(currentBlock.getNumberOfNormalOut() == 1); - currentBlock = nextBlock; + + //currentBlock = nextBlock; } /** - * Is it suitable to stop the trace now? + * 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 suitableToStop() { + protected boolean shallTraceStop() { if (DBT_Options.singleInstrTranslation && (numberOfInstructions >= 1)) { return true; } else { @@ -880,7 +836,7 @@ * @return whether the trace should continue */ public boolean traceContinuesAfterBranchAndLink(int pc) { - return suitableToStop() == false; + return shallTraceStop() == false; } /** @@ -1015,7 +971,7 @@ appendInstruction(t); - setReturnValueResolveLazinessAndBranchToFinish(lazy, + appendTraceExit(lazy, new OPT_IntConstantOperand(0xEBADC0DE)); } @@ -1312,6 +1268,37 @@ while (block != null && count-- > 0); } + /** + * Appends an call instruction the current trace. + * + * @param callInstruction + * The call instruction that shall be added to the current block. + */ + public void appendCustomCall(OPT_Instruction callInstruction) { + if (DBT.VerifyAssertions) DBT._assert(Call.conforms(callInstruction)); + + OPT_MethodOperand methOp = Call.getMethod(callInstruction); + VM_MethodReference methodRef = methOp.getMemberRef().asMethodReference(); + int callType; + + if (methOp.isVirtual()) + callType = VM_BytecodeConstants.JBC_invokespecial; + else + if (methOp.isInterface()) + callType = VM_BytecodeConstants.JBC_invokeinterface; + else + if (methOp.isSpecial()) + callType = VM_BytecodeConstants.JBC_invokespecial; + else + throw new RuntimeException("Unknown call type in call to appendCustomCall()."); + + trace.registerDynamicLink(methodRef, callType); + + //append the instruction to the current block + callInstruction.position = gc.inlineSequence; + appendInstruction(callInstruction); + } + /** Report some debug output */ protected abstract void report(String str); Added: src/org/binarytranslator/generic/decoder/CodeCache.java =================================================================== --- src/org/binarytranslator/generic/decoder/CodeCache.java (rev 0) +++ src/org/binarytranslator/generic/decoder/CodeCache.java 2007-05-18 17:13:21 UTC (rev 123) @@ -0,0 +1,39 @@ +package org.binarytranslator.generic.decoder; + +import java.util.WeakHashMap; + +import org.binarytranslator.vmInterface.DBT_Trace; + +/** Caches traces and the PC - addresses that they start from. */ +public class CodeCache { + + /** Stores the cached traces. The address at which the trace starts is used as the key. */ + private WeakHashMap<Integer, DBT_Trace> codeSnippets = new WeakHashMap<Integer, DBT_Trace>(); + + /** + * Adds a trace to the codecache. + * @param pc + * The address at which the trace starts. + * @param trace + * The cached trace. + */ + public void add(int pc, DBT_Trace trace) { + + if (codeSnippets.containsKey(pc)) + throw new RuntimeException("The codecache already contains a translation for 0x" + Integer.toHexString(pc)); + + codeSnippets.put(pc, trace); + } + + /** + * Try to retrieve a cached version of a trace starting at <code>pc</code>. + * @param pc + * The address at which the sought trace starts. + * @return + * A trace that starts at <code>pc</code> or null if the cache does not contain + * such a trace. + */ + public DBT_Trace tryGet(int pc) { + return codeSnippets.get(pc); + } +} Modified: src/org/binarytranslator/generic/execution/DynamicTranslationController.java =================================================================== --- src/org/binarytranslator/generic/execution/DynamicTranslationController.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/generic/execution/DynamicTranslationController.java 2007-05-18 17:13:21 UTC (rev 123) @@ -1,7 +1,5 @@ package org.binarytranslator.generic.execution; -import java.util.Hashtable; - import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.fault.BadInstructionException; import org.binarytranslator.generic.os.process.ProcessSpace; @@ -16,13 +14,8 @@ */ public class DynamicTranslationController extends ExecutionController { - /** Caches pre-translated code and uses the starting address of the code on the subject machine as a key*/ - private final Hashtable<Integer, DBT_Trace> codeHash; - public DynamicTranslationController(ProcessSpace ps) { super(ps); - - codeHash = new Hashtable<Integer, DBT_Trace>(); } @Override @@ -51,7 +44,7 @@ * An executable VM_CodeArray, which contains a trace starting at the given address. */ private VM_CodeArray getCodeForPC(int pc) { - DBT_Trace trace = codeHash.get(pc); + DBT_Trace trace = ps.codeCache.tryGet(pc); if (trace == null) { trace = translateCode(pc); @@ -81,9 +74,9 @@ // compile the given trace trace.compile(); - // store the compiled code in code hash - codeHash.put(trace.pc, trace); - + // store the compiled code in the code cache + ps.codeCache.add(pc, trace); + return trace; } } Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-05-17 22:26:48 UTC (rev 122) +++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-05-18 17:13:21 UTC (rev 123) @@ -9,6 +9,7 @@ package org.binarytranslator.generic.memory; import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.decoder.AbstractCodeTranslator; import org.binarytranslator.generic.os.process.ProcessSpace; import org.binarytranslator.vmInterface.DBT_Trace; @@ -118,39 +119,42 @@ */ protected CallBasedMemory(Class memoryClass) { //Debug initializations to run this stuff on SUN - /*memoryType = null; - loadS8 = loadU8 = loadS16 = loadU16 = load32 = null; - store8 = store16 = store32 = null;*/ - + if (DBT_Options.buildForSunVM) { + memoryType = null; + loadS8 = loadU8 = loadS16 = loadU16 = load32 = null; + store8 = store16 = store32 = null; + } + else { memoryType = VM_TypeReference.findOrCreate(memoryClass); - VM_Atom storeDescriptor = VM_Atom.findOrCreateAsciiAtom("(II)V"); - store8 = VM_MemberReference.findOrCreate(memoryType, - VM_Atom.findOrCreateAsciiAtom("store8"), storeDescriptor) - .asMethodReference().resolve(); - store16 = VM_MemberReference.findOrCreate(memoryType, - VM_Atom.findOrCreateAsciiAtom("store16"), storeDescriptor) - .asMethodReference().resolve(); - store32 = VM_MemberReference.findOrCreate(memoryType, - VM_Atom.findOrCreateAsciiAtom("store32"), storeDescriptor) - .asMethodReference().resolve(); + VM_Atom storeDescriptor = VM_Atom.findOrCreateAsciiAtom("(II)V"); + store8 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("store8"), storeDescriptor) + .asMethodReference().resolve(); + store16 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("store16"), storeDescriptor) + .asMethodReference().resolve(); + store32 = VM_MemberReference.findOrCreate(memoryType, + VM_Atom.findOrCreateAsciiAtom("store32"), storeDescriptor) + .asMethodReference().resolve(); - VM_Atom loadDescriptor = VM_Atom.findOrCreateAsciiAtom("(I)I"); - loadS8 = VM_MemberReference.findOrCreate(mem... [truncated message content] |
From: <mic...@us...> - 2007-05-17 22:26:47
|
Revision: 122 http://svn.sourceforge.net/pearcolator/?rev=122&view=rev Author: michael_baer Date: 2007-05-17 15:26:48 -0700 (Thu, 17 May 2007) Log Message: ----------- - Added further branch profile notifications for call & return instructions - Removed registration of unresolved IfCmps for code clarity 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/branch/BranchLogic.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-05-17 19:20:02 UTC (rev 121) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-17 22:26:48 UTC (rev 122) @@ -1660,7 +1660,7 @@ } arm2ir.getCurrentBlock().deleteNormalOut(); - arm2ir.appendGoto(pc + getOffset() + 8, lazy); + arm2ir.appendGoto(pc + getOffset() + 8, lazy, link ? BranchType.CALL : BranchType.DIRECT_BRANCH); } public int getSuccessor(int pc) { Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-17 19:20:02 UTC (rev 121) +++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-05-17 22:26:48 UTC (rev 122) @@ -11703,9 +11703,9 @@ BI, !branch_if_cond_true, likely_to_fallthrough); } - if ((LK == 0) || (ppc2ir.traceContinuesAfterBranchAndLink(pc))) { + if ((LK == 0) || ppc2ir.traceContinuesAfterBranchAndLink(pc)) { // Plant branch block - ppc2ir.appendGoto(target_address, lazy); + ppc2ir.appendGoto(target_address, lazy, LK != 0 ? BranchType.CALL : BranchType.DIRECT_BRANCH); // stop translation on branch always if (BO == 0x14) { @@ -11724,15 +11724,14 @@ ppc2ir.setCurrentBlock(instructionEndBlock); ppc2ir.setNextBlock(ppc2ir.createBlockAfterCurrent()); - ppc2ir.appendGoto(pc + 4, lazy); + ppc2ir.appendGoto(pc + 4, lazy, BranchType.DIRECT_BRANCH); return target_address; } } } else { // This was a branch and link and the trace should stop, so end // gracefully - ppc2ir.setReturnValueResolveLazinessAndBranchToFinish((PPC_Laziness) lazy - .clone(), new OPT_IntConstantOperand(target_address)); + ppc2ir.appendGoto(target_address, lazy, BranchType.CALL); return -1; } } Modified: src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java =================================================================== --- src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-05-17 19:20:02 UTC (rev 121) +++ src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java 2007-05-17 22:26:48 UTC (rev 122) @@ -11,6 +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.decoder.InstructionDecoder; import org.binarytranslator.generic.decoder.Laziness; import org.binarytranslator.generic.fault.BadInstructionException; @@ -3646,9 +3647,9 @@ translationHelper.appendInstruction(Move.create(INT_MOVE, temp, new OPT_IntConstantOperand(pc + length))); stack.writeValue(translationHelper, lazy, temp.copyRO()); + // Branch - translationHelper.setReturnValueResolveLazinessAndBranchToFinish( - (X86_Laziness) lazy.clone(), destOp.copyRO()); + translationHelper.appendDynamicJump(destOp.copyRO(), lazy, BranchType.CALL); return -1; } @@ -3917,7 +3918,8 @@ X86_Group4PrefixDecoder prefix4, X86_Group5PrefixDecoder prefix5) { // The destination for the branch int target_address = pc + length + immediate; - // Find a pre-translated version + + OPT_BasicBlock executeBranch = translationHelper.createBlockAfterCurrent(); OPT_BasicBlock fallThrough = translationHelper.createBlockAfterCurrent(); boolean branchLikely; if (prefix2 != null) { @@ -4027,11 +4029,14 @@ .getConditionalBranchProfileOperand(false)); } translationHelper.appendInstruction(boolcmp); - translationHelper.appendIfCmp(INT_IFCMP, translationHelper - .getTempValidation(0), temp.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), target_address, lazy, likelyOp); + translationHelper.appendInstruction(IfCmp.create(INT_IFCMP, translationHelper.getTempValidation(0), temp.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), executeBranch.makeJumpTarget(), likelyOp)); OPT_Instruction gotoInstr = Goto.create(GOTO, fallThrough.makeJumpTarget()); translationHelper.appendInstruction(gotoInstr); + + translationHelper.setCurrentBlock(executeBranch); + translationHelper.appendGoto(target_address, lazy, BranchType.DIRECT_BRANCH); + translationHelper.setCurrentBlock(fallThrough); return pc + length; } @@ -4164,7 +4169,7 @@ if (modrm == null) { target_address = absolute ? immediate : pc + length + immediate; translationHelper.getCurrentBlock().deleteNormalOut(); - translationHelper.appendGoto(target_address, lazy); + translationHelper.appendGoto(target_address, lazy, BranchType.DIRECT_BRANCH); } else { int operandSize; if (prefix3 == null) { Modified: src/org/binarytranslator/generic/branch/BranchLogic.java =================================================================== --- src/org/binarytranslator/generic/branch/BranchLogic.java 2007-05-17 19:20:02 UTC (rev 121) +++ src/org/binarytranslator/generic/branch/BranchLogic.java 2007-05-17 22:26:48 UTC (rev 122) @@ -23,6 +23,8 @@ public enum BranchType { INDIRECT_BRANCH, + DIRECT_BRANCH, + CALL, RETURN } @@ -56,12 +58,12 @@ * * @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 - * @param dest - * the destination of the branch instruction */ - public void registerCall(int pc, int ret, int dest) { + public void registerCall(int pc, int dest, int ret) { ProcedureInformation procedure = procedures.get(dest); if (procedure != null) { @@ -71,6 +73,18 @@ procedures.put(dest, procedure); } } + + /** + * 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 @@ -120,6 +134,21 @@ 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; + } + + //Perform the general branch registration, too Set<Integer> dests = branchSitesAndDestinations.get(origin); if (dests != null && dests.contains(target)) { Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-17 19:20:02 UTC (rev 121) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-17 22:26:48 UTC (rev 122) @@ -176,8 +176,6 @@ /** List of unresolved Goto instructions */ private final ArrayList<UnresolvedJumpInstruction> unresolvedGoto; - /** List of unresolved IfCmp instructions */ - private final ArrayList<UnresolvedJumpInstruction> unresolvedIfCmp; /** List of unresolved dynamic jumps */ private final ArrayList<UnresolvedJumpInstruction> unresolvedDynamicJumps; @@ -211,7 +209,6 @@ // Fix up stores unresolvedGoto = new ArrayList<UnresolvedJumpInstruction>(); - unresolvedIfCmp = new ArrayList<UnresolvedJumpInstruction>(); unresolvedDynamicJumps = new ArrayList<UnresolvedJumpInstruction>(); } @@ -237,16 +234,16 @@ if (DBT_Options.resolveBranchesAtOnce) { do { resolveGoto(); - resolveIfCmp(); - } while ((unresolvedGoto.size() != 0) || (unresolvedIfCmp.size() != 0)); + + } while (unresolvedGoto.size() != 0); } else { resolveGoto(); - resolveIfCmp(); + } if (!DBT_Options.resolveProceduresBeforeBranches) { resolveAllDynamicJumpTargets(); } - } while (((unresolvedGoto.size() == 0) && (unresolvedIfCmp.size() == 0) + } while (((unresolvedGoto.size() == 0) && areDynamicJumpsReadyToResolve()) == false); // Resolve unresolved dynamic jumps @@ -520,67 +517,6 @@ } /** - * Appends an IfCmp instruction to the current block that (when the condition is true) jumps - * to the address <code>targetPc</code>. The parameters for this function are mostly - * the same as for the {@link IfCmp#create(OPT_Operator, OPT_RegisterOperand, OPT_Operand, OPT_Operand, OPT_ConditionOperand, OPT_BranchOperand, OPT_BranchProfileOperand)} function. - * - * @param operator - * The HIR operator. - * @param guard - * A guard result for this call. - * @param lhs - * The left-hand-side comparision operator. - * @param rhs - * The right-hand-side comparision operator. - * @param condition - * The type of comparison that is to be executed. - * @param targetPc - * The address that the trace shall jump to, when the condition evaluates to true. - * @param targetLaziness - * The laziness at the point of jump. - * @param branchProfile - * A branch profile operand that describes how likely it is that the jump is executed. - */ - public void appendIfCmp(OPT_Operator operator, OPT_RegisterOperand guard, OPT_Operand lhs, - OPT_Operand rhs, OPT_ConditionOperand condition, int targetPc, Laziness targetLaziness, OPT_BranchProfileOperand branchProfile) { - - OPT_BasicBlock targetBlock = findMapping(targetPc, targetLaziness); - OPT_Instruction ifcmp = IfCmp.create(operator, guard, lhs, rhs, condition, null, branchProfile); - - if (targetBlock != null) { - IfCmp.setTarget(ifcmp, targetBlock.makeJumpTarget()); - getCurrentBlock().insertOut(targetBlock); - } - else { - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(ifcmp, (Laziness)targetLaziness.clone(), targetPc); - unresolvedIfCmp.add(unresolvedJump); - } - - appendInstruction(ifcmp); - } - - /** Resolve a single ifCmp instruction */ - private void resolveIfCmp() { - - if (unresolvedIfCmp.size() == 0) - return; - - //Try to find if block has now been translated - UnresolvedJumpInstruction instruction = unresolvedIfCmp.remove(unresolvedIfCmp.size() - 1); - - OPT_Instruction ifCmp = instruction.instruction; - - if (DBT.VerifyAssertions) DBT._assert(IfCmp.conforms(ifCmp)); - - //try to resolve the ifcmp's jump target - OPT_BasicBlock targetBB = resolveJumpTarget(instruction.pc, instruction.lazyStateAtJump); - - //Fix up the instruction - IfCmp.setTarget(ifCmp, targetBB.makeJumpTarget()); - ifCmp.getBasicBlock().insertOut(targetBB); - } - - /** * 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. * @@ -588,27 +524,50 @@ * 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 appendGoto(int targetPC, Laziness targetLaziness) { + public void appendGoto(int targetPC, Laziness targetLaziness, BranchType branchType) { - OPT_Instruction jump; + //see if we already compiled the target address OPT_BasicBlock target = findMapping(targetPC, targetLaziness); + //if yes, just jump directly to it if (target != null) { if (DBT_Options.debugBranchResolution) System.out.println(String.format("Found precompiled mapping for pc 0x%x: %s", targetPC, target)); - jump = Goto.create(GOTO, target.makeJumpTarget()); + OPT_Instruction jump = Goto.create(GOTO, target.makeJumpTarget()); getCurrentBlock().insertOut(target); + appendInstruction(jump); } else { - jump = Goto.create(GOTO, null); - UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(jump, (Laziness)targetLaziness.clone(), targetPC); - unresolvedGoto.add(unresolvedJump); + //otherwise, we have to decide whether to compile that address into the trace or to compile + //it as a separate trace. We use the branchType hint for that... + + switch (branchType) { + case CALL: + //exit the trace on a call + ps.branchInfo.registerCall(currentPC, targetPC); + setReturnValueResolveLazinessAndBranchToFinish(targetLaziness, new OPT_IntConstantOperand(targetPC)); + break; + + case RETURN: + //exit the trace + ps.branchInfo.registerReturn(currentPC, targetPC); + setReturnValueResolveLazinessAndBranchToFinish(targetLaziness, new OPT_IntConstantOperand(targetPC)); + break; + + default: + //compile the jump directly into the trace. + OPT_Instruction jump = Goto.create(GOTO, null); + UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(jump, (Laziness)targetLaziness.clone(), targetPC); + unresolvedGoto.add(unresolvedJump); + } } - appendInstruction(jump); + } /** Resolve a single goto instruction */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-17 19:20:16
|
Revision: 121 http://svn.sourceforge.net/pearcolator/?rev=121&view=rev Author: michael_baer Date: 2007-05-17 12:20:02 -0700 (Thu, 17 May 2007) Log Message: ----------- - Fixed in the generation of ARM_Laziness instances - Added a command line option to debug the resolution of branches Modified Paths: -------------- src/org/binarytranslator/DBT_Options.java src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java Modified: src/org/binarytranslator/DBT_Options.java =================================================================== --- src/org/binarytranslator/DBT_Options.java 2007-05-17 16:31:37 UTC (rev 120) +++ src/org/binarytranslator/DBT_Options.java 2007-05-17 19:20:02 UTC (rev 121) @@ -105,9 +105,9 @@ public static boolean debugInstr = true; /** - * In PPC2IR, print information about lazy resolution... + * Print information about the lazy resolution of branch addresses... */ - public final static boolean debugLazy = false; + public static boolean debugBranchResolution = true; /** * In PPC2IR, print cfg. @@ -213,6 +213,8 @@ debugInstr = Boolean.parseBoolean(value); } else if (arg.equalsIgnoreCase("-X:dbt:debugRuntime")) { debugRuntime = Boolean.parseBoolean(value); + } else if (arg.equalsIgnoreCase("-X:dbt:debugBranchResolution")) { + debugBranchResolution = 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/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-17 16:31:37 UTC (rev 120) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-17 19:20:02 UTC (rev 121) @@ -376,20 +376,6 @@ } /** - * Prints the given BasicBlock and the <code>count</code> blocks following it in code order. - * @param block - * @param count - */ - public void printNextBlocks(OPT_BasicBlock block, int count) { - do - { - block.printExtended(); - block = block.nextBasicBlockInCodeOrder(); - } - while (block != null && count-- > 0); - } - - /** * Adds code to the current block that will rotate <code>rotatedOperand</code> by * <code>rotation</code> and stores the rotated integer into <code>result</code>. * @param result Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-05-17 16:31:37 UTC (rev 120) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-05-17 19:20:02 UTC (rev 121) @@ -4,22 +4,39 @@ public class ARM_Laziness extends Laziness { + final class ARM_LazinessKey extends Key { + private final int pc; + + public int hashCode() { + return pc; + } + + public boolean equals(Object o) { + return ((o instanceof ARM_LazinessKey) && ((ARM_LazinessKey) o).pc == pc); + } + + ARM_LazinessKey(int pc) { + this.pc = pc; + } + + public String toString() { + return "0x" + Integer.toHexString(pc); + } + } + @Override public Object clone() { - // TODO Auto-generated method stub - return null; + return new ARM_Laziness(); } @Override public boolean equivalent(Laziness other) { - // TODO Auto-generated method stub - return false; + return other instanceof ARM_Laziness; } @Override public Key makeKey(int pc) { - // TODO Auto-generated method stub - return null; + return new ARM_LazinessKey(pc); } } Modified: src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java =================================================================== --- src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-17 16:31:37 UTC (rev 120) +++ src/org/binarytranslator/generic/decoder/AbstractCodeTranslator.java 2007-05-17 19:20:02 UTC (rev 121) @@ -238,7 +238,7 @@ do { resolveGoto(); resolveIfCmp(); - } while (((unresolvedGoto.size() == 0) && (unresolvedIfCmp.size() == 0)) == false); + } while ((unresolvedGoto.size() != 0) || (unresolvedIfCmp.size() != 0)); } else { resolveGoto(); resolveIfCmp(); @@ -304,6 +304,7 @@ setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc)); } + break; } @@ -594,6 +595,10 @@ OPT_BasicBlock target = findMapping(targetPC, targetLaziness); if (target != null) { + + if (DBT_Options.debugBranchResolution) + System.out.println(String.format("Found precompiled mapping for pc 0x%x: %s", targetPC, target)); + jump = Goto.create(GOTO, target.makeJumpTarget()); getCurrentBlock().insertOut(target); } @@ -622,18 +627,17 @@ OPT_BasicBlock targetBB = resolveJumpTarget(targetPc, lazyStateAtJump); - if (DBT_Options.debugLazy) { + if (DBT_Options.debugBranchResolution) { report("Resolving goto " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); } // Fix up instruction Goto.setTarget(gotoInstr, targetBB.makeJumpTarget()); - gotoInstr.getBasicBlock().deleteNormalOut(); gotoInstr.getBasicBlock().insertOut(targetBB); if (DBT.VerifyAssertions) DBT._assert(gotoInstr.getBasicBlock().getNumberOfNormalOut() == 1); - if (DBT_Options.debugLazy) { + if (DBT_Options.debugBranchResolution) { report("Properly resolving goto in block " + gotoInstr.getBasicBlock() + " to " + lazyStateAtJump.makeKey(targetPc) + " " + targetBB); @@ -661,6 +665,7 @@ //In Single instruction mode, the target block just ends the trace if (currentBlock.getNumberOfRealInstructions() != 0) { currentBlock = createBlockAfterCurrentNotInCFG(); + System.out.println("Resolving branch to next block."); } targetBB = currentBlock; @@ -1332,6 +1337,22 @@ return gc.temps.makeTemp(type); } + /** + * Prints the given BasicBlock and the <code>count</code> blocks following it in code order. + * @param block + * The basic block that shall be printed. + * @param count + * The number of blocks following <code>block</code> that shall be printed. + */ + public void printNextBlocks(OPT_BasicBlock block, int count) { + do + { + block.printExtended(); + block = block.nextBasicBlockInCodeOrder(); + } + while (block != null && count-- > 0); + } + /** Report some debug output */ protected abstract void report(String str); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-17 16:31:40
|
Revision: 120 http://svn.sourceforge.net/pearcolator/?rev=120&view=rev Author: michael_baer Date: 2007-05-17 09:31:37 -0700 (Thu, 17 May 2007) Log Message: ----------- General changes to the dynamic translator: - Generalized & harmonized the set of functions used to build a trace - enabled the use of branch profiling for all ISAs - many code cleanups & refactorings ARM DBT changes: - Not returning from the trace on most branches - Using branch profiling - added support for more instruction types Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java src/org/binarytranslator/arch/ppc/decoder/PPC2IR.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_DecodedOperand.java src/org/binarytranslator/arch/x86/decoder/X86_InstructionDecoder.java src/org/binarytranslator/arch/x86/decoder/X86_ModRM_Decoder.java src/org/binarytranslator/generic/branch/BranchLogic.java src/org/binarytranslator/generic/decoder/InstructionDecoder.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/generic/decoder/AbstractCodeTranslator.java src/org/binarytranslator/generic/os/abi/linux/filesystem/RemappingFilesystem.java Removed Paths: ------------- src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/vmInterface/TranslationHelper.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-16 18:16:21 UTC (rev 119) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-17 16:31:37 UTC (rev 120) @@ -7,7 +7,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.DecoderUtils; +import org.binarytranslator.generic.decoder.AbstractCodeTranslator; import org.binarytranslator.generic.decoder.Laziness; import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_FieldReference; @@ -17,7 +17,7 @@ import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.ir.*; -public class ARM2IR extends DecoderUtils implements OPT_HIRGenerator { +public class ARM2IR extends AbstractCodeTranslator implements OPT_HIRGenerator { /** Mapping of ARM registers to HIR registers */ private OPT_Register regMap[] = new OPT_Register[16]; @@ -128,7 +128,6 @@ if (DBT.VerifyAssertions) DBT._assert(registers_overflowFlag_Fref != null); } - public ARM2IR(OPT_GenerationContext context) { super(context); @@ -172,7 +171,7 @@ VM_FieldReference requestedMode_FieldReference = VM_FieldReference.findOrCreate(OperatingMode_TypeRef, VM_Atom.findOrCreateAsciiAtom(mode.name()), VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/arm/os/process/ARM_Registers/OperatingMode;")).asFieldReference(); //Finally, use a getfield to grab the (static) member field - appendInstructionToCurrentBlock(GetField.create(GETFIELD, result, + appendInstruction(GetField.create(GETFIELD, result, null, new OPT_AddressConstantOperand(requestedMode_FieldReference .peekResolvedField().getOffset()), new OPT_LocationOperand( requestedMode_FieldReference), new OPT_TrueGuardOperand())); @@ -190,7 +189,7 @@ if (ps_registers == null) { ps_registersOp = gc.temps.makeTemp(registersTref); ps_registers = ps_registersOp.register; - appendInstructionToCurrentBlock(GetField.create(GETFIELD, ps_registersOp, + appendInstruction(GetField.create(GETFIELD, ps_registersOp, gc.makeLocal(1, psTref), new OPT_AddressConstantOperand(registersFref .peekResolvedField().getOffset()), new OPT_LocationOperand( registersFref), new OPT_TrueGuardOperand())); @@ -218,19 +217,19 @@ //store the carry flag OPT_RegisterOperand flag = new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); - appendInstructionToCurrentBlock(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_carryFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_carryFlag_Fref), new OPT_TrueGuardOperand()) ); + 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); - appendInstructionToCurrentBlock(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_negativeFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_negativeFlag_Fref), new OPT_TrueGuardOperand()) ); + 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); - appendInstructionToCurrentBlock(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_zeroFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_zeroFlag_Fref), new OPT_TrueGuardOperand()) ); + 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); - appendInstructionToCurrentBlock(PutField.create(PUTFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_overflowFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_overflowFlag_Fref), new OPT_TrueGuardOperand()) ); + 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() { @@ -247,19 +246,19 @@ //get the carry flag OPT_RegisterOperand flag = new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); - appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_carryFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_carryFlag_Fref), new OPT_TrueGuardOperand()) ); + appendInstruction(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_carryFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_carryFlag_Fref), new OPT_TrueGuardOperand()) ); //get the negative flag flag = new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean); - appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_negativeFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_negativeFlag_Fref), new OPT_TrueGuardOperand()) ); + appendInstruction(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_negativeFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_negativeFlag_Fref), new OPT_TrueGuardOperand()) ); //get the zero flag flag = new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean); - appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_zeroFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_zeroFlag_Fref), new OPT_TrueGuardOperand()) ); + appendInstruction(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_zeroFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_zeroFlag_Fref), new OPT_TrueGuardOperand()) ); //get the overflow flag flag = new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean); - appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_overflowFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_overflowFlag_Fref), new OPT_TrueGuardOperand()) ); + appendInstruction(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_overflowFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_overflowFlag_Fref), new OPT_TrueGuardOperand()) ); } @Override @@ -273,7 +272,7 @@ if (ps_registers_regs == null) { ps_registers_regsOp = gc.temps.makeTemp(registers_regs_Tref); - appendInstructionToCurrentBlock(GetField.create(GETFIELD, + appendInstruction(GetField.create(GETFIELD, ps_registers_regsOp, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_regs_Fref.peekResolvedField() .getOffset()), new OPT_LocationOperand(registers_regs_Fref), @@ -292,7 +291,7 @@ } else { regOp = new OPT_RegisterOperand(regMap[i], VM_TypeReference.Int); } - appendInstructionToCurrentBlock(ALoad.create(INT_ALOAD, regOp, + appendInstruction(ALoad.create(INT_ALOAD, regOp, ps_registers_regsOp.copyRO(), new OPT_IntConstantOperand(i), new OPT_LocationOperand(VM_TypeReference.Int), new OPT_TrueGuardOperand())); @@ -357,7 +356,7 @@ // never used if ((DBT_Options.singleInstrTranslation == false) || (regUsed[i] == true)) { - appendInstructionToCurrentBlock(AStore.create(INT_ASTORE, + appendInstruction(AStore.create(INT_ASTORE, new OPT_RegisterOperand(regMap[i], VM_TypeReference.Int), ps_registers_regsOp.copyRO(), new OPT_IntConstantOperand(i), new OPT_LocationOperand(VM_TypeReference.Int), @@ -423,23 +422,23 @@ Call.setAddress(s, new OPT_AddressConstantOperand(rotateRightMethod .getOffset())); - appendInstructionToCurrentBlock(s); + appendInstruction(s); } protected void appendBitTest(OPT_RegisterOperand target, OPT_Operand wordToTest, OPT_Operand bit) { if (DBT.VerifyAssertions) DBT._assert(wordToTest != target && bit != target); - appendInstructionToCurrentBlock(Binary.create(OPT_Operators.INT_SHL, target, new OPT_IntConstantOperand(1), bit)); - appendInstructionToCurrentBlock(Binary.create(OPT_Operators.INT_AND, target, wordToTest, target)); - appendInstructionToCurrentBlock(BooleanCmp.create(OPT_Operators.BOOLEAN_CMP_INT, target, target, new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand())); + appendInstruction(Binary.create(OPT_Operators.INT_SHL, target, new OPT_IntConstantOperand(1), bit)); + appendInstruction(Binary.create(OPT_Operators.INT_AND, target, wordToTest, target)); + appendInstruction(BooleanCmp.create(OPT_Operators.BOOLEAN_CMP_INT, target, target, new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand())); } protected void appendBitTest(OPT_RegisterOperand target, OPT_Operand wordToTest, int bit) { if (DBT.VerifyAssertions) DBT._assert(wordToTest != target); if (DBT.VerifyAssertions) DBT._assert(bit <= 31 && bit >= 0); - appendInstructionToCurrentBlock(Binary.create(OPT_Operators.INT_AND, target, wordToTest, new OPT_IntConstantOperand(1 << bit))); - appendInstructionToCurrentBlock(BooleanCmp.create(OPT_Operators.BOOLEAN_CMP_INT, target, target, new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand())); + appendInstruction(Binary.create(OPT_Operators.INT_AND, target, wordToTest, new OPT_IntConstantOperand(1 << bit))); + appendInstruction(BooleanCmp.create(OPT_Operators.BOOLEAN_CMP_INT, target, target, new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand())); } } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-16 18:16:21 UTC (rev 119) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-17 16:31:37 UTC (rev 120) @@ -8,6 +8,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.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_MemberReference; import org.jikesrvm.classloader.VM_Method; @@ -15,17 +16,18 @@ import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.ir.*; -/** - */ public class ARM_Translator implements OPT_Operators { /** The process space that we're interpreting.*/ protected final ARM_ProcessSpace ps; + /** The ARM translation class. */ protected final ARM2IR arm2ir; + /** The current laziness state. */ protected ARM_Laziness lazy; + /** The current pc that we're translating. */ protected int pc; /** A "quick" pointer to the ARM registers within the process space*/ @@ -53,6 +55,19 @@ return instr.getSuccessor(pc); } + /** + * Creates an HIR instruction that will call method <code>methodName</code> in the current ARM registers class, + * which has the signature <code>signature</code> and takes <code>numParameters</code> parameters. + * + * @param methodName + * The name of the method to call. + * @param signature + * The method's signature + * @param numParameters + * The number of parameters the method takes. + * @return + * An HIR instruction that will call the given method. + */ private OPT_Instruction createCallToRegisters(String methodName, String signature, int numParameters) { VM_TypeReference RegistersType = VM_TypeReference @@ -79,19 +94,28 @@ return call; } + /** Some ARM instructions can use several addressing modes. Therefore, the ARM Decoder uses an + * {@link OperandWrapper}, that abstracts these differences. The <code>ResolvedOperand</code> class + * can be used to resolve an <code>OperandWrapper</code> into an actual HIR operand.*/ private abstract static class ResolvedOperand { + /** Stores the value that the operand resolves to. */ protected OPT_Operand value; + /** A backlink to the {@link ARM_Translator} class that is using this ResolvedOperand instance. */ protected ARM_Translator translator; - public static OPT_Operand resolveAndStoreShifterCarryOutToCarry( - ARM_Translator translator, OperandWrapper operand) { - - ResolvedOperand result = new ResolvedOperand_WithShifterCarryOut(translator, operand); - return result.getValue(); - } - + /** + * Call this function to create code that converts the <code>operand</code> into an + * HIR <code>OPT_Operand</code>. + * + * @param translator + * + * @param operand + * The operand that is to be converted. + * @return + * An HIR operand that represents the resolved operand. + */ public static OPT_Operand resolve(ARM_Translator translator, OperandWrapper operand) { ResolvedOperand result = new ResolvedOperand_WithoutShifterCarryOut( @@ -99,10 +123,30 @@ return result.getValue(); } + /** + * Works similar to {@link #resolve(ARM_Translator, OperandWrapper)}, but also calculates the + * shifter-carry-out that the ARM barell shifter would produce while resolving this operand. + * The shifter-carry-out is directly written into the <code>translator</code>'s carry flag. + * @param translator + * The translator instance within which the code for the said conversion is to be created. + * @param operand + * The operand that is to be converted. + * @return + * An HIR operand that represents the resolved operand. + */ + public static OPT_Operand resolveAndStoreShifterCarryOutToCarry( + ARM_Translator translator, OperandWrapper operand) { + + ResolvedOperand result = new ResolvedOperand_WithShifterCarryOut(translator, operand); + return result.getValue(); + } + public final OPT_Operand getValue() { return value; } + /** A subclass that resolves an {@link OperandWrapper} without calculating the shifter + * carry out produced by ARM's barrel shifter. */ private static class ResolvedOperand_WithoutShifterCarryOut extends ResolvedOperand { @@ -173,7 +217,7 @@ // the amount of shifting is determined by a register shiftAmount = translator.arm2ir.getRegister(operand.getShiftingRegister()); OPT_RegisterOperand shiftAmountAsByte = translator.arm2ir.getTempInt(7); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, shiftAmountAsByte, shiftAmount, new OPT_IntConstantOperand(0xFF))); + translator.arm2ir.appendInstruction(Binary.create(INT_AND, shiftAmountAsByte, shiftAmount, new OPT_IntConstantOperand(0xFF))); shiftAmount = shiftAmountAsByte; } @@ -196,18 +240,18 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(block2); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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.appendInstructionToCurrentBlock(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount)); - translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + translator.arm2ir.appendInstruction(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 2 - shift >= 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + translator.arm2ir.appendInstruction(Binary.create( INT_SHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(31))); break; @@ -218,24 +262,22 @@ block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - //current block curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(block2); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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.appendInstructionToCurrentBlock(Binary.create(INT_SHL, resultRegister, shiftedOperand, shiftAmount)); - translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + translator.arm2ir.appendInstruction(Binary.create(INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); - //block 2 - shift >= 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); break; case LSR: @@ -247,23 +289,22 @@ block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - //current block curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(block2); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, shiftAmount)); - translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 2 - shift >= 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); break; case ROR: @@ -285,13 +326,13 @@ curBlock.deleteNormalOut(); curBlock.insertOut(nextBlock); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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.appendInstructionToCurrentBlock(Binary.create(INT_OR, resultRegister, resultRegister, new OPT_IntConstantOperand(0x80000000))); + translator.arm2ir.appendInstruction(Binary.create(INT_OR, resultRegister, resultRegister, new OPT_IntConstantOperand(0x80000000))); break; default: @@ -303,7 +344,10 @@ return resultRegister; } } - + + /** + * This class resolves an {@link OperandWrapper} and also writes the shifter carry out, as + * produced by ARM's barrel shifter, into the Carry flag.*/ private static class ResolvedOperand_WithShifterCarryOut extends ResolvedOperand { @@ -323,7 +367,7 @@ OPT_Operand shifterCarryOut = new OPT_IntConstantOperand(((operand.getImmediate() & 0x80000000) != 0) ? 1 : 0); //otherwise there is no shifter carry out - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, carryFlag, shifterCarryOut)); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, carryFlag, shifterCarryOut)); } return; @@ -386,7 +430,7 @@ // the amount of shifting is determined by a register shiftAmount = translator.arm2ir.getRegister(operand.getShiftingRegister()); OPT_RegisterOperand shiftAmountAsByte = translator.arm2ir.getTempInt(7); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, shiftAmountAsByte, shiftAmount, new OPT_IntConstantOperand(0xFF))); + translator.arm2ir.appendInstruction(Binary.create(INT_AND, shiftAmountAsByte, shiftAmount, new OPT_IntConstantOperand(0xFF))); shiftAmount = shiftAmountAsByte; } @@ -409,33 +453,33 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(block4); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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.appendInstructionToCurrentBlock(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, shiftAmount, 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.appendInstructionToCurrentBlock(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount) ); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1)) ); + 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.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + 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.appendInstructionToCurrentBlock(Binary.create(INT_MUL, resultRegister, getShifterCarryOutTarget(), new OPT_IntConstantOperand(-1)) ); //creates either 0xFFFFFFFF if the bit is set, or 0 otherwise - translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + 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(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 4 - shift == 0 translator.arm2ir.setCurrentBlock(block4); block4.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case LSL: @@ -453,45 +497,45 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block6); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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.appendInstructionToCurrentBlock(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, shiftAmount, 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.appendInstructionToCurrentBlock(Binary.create(INT_SUB, tmp, new OPT_IntConstantOperand(32), shiftAmount) ); + translator.arm2ir.appendInstruction(Binary.create(INT_SUB, tmp, new OPT_IntConstantOperand(32), shiftAmount) ); translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHL, resultRegister, shiftedOperand, shiftAmount)); - translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + translator.arm2ir.appendInstruction(Binary.create(INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 3 - Shift >= 32 translator.arm2ir.setCurrentBlock(block3); - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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())); block3.insertOut(block4); block3.insertOut(block5); //block 4 - Shift > 32 translator.arm2ir.setCurrentBlock(block4); block4.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); - translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 5 - Shift == 32 translator.arm2ir.setCurrentBlock(block5); block5.insertOut(nextBlock); translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 0); - translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 6 - shift == 0 translator.arm2ir.setCurrentBlock(block6); block6.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case LSR: @@ -510,45 +554,45 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block6); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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.appendInstructionToCurrentBlock(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, shiftAmount, 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.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1))); + translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1))); translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, shiftAmount)); - translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 3 - Shift >= 32 translator.arm2ir.setCurrentBlock(block3); - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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())); block3.insertOut(block4); block3.insertOut(block5); //block 4 - Shift > 32 translator.arm2ir.setCurrentBlock(block4); block4.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); - translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 5 - Shift == 32 translator.arm2ir.setCurrentBlock(block5); block5.insertOut(nextBlock); translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 31); - translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 6 - shift == 0 translator.arm2ir.setCurrentBlock(block6); block6.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case ROR: @@ -562,20 +606,20 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(block2); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1)) ); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, tmp, tmp, new OPT_IntConstantOperand(0x1F)) ); + 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.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget())); //block 2 translator.arm2ir.setCurrentBlock(block2); - translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); + translator.arm2ir.appendInstruction(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case RRX: @@ -589,13 +633,13 @@ curBlock.deleteNormalOut(); curBlock.insertOut(block1); curBlock.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); - translator.arm2ir.appendInstructionToCurrentBlock(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, 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.appendInstructionToCurrentBlock(Binary.create(INT_OR, resultRegister, resultRegister, new OPT_IntConstantOperand(0x80000000))); + translator.arm2ir.appendInstruction(Binary.create(INT_OR, resultRegister, resultRegister, new OPT_IntConstantOperand(0x80000000))); //nextBlock translator.arm2ir.setCurrentBlock(nextBlock); @@ -640,29 +684,17 @@ 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; - else - return -1; + return pc + 4; } public void translate() { //conditionals are implemented easily: if the condition does not hold, then just //jump to the block following the conditional instruction - OPT_BasicBlock nextInstruction; - OPT_BasicBlock condBlock; - - if (getSuccessor(pc) != -1) { - nextInstruction = arm2ir.getNextBlock(); - condBlock = arm2ir.createBlockAfterCurrent(); - condBlock.insertOut(nextInstruction); - } - else { - nextInstruction = arm2ir.createBlockAfterCurrent(); - condBlock = arm2ir.createBlockAfterCurrent(); - } - + OPT_BasicBlock nextInstruction = arm2ir.getNextBlock(); + OPT_BasicBlock condBlock = arm2ir.createBlockAfterCurrent(); + arm2ir.getCurrentBlock().deleteNormalOut(); arm2ir.getCurrentBlock().insertOut(nextInstruction); + arm2ir.getCurrentBlock().insertOut(condBlock); switch (conditionalInstruction.getCondition()) { case AL: @@ -745,11 +777,6 @@ arm2ir.setCurrentBlock(condBlock); conditionalInstruction.translate(); - - if (getSuccessor(pc) == -1) { - arm2ir.setCurrentBlock(nextInstruction); - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc+4)); - } } private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand operand, OPT_ConditionOperand condition) { @@ -759,7 +786,7 @@ private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand lhs, OPT_ConditionOperand condition, OPT_Operand rhs) { condition = condition.flipCode(); - arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), lhs, rhs, condition, nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), lhs, rhs, condition, nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_HI(OPT_BasicBlock nextInstruction) { @@ -768,10 +795,10 @@ OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); - arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, carry, + 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.appendInstructionToCurrentBlock(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, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_LS(OPT_BasicBlock nextInstruction) { @@ -780,10 +807,10 @@ OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); - arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, carry, + 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.appendInstructionToCurrentBlock(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, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_GT(OPT_BasicBlock nextInstruction) { @@ -793,10 +820,10 @@ OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); - arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, negative, + 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.appendInstructionToCurrentBlock(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, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_LE(OPT_BasicBlock nextInstruction) { @@ -806,10 +833,10 @@ OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); - arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, negative, + 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.appendInstructionToCurrentBlock(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, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } public Condition getCondition() { @@ -854,7 +881,7 @@ public abstract void translate(); /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ - protected final void setAddResult(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setAddResult(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) { if (updateConditionCodes) { if (Rd != 15) { @@ -862,14 +889,20 @@ } else { OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); - arm2ir.appendInstructionToCurrentBlock(s); + arm2ir.appendInstruction(s); } } - arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); - - if (Rd == 15) - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + if (Rd == 15) { + + if (updateConditionCodes) + arm2ir.appendDynamicJump(result, lazy, BranchType.INDIRECT_BRANCH); + else + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + } + else { + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + } } /** @@ -883,24 +916,24 @@ */ protected final void setAddFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { //set the carry flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + arm2ir.appendInstruction(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.CARRY_FROM_ADD(), new OPT_BranchProfileOperand())); //set the overflow flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + arm2ir.appendInstruction(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + arm2ir.appendInstruction(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + arm2ir.appendInstruction(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, 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>.*/ - protected final void setSubResult(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setSubResult(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) { if (updateConditionCodes) { if (Rd != 15) { @@ -908,14 +941,20 @@ } else { OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); - arm2ir.appendInstructionToCurrentBlock(s); + arm2ir.appendInstruction(s); } } - - arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); - - if (Rd == 15) - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + + if (Rd == 15) { + + if (updateConditionCodes) + arm2ir.appendDynamicJump(result, lazy, BranchType.INDIRECT_BRANCH); + else + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + } + else { + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + } } /** @@ -929,20 +968,20 @@ */ protected final void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { //set the carry flag to not(Borrow) - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + arm2ir.appendInstruction(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); - arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); + arm2ir.appendInstruction(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); //set the overflow flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + arm2ir.appendInstruction(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + arm2ir.appendInstruction(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + arm2ir.appendInstruction(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); } @@ -975,21 +1014,36 @@ } /** Sets the condition field for logical operations. */ - protected final void setLogicalResult(OPT_Operand result) { + protected final void setLogicalResult(OPT_RegisterOperand result) { if (updateConditionCodes) { if (Rd != 15) { setLogicalFlags(result); } else { OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); - arm2ir.appendInstructionToCurrentBlock(s); + arm2ir.appendInstruction(s); } } - arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); - if (Rd == 15) - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + + if (Rd == 15) { + if (updateConditionCodes) { + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); + } + else { + BranchType branchType = BranchType.INDIRECT_BRANCH; + + //Mark "MOV pc, lr" instructions as returns + if (opcode == Opcode.MOV && operand2.getType() == OperandWrapper.Type.Register && operand2.getRegister() == ARM_Registers.LR) + branchType = BranchType.RETURN; + + arm2ir.appendDynamicJump(result, lazy, branchType); + } + } + else { + arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + } } /** @@ -1001,11 +1055,11 @@ //the shifter carry out has already been set during the resolve-phase //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + arm2ir.appendInstruction(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + arm2ir.appendInstruction(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); } } @@ -1021,7 +1075,7 @@ public void translate() { OPT_RegisterOperand result = getResultRegister(); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, resolveOperand1(), resolveOperand2())); + arm2ir.appendInstruction(Binary.create(INT_AND, result, resolveOperand1(), resolveOperand2())); setLogicalResult(result); } @@ -1038,7 +1092,7 @@ public void translate() { OPT_RegisterOperand result = getResultRegister(); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_XOR, result, resolveOperand1(), resolveOperand2())); + arm2ir.appendInstruction(Binary.create(INT_XOR, result, resolveOperand1(), resolveOperand2())); setLogicalResult(result); } @@ -1057,7 +1111,7 @@ OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = getResultRegister(); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); + arm2ir.appendInstruction(Binary.create(INT_ADD, result, operand1, operand2)); setAddResult(result, operand1, operand2); } @@ -1076,7 +1130,7 @@ OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = getResultRegister(); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); + arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2)); setSubResult(result, operand1, operand2); } @@ -1095,7 +1149,7 @@ OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = getResultRegister(); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand2, operand1)); + arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand2, operand1)); setSubResult(result, operand2, operand1); } @@ -1121,13 +1175,13 @@ OPT_BasicBlock addWithCarry = arm2ir.createBlockAfterCurrentNotInCFG(); //Is the carry set at all? if not, just jump to addWithoutCarry - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); - arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstruction(Binary.create(INT_ADD, result, operand1, operand2)); + arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand())); arm2ir.getCurrentBlock().insertOut(addWithCarry); //Yes, the carry flag is set. Pre-increase the result by one to account for the carry. arm2ir.setCurrentBlock(addWithCarry); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, result, new OPT_IntConstantOperand(1))); + arm2ir.appendInstruction(Binary.create(INT_ADD, result, result, new OPT_IntConstantOperand(1))); addWithCarry.insertOut(addWithoutCarry); //Finally, add the second operands to the result @@ -1152,13 +1206,13 @@ OPT_BasicBlock subWithCarry = arm2ir.createBlockAfterCurrentNotInCFG(); //Is the carry set? if yes, just jump to subWithoutCarry - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); - arm2... [truncated message content] |
From: <mic...@us...> - 2007-05-16 18:16:19
|
Revision: 119 http://svn.sourceforge.net/pearcolator/?rev=119&view=rev Author: michael_baer Date: 2007-05-16 11:16:21 -0700 (Wed, 16 May 2007) Log Message: ----------- Changes to compile with latest JRVM Modified Paths: -------------- ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java Modified: ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java =================================================================== --- ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java 2007-05-16 18:15:51 UTC (rev 118) +++ ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java 2007-05-16 18:16:21 UTC (rev 119) @@ -9,11 +9,7 @@ package org.jikesrvm.compilers.opt.ia32; import org.jikesrvm.VM; -import org.jikesrvm.runtime.VM_Entrypoints; -import org.jikesrvm.runtime.VM_Magic; -import org.jikesrvm.runtime.VM_Runtime; -import org.jikesrvm.classloader.*; -import org.jikesrvm.compilers.opt.ir.ia32.*; +import org.jikesrvm.classloader.VM_TypeReference; import org.jikesrvm.compilers.opt.OPT_BURS; import org.jikesrvm.compilers.opt.OPT_BURS_MemOp_Helpers; import org.jikesrvm.compilers.opt.OPT_DefUse; @@ -63,6 +59,64 @@ 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 static org.jikesrvm.compilers.opt.ir.OPT_Operators.CALL_SAVE_VOLATILE; +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.IA32_ADC; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_ADD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_AND; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_BT; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_CALL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_CDQ; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_CMOV; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_CMP; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FCMOV; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FCOMI; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FCOMIP; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FILD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FIST; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FLD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FLD1; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FLDCW; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FLDL2E; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FLDL2T; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FLDLG2; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FLDLN2; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FLDPI; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FLDZ; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FMOV; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FNSTCW; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FPREM; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_FSTP; +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_LOCK_CMPXCHG; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_MOV; +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; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_NEG; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_NOT; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_OR; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_RCR; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_RDTSC; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_SAR; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_SBB; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_SET__B; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_SHL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_SHLD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_SHR; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_SHRD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_SUB; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_SYSCALL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_TEST; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IA32_TRAPIF; +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; @@ -73,16 +127,15 @@ import org.jikesrvm.compilers.opt.ir.Prologue; import org.jikesrvm.compilers.opt.ir.TrapIf; import org.jikesrvm.compilers.opt.ir.Unary; - -import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*; +import org.jikesrvm.compilers.opt.ir.ia32.OPT_BURSManagedFPROperand; +import org.jikesrvm.compilers.opt.ir.ia32.OPT_IA32ConditionOperand; +import org.jikesrvm.runtime.VM_Entrypoints; +import org.jikesrvm.runtime.VM_Magic; +import org.jikesrvm.runtime.VM_Runtime; import org.vmmagic.unboxed.Offset; /** * Contains IA32-specific helper functions for BURS. - * - * @author Dave Grove - * @author Stephen Fink - * @author Ian Rogers */ abstract class OPT_BURS_Helpers extends OPT_BURS_MemOp_Helpers { /** Constant log10(2), supported as an x87 constant */ @@ -114,7 +167,7 @@ /** * Follow a chain of Move operations filtering back to a def - * + * * @param use the place to start from * @return the operand at the start of the chain */ @@ -146,18 +199,19 @@ /** * Remember a condition code in a child node - * + * * @param c condition code to record */ protected final void pushCOND(OPT_ConditionOperand c) { - if (VM.VerifyAssertions) + if (VM.VerifyAssertions) { VM._assert(cc == null); + } cc = c; } /** * Acquire remembered condition code in parent - * + * * @return condition code */ protected final OPT_ConditionOperand consumeCOND() { @@ -171,7 +225,7 @@ /** * Can an IV be the scale in a LEA instruction? - * + * * @param op operand to examine * @param trueCost the cost if this can be part of an LEA * @return trueCost or INFINITE @@ -182,7 +236,7 @@ /** * Can an IV be the scale in a LEA instruction? - * + * * @param op operand to examine * @param trueCost the cost if this can be part of an LEA * @param falseCost the cost if this can't be part of an LEA @@ -200,22 +254,22 @@ protected final byte LEA_SHIFT(OPT_Operand op) { switch (IV(op)) { - case 0: - return B_S; - case 1: - return W_S; - case 2: - return DW_S; - case 3: - return QW_S; - default: - throw new OPT_OptimizingCompilerException("bad val for LEA shift " + op); + case 0: + return B_S; + case 1: + return W_S; + case 2: + return DW_S; + case 3: + return QW_S; + default: + throw new OPT_OptimizingCompilerException("bad val for LEA shift " + op); } } /** * Is the given instruction's constant operand a x87 floating point constant - * + * * @param s the instruction to examine * @param trueCost the cost if this is a valid constant * @return trueCost or INFINITE depending on the given constant @@ -298,7 +352,7 @@ } } throw new OPT_OptimizingCompilerException("OPT_BURS_Helpers", - "unexpected 387 constant " + val); + "unexpected 387 constant " + val); } protected final OPT_IA32ConditionOperand COND(OPT_ConditionOperand op) { @@ -354,9 +408,10 @@ * 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) { - if (op.isRegister()) + OPT_Operand op) { + if (op.isRegister()) { return op; + } OPT_RegisterOperand tmp = regpool.makeTemp(op); EMIT(CPOS(s, MIR_Move.create(movop, tmp, op))); return tmp.copy(); @@ -364,7 +419,7 @@ /** * Set the size field of the given memory operand and return it - * + * * @param mo memory operand size to set * @param size the new size * @return mo @@ -376,7 +431,7 @@ /** * Create a slot on the stack in memory for a conversion - * + * * @param size for memory operand * @return memory operand of slot in stack */ @@ -396,21 +451,21 @@ 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)); + offset + 4, DW), hval)); EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset, - DW), lval)); + DW), lval)); } else { OPT_LongConstantOperand val = LC(op); EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, - offset + 4, DW), IC(val.upper32()))); + offset + 4, DW), IC(val.upper32()))); EMIT(MIR_Move.create(IA32_MOV, new OPT_StackLocationOperand(true, offset, - DW), IC(val.lower32()))); + DW), IC(val.lower32()))); } } /** * Create memory operand to load 32 bits form a given jtoc offset - * + * * @param offset location in JTOC * @return created memory operand */ @@ -418,7 +473,7 @@ OPT_LocationOperand loc = new OPT_LocationOperand(offset); OPT_Operand guard = TG(); return OPT_MemoryOperand.D(VM_Magic.getTocPointer().plus(offset), (byte) 4, - loc, guard); + loc, guard); } /* @@ -430,7 +485,7 @@ /** * Emit code to get a caught exception object into a register - * + * * @param s the instruction to expand */ protected final void GET_EXCEPTION_OBJECT(OPT_Instruction s) { @@ -442,7 +497,7 @@ /** * Emit code to move a value in a register to the stack location where a * caught exception object is expected to be. - * + * * @param s the instruction to expand */ protected final void SET_EXCEPTION_OBJECT(OPT_Instruction s) { @@ -454,22 +509,22 @@ /** * Expansion of INT_2LONG - * + * * @param s the instruction to expand * @param result the result operand * @param value the second operand */ protected final void INT_2LONG(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { + OPT_Operand value) { 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)); + VM_TypeReference.Int), value)); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(hr, - VM_TypeReference.Int), - new OPT_RegisterOperand(lr, VM_TypeReference.Int))); + 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))); + VM_TypeReference.Int), IC(31))); } /** @@ -477,13 +532,13 @@ * expansion does some boolean logic and conditional moves in order to avoid * changing the floating-point rounding mode or inserting branches. Other * expansions are possible, and may be better? - * + * * @param s the instruction to expand * @param result the result operand * @param value the second operand */ protected final void FPR_2INT(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { + OPT_Operand value) { OPT_MemoryOperand M; // Step 1: Get value to be converted into myFP0 @@ -500,8 +555,9 @@ // semantics before doing a particular f2int conversion. To do this // we must have a store/load sequence to cause IEEE rounding. if (value instanceof OPT_BURSManagedFPROperand) { - if (VM.VerifyAssertions) + 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))); } else { @@ -521,21 +577,27 @@ 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))); + VM_TypeReference.Int), IC(1))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(isPositive, - VM_TypeReference.Int), IC(0))); + VM_TypeReference.Int), IC(0))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(isNegative, - VM_TypeReference.Int), IC(0))); + VM_TypeReference.Int), IC(0))); EMIT(MIR_Nullary.create(IA32_FLDZ, myFP0())); // FP Stack: myFP0 = 0.0; myFP1 = value EMIT(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(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(MIR_Move.create(IA32_FILD, myFP0(), MO_CONV(DW))); // FP Stack: myFP0 = round(value), myFP1 = value @@ -547,25 +609,35 @@ EMIT(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))); + 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())); + 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())); // 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_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))); @@ -582,7 +654,7 @@ // 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))); + 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())); @@ -596,7 +668,7 @@ // 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))); + 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())); @@ -606,7 +678,7 @@ // 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))); + VM_TypeReference.Int), IC(0))); EMIT(MIR_CondMove.create(IA32_CMOV, result.copy(), new OPT_RegisterOperand( zero, VM_TypeReference.Int), OPT_IA32ConditionOperand.PE())); @@ -619,9 +691,9 @@ 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); + offset + 4, DW); OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, - DW); + DW); EMIT(MIR_Move.create(IA32_FMOV, sl, Unary.getVal(s))); OPT_RegisterOperand i1 = Unary.getResult(s); OPT_RegisterOperand i2 = new OPT_RegisterOperand(regpool @@ -637,16 +709,16 @@ 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); + offset + 4, DW); OPT_StackLocationOperand sl2 = new OPT_StackLocationOperand(true, offset, - DW); + 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); + VM_TypeReference.Int); } else { OPT_LongConstantOperand rhs = (OPT_LongConstantOperand) val; i1 = IC(rhs.upper32()); @@ -659,7 +731,7 @@ /** * Expansion of ROUND_TO_ZERO. - * + * * @param s the instruction to expand */ protected final void ROUND_TO_ZERO(OPT_Instruction s) { @@ -673,7 +745,7 @@ // Store the FPU Control Word to a JTOC slot OPT_MemoryOperand M = OPT_MemoryOperand.BD(regOp.copyRO(), - VM_Entrypoints.FPUControlWordField.getOffset(), W, null, null); + VM_Entrypoints.FPUControlWordField.getOffset(), W, null, null); EMIT(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 @@ -685,7 +757,7 @@ /** * Expansion of INT_DIV and INT_REM - * + * * @param s the instruction to expand * @param result the result operand * @param val1 the first operand @@ -693,21 +765,28 @@ * @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, - boolean isDiv) { + 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))); + VM_TypeReference.Int), val1)); + EMIT(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)); val2 = temp.copyRO(); } - EMIT(MIR_Divide.mutate(s, IA32_IDIV, new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), val2, GuardedBinary.getGuard(s))); + EMIT(MIR_Divide.mutate(s, + IA32_IDIV, + 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))); @@ -719,106 +798,116 @@ /** * Expansion of LONG_ADD_ACC - * + * * @param s the instruction to expand * @param result the result/first operand * @param value the second operand */ protected final void LONG_ADD(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { + 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_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))); + 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 (low == 0) { EMIT(MIR_BinaryAcc.mutate(s, IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + VM_TypeReference.Int), IC(high))); } else { EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), IC(low))); + VM_TypeReference.Int), IC(low))); EMIT(MIR_BinaryAcc.mutate(s, IA32_ADC, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + VM_TypeReference.Int), IC(high))); } } } /** * Expansion of LONG_SUB_ACC - * + * * @param s the instruction to expand * @param result the result/first operand * @param value the second operand */ protected final void LONG_SUB(OPT_Instruction s, OPT_RegisterOperand result, - OPT_Operand value) { + 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))); + 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))); + VM_TypeReference.Int), IC(high))); } else { EMIT(MIR_BinaryAcc.create(IA32_SUB, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), IC(low))); + VM_TypeReference.Int), IC(low))); EMIT(MIR_BinaryAcc.mutate(s, IA32_SBB, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); + VM_TypeReference.Int), IC(high))); } } } /** * Expansion of RDTSC (called GET_TIME_BASE for consistency with PPC) - * + * * @param s the instruction to expand * @param result the result/first operand */ protected final void GET_TIME_BASE(OPT_Instruction s, - OPT_RegisterOperand result) { + 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))); + 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))); + 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))); + 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) { + 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; @@ -827,31 +916,40 @@ 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_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))); + 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))); + 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, - VM_TypeReference.Int))); + 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, + VM_TypeReference.Int))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); + VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int))); + EMIT(MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int))); } else { OPT_LongConstantOperand rhs = (OPT_LongConstantOperand) value; int low = rhs.lower32(); @@ -882,132 +980,183 @@ if (low == 0) { // -1, 0 // CLAIM: (x,y) * (-1,0) = (-y,0) - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); + EMIT(MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); EMIT(MIR_UnaryAcc.create(IA32_NEG, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int))); + VM_TypeReference.Int))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), IC(0))); + VM_TypeReference.Int), IC(0))); } else if (low == 1) { // -1, 1 // CLAIM: (x,y) * (-1,1) = (x-y,y) - EMIT(MIR_BinaryAcc.create(IA32_SUB, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); + EMIT(MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); } else { // -1, * // CLAIM: (x,y) * (-1, z) = (l(x imul z)-y+u(y mul z)+, l(y mul z)) EMIT(MIR_BinaryAcc.create(IA32_IMUL2, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(low))); - EMIT(MIR_BinaryAcc.create(IA32_SUB, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); + VM_TypeReference.Int), IC(low))); + EMIT(MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), IC(low))); - EMIT(MIR_Multiply.create(IA32_MUL, new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); + VM_TypeReference.Int), IC(low))); + EMIT(MIR_Multiply.create(IA32_MUL, + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); + EMIT(MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int))); + EMIT(MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int))); } } else if (high == 0) { if (low == -1) { // 0, -1 // CLAIM: (x,y) * (0,-1) = (u(y mul -1)-x, l(y mul -1)) EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), IC(-1))); - EMIT(MIR_Multiply.create(IA32_MUL, new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_SUB, new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); + VM_TypeReference.Int), IC(-1))); + EMIT(MIR_Multiply.create(IA32_MUL, + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); + EMIT(MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int))); + EMIT(MIR_BinaryAcc.create(IA32_SUB, + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int))); + EMIT(MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int))); } else { // 0, * // CLAIM: (x,y) * (0,z) = (l(x imul z)+u(y mul z), l(y mul z)) EMIT(MIR_BinaryAcc.create(IA32_IMUL2, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(low))); + VM_TypeReference.Int), IC(low))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), IC(low))); - EMIT(MIR_Multiply.create(IA32_MUL, new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); + VM_TypeReference.Int), IC(low))); + EMIT(MIR_Multiply.create(IA32_MUL, + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); + EMIT(MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int))); + EMIT(MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int))); } } else if (high == 1) { if (low == -1) { // 1, -1 // CLAIM: (x,y) * (1,-1) = (-x+y+u(y mul -1), l(y mul -1)) EMIT(MIR_UnaryAcc.create(IA32_NEG, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); + VM_TypeReference.Int))); + EMIT(MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), IC(-1))); - EMIT(MIR_Multiply.create(IA32_MUL, new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); + VM_TypeReference.Int), IC(-1))); + EMIT(MIR_Multiply.create(IA32_MUL, + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); + EMIT(MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int))); + EMIT(MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int))); } else if (low == 0) { // 1, 0 // CLAIM: (x,y) * (1,0) = (y,0) - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); + EMIT(MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), IC(0))); + VM_TypeReference.Int), IC(0))); } else if (low == 1) { // 1, 1 // CLAIM: (x,y) * (1,1) = (x+y,y) - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - 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(lowlhsReg, + VM_TypeReference.Int))); } else { // 1, * // CLAIM: (x,y) * (1,z) = (l(x imul z)+y+u(y mul z), l(y mul z)) EMIT(MIR_BinaryAcc.create(IA32_IMUL2, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(low))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); + VM_TypeReference.Int), IC(low))); + EMIT(MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), IC(low))); - EMIT(MIR_Multiply.create(IA32_MUL, new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); + VM_TypeReference.Int), IC(low))); + EMIT(MIR_Multiply.create(IA32_MUL, + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); + EMIT(MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int))); + EMIT(MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int))); } } else { if (low == -1) { @@ -1015,74 +1164,100 @@ // CLAIM: (x,y) * (z,-1) = (-x+l(y imul z)+u(y mul -1), l(y mul -1)) OPT_Register tmp = regpool.getInteger(); EMIT(MIR_UnaryAcc.create(IA32_NEG, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int))); + VM_TypeReference.Int))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(tmp, - VM_TypeReference.Int), IC(high))); - 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))); + VM_TypeReference.Int), IC(high))); + 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), IC(low))); - EMIT(MIR_Multiply.create(IA32_MUL, new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEAX(), - VM_TypeReference.Int))); - EMIT(MIR_BinaryAcc.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(getEDX(), - VM_TypeReference.Int))); + VM_TypeReference.Int), IC(low))); + EMIT(MIR_Multiply.create(IA32_MUL, + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); + EMIT(MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEAX(), + VM_TypeReference.Int))); + EMIT(MIR_BinaryAcc.create(IA32_ADD, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(getEDX(), + VM_TypeReference.Int))); } else if (low == 0) { // *, 0 // CLAIM: (x,y) * (z,0) = (l(y imul z),0) EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), IC(high))); - EMIT(MIR_BinaryAcc.create(IA32_IMUL2, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); + VM_TypeReference.Int), IC(high))); + EMIT(MIR_BinaryAcc.create(IA32_IMUL2, + new OPT_RegisterOperand(lhsReg, + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int), IC(0))); + VM_TypeReference.Int), IC(0))); } else if (low == 1) { // *, 1 // CLAIM: (x,y) * (z,1) = (l(y imul z)+x,y) OPT_Register tmp = regpool.getInteger(); - EMIT(MIR_Move.create(IA32_MOV, new OPT_RegisterOperand(tmp, - VM_TypeReference.Int), new OPT_RegisterOperand(lowlhsReg, - VM_TypeReference.Int))); + EMIT(MIR_Move.create(IA32_MOV, + new OPT_RegisterOperand(tmp, + VM_TypeReference.Int), + new OPT_RegisterOperand(lowlhsReg, + VM_TypeReference.Int))); EMIT(MIR_BinaryAcc.create(IA32_IMUL2, new OPT_RegisterOperand(tmp, - VM_TypeReference.Int), IC(high))); + VM_TypeReference.Int), IC(high))); EMIT(MIR_Move.create(IA32_ADD, new OPT_RegisterOperand(lhsReg, - VM_TypeReference.Int), new OPT_RegisterOperand(tmp, - VM_TypeReference.Int))); + VM_TypeReference.Int), new OPT_RegisterOperand(tmp, + VM_TypeReference.Int))); } else { // *, * (sigh, can't do anything interesting...) OPT_Register tmp = regpool.getInteger(); EMIT(MIR_BinaryAcc.create(IA32_IMUL2, new OPT_RegisterOperand(lhsReg, - ... [truncated message content] |
From: <mic...@us...> - 2007-05-16 18:15:50
|
Revision: 118 http://svn.sourceforge.net/pearcolator/?rev=118&view=rev Author: michael_baer Date: 2007-05-16 11:15:51 -0700 (Wed, 16 May 2007) Log Message: ----------- First ARM DBT version that runs Dhrystone Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.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/linux/ARM_ProcFileSystem.java src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-16 18:14:22 UTC (rev 117) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-16 18:15:51 UTC (rev 118) @@ -426,4 +426,20 @@ appendInstructionToCurrentBlock(s); } + protected void appendBitTest(OPT_RegisterOperand target, OPT_Operand wordToTest, OPT_Operand bit) { + if (DBT.VerifyAssertions) DBT._assert(wordToTest != target && bit != target); + + appendInstructionToCurrentBlock(Binary.create(OPT_Operators.INT_SHL, target, new OPT_IntConstantOperand(1), bit)); + appendInstructionToCurrentBlock(Binary.create(OPT_Operators.INT_AND, target, wordToTest, target)); + appendInstructionToCurrentBlock(BooleanCmp.create(OPT_Operators.BOOLEAN_CMP_INT, target, target, new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand())); + } + + protected void appendBitTest(OPT_RegisterOperand target, OPT_Operand wordToTest, int bit) { + if (DBT.VerifyAssertions) DBT._assert(wordToTest != target); + if (DBT.VerifyAssertions) DBT._assert(bit <= 31 && bit >= 0); + + appendInstructionToCurrentBlock(Binary.create(OPT_Operators.INT_AND, target, wordToTest, new OPT_IntConstantOperand(1 << bit))); + appendInstructionToCurrentBlock(BooleanCmp.create(OPT_Operators.BOOLEAN_CMP_INT, target, target, new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand())); + } + } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-16 18:14:22 UTC (rev 117) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-16 18:15:51 UTC (rev 118) @@ -654,7 +654,7 @@ } } - /** Subtract with carry. <code>Rd = op1 - op2 + CARRY</code>.*/ + /** Subtract with carry. <code>Rd = op1 - op2 - NOT(CARRY)</code>.*/ private class DataProcessing_Sbc extends DataProcessing { protected DataProcessing_Sbc(int instr) { @@ -668,8 +668,8 @@ if (!regs.isCarrySet()) { if (operand1 != Integer.MIN_VALUE) { operand1--; - } else if (operand2 != Integer.MIN_VALUE) { - operand2--; + } else if (operand2 != Integer.MAX_VALUE) { + operand2++; } else { //TODO: Remove this exception, when the correct behavior has been verified. throw new RuntimeException("I'm interested in finding a case where this occurs, so this exception is sooner or later going to 'notify' me.."); @@ -686,7 +686,7 @@ } } - /** Reserve subtract with carry. <code>Rd = -op1 + op2 + CARRY</code>.*/ + /** Reserve subtract with carry. <code>Rd = -op1 + op2 - NOT(CARRY)</code>.*/ private final class DataProcessing_Rsc extends DataProcessing_Sbc { protected DataProcessing_Rsc(int instr) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-16 18:14:22 UTC (rev 117) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-16 18:15:51 UTC (rev 118) @@ -78,8 +78,7 @@ return call; } - - + private abstract static class ResolvedOperand { protected OPT_Operand value; @@ -155,8 +154,7 @@ */ private final OPT_Operand resolveShift(OperandWrapper operand) { if (DBT.VerifyAssertions) - DBT - ._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister + DBT._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); // consider the "usual" ARM program counter offset @@ -173,29 +171,72 @@ shiftAmount = new OPT_IntConstantOperand(operand.getShiftAmount()); } else { // the amount of shifting is determined by a register - shiftAmount = translator.arm2ir.getRegister(operand - .getShiftingRegister()); + shiftAmount = translator.arm2ir.getRegister(operand.getShiftingRegister()); + OPT_RegisterOperand shiftAmountAsByte = translator.arm2ir.getTempInt(7); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, shiftAmountAsByte, shiftAmount, new OPT_IntConstantOperand(0xFF))); + shiftAmount = shiftAmountAsByte; } OPT_RegisterOperand resultRegister = translator.arm2ir.getTempInt(9); + OPT_RegisterOperand validation = translator.arm2ir.getTempValidation(0); + + OPT_BasicBlock nextBlock = translator.arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); + OPT_BasicBlock block1, block2; switch (operand.getShiftType()) { case ASR: /* * shiftedOperand >> shiftAmount; */ + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + //current block + curBlock.deleteNormalOut(); + curBlock.insertOut(block1); + curBlock.insertOut(block2); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, 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.appendInstructionToCurrentBlock(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 2 - shift >= 32 + translator.arm2ir.setCurrentBlock(block2); + block2.insertOut(nextBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHR, resultRegister, shiftedOperand, shiftAmount)); + INT_SHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(31))); + break; - return resultRegister; - case LSL: /* * value = shiftedOperand << shiftAmount; */ - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHL, resultRegister, shiftedOperand, shiftAmount)); - return resultRegister; + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + + //current block + curBlock.deleteNormalOut(); + curBlock.insertOut(block1); + curBlock.insertOut(block2); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, 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.appendInstructionToCurrentBlock(Binary.create(INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + + //block 2 - shift >= 32 + translator.arm2ir.setCurrentBlock(block2); + block2.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + break; case LSR: @@ -203,57 +244,63 @@ * value = shiftedOperand >>> shiftAmount; */ - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + + //current block + curBlock.deleteNormalOut(); + curBlock.insertOut(block1); + curBlock.insertOut(block2); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, 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.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 2 - shift >= 32 + translator.arm2ir.setCurrentBlock(block2); + block2.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + break; - return resultRegister; - case ROR: /* * return Integer.rotateRight(value, shiftAmount); */ translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); - return resultRegister; + break; case RRX: /* * result = shiftedOperand >>> 1; * if (regs.isCarrySet()) result |= 0x80000000; */ - - // resultRegister = shiftedOperand >>> 1 - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); - - //conditionally, set resultRegister = resultRegister | 0x80000000; - OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); - OPT_BasicBlock nextBlock = translator.arm2ir.createBlockAfterCurrent(); - OPT_BasicBlock block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - //Current block + // Current block + curBlock.deleteNormalOut(); + curBlock.insertOut(nextBlock); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), - new OPT_IntConstantOperand(1), OPT_ConditionOperand - .EQUAL(), block1.makeJumpTarget(), - new OPT_BranchProfileOperand())); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); + translator.arm2ir.appendInstructionToCurrentBlock(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.appendInstructionToCurrentBlock(Binary.create(INT_OR, resultRegister, resultRegister, new OPT_IntConstantOperand(0x80000000))); + break; - translator.arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create( - INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); - - translator.arm2ir.setCurrentBlock(nextBlock); - translator.arm2ir.setNextBlock(translator.arm2ir.createBlockAfterCurrent()); - return resultRegister; - default: throw new RuntimeException("Unexpected shift type: " + operand.getShiftType()); } + + translator.arm2ir.setCurrentBlock(nextBlock); + return resultRegister; } } @@ -337,8 +384,10 @@ shiftAmount = new OPT_IntConstantOperand(operand.getShiftAmount()); } else { // the amount of shifting is determined by a register - shiftAmount = translator.arm2ir.getRegister(operand - .getShiftingRegister()); + shiftAmount = translator.arm2ir.getRegister(operand.getShiftingRegister()); + OPT_RegisterOperand shiftAmountAsByte = translator.arm2ir.getTempInt(7); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, shiftAmountAsByte, shiftAmount, new OPT_IntConstantOperand(0xFF))); + shiftAmount = shiftAmountAsByte; } OPT_RegisterOperand resultRegister = translator.arm2ir.getTempInt(8); @@ -347,136 +396,186 @@ OPT_BasicBlock nextBlock = translator.arm2ir.createBlockAfterCurrent(); OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); - OPT_BasicBlock block1, block2, block3; + OPT_BasicBlock block1, block2, block3, block4, block5, block6; switch (operand.getShiftType()) { case ASR: - /* - * shiftedOperand >> shiftAmount; - * - * if (shiftAmount != 0) { - * shiftAmount = MIN(shiftAmount, 32); - * carry = shiftedOperand[shiftAmount] - * } - */ - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHR, resultRegister, shiftedOperand, shiftAmount)); - + block4 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block3 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); //current block + curBlock.deleteNormalOut(); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + curBlock.insertOut(block4); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block4.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 1 + //block 1 - shift != 0 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 2 + //block 2 - shift < 32 && shift != 0 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, shiftAmount, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount) ); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1)) ); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); - //block 3 + //block 3 - shift >= 32 translator.arm2ir.setCurrentBlock(block3); block3.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, new OPT_IntConstantOperand(32), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 31); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_MUL, resultRegister, getShifterCarryOutTarget(), new OPT_IntConstantOperand(-1)) ); //creates either 0xFFFFFFFF if the bit is set, or 0 otherwise + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); - + //block 4 - shift == 0 + translator.arm2ir.setCurrentBlock(block4); + block4.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case LSL: /* * value = shiftedOperand << shiftAmount; */ - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHL, resultRegister, shiftedOperand, shiftAmount)); - + block6 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block5 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block4 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block3 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); //current block + curBlock.deleteNormalOut(); + curBlock.insertOut(block6); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block6.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 1 + //block 1 - shift != 0 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 2 + //block 2 - Shift != 0 && Shift < 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock( Binary.create(INT_SUB, tmp, new OPT_IntConstantOperand(32), shiftAmount) ); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, tmp, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, tmp, new OPT_IntConstantOperand(32), shiftAmount) ); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); - //block 3 + //block 3 - Shift >= 32 translator.arm2ir.setCurrentBlock(block3); - block3.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock( Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); - + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.EQUAL(), block5.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + block3.insertOut(block4); + block3.insertOut(block5); + + //block 4 - Shift > 32 + translator.arm2ir.setCurrentBlock(block4); + block4.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 5 - Shift == 32 + translator.arm2ir.setCurrentBlock(block5); + block5.insertOut(nextBlock); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 0); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 6 - shift == 0 + translator.arm2ir.setCurrentBlock(block6); + block6.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case LSR: /* * value = shiftedOperand >>> shiftAmount; - */ - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_USHR, resultRegister, shiftedOperand, shiftAmount)); - + block6 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block5 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block4 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block3 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); //current block + curBlock.deleteNormalOut(); + curBlock.insertOut(block6); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block6.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 1 + //block 1 - shift != 0 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER_EQUAL(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); - //block 2 + //block 2 - Shift != 0 && Shift < 32 translator.arm2ir.setCurrentBlock(block2); block2.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, shiftAmount, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1))); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); - //block 3 + //block 3 - Shift >= 32 translator.arm2ir.setCurrentBlock(block3); - block3.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock( Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); - + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.EQUAL(), block5.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + block3.insertOut(block4); + block3.insertOut(block5); + + //block 4 - Shift > 32 + translator.arm2ir.setCurrentBlock(block4); + block4.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 5 - Shift == 32 + translator.arm2ir.setCurrentBlock(block5); + block5.insertOut(nextBlock); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 31); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + + //block 6 - shift == 0 + translator.arm2ir.setCurrentBlock(block6); + block6.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case ROR: /* * return Integer.rotateRight(value, shiftAmount); */ - translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); - + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); //current block + curBlock.deleteNormalOut(); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + curBlock.insertOut(block2); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), block2.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock( Binary.create(INT_SUB, tmp, shiftAmount, new OPT_IntConstantOperand(1)) ); - translator.arm2ir.appendInstructionToCurrentBlock( Binary.create(INT_AND, tmp, shiftAmount, new OPT_IntConstantOperand(0x1F)) ); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, tmp, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, shiftAmount, new OPT_IntConstantOperand(-1)) ); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, tmp, tmp, new OPT_IntConstantOperand(0x1F)) ); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp); + translator.arm2ir.appendInstructionToCurrentBlock(Goto.create(GOTO, nextBlock.makeJumpTarget())); + //block 2 + translator.arm2ir.setCurrentBlock(block2); + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, resultRegister, shiftedOperand)); break; case RRX: @@ -484,30 +583,23 @@ * value = shiftedOperand >>> 1; * if (regs.isCarrySet()) value |= 0x80000000; */ - - // resultRegister = shiftedOperand >>> 1 - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, new OPT_IntConstantOperand(1), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); - - //conditionally, set resultRegister = resultRegister | 0x80000000; block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - //Current block + //Current Block + curBlock.deleteNormalOut(); curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), - new OPT_IntConstantOperand(1), OPT_ConditionOperand - .EQUAL(), block1.makeJumpTarget(), - new OPT_BranchProfileOperand())); + curBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); + translator.arm2ir.appendInstructionToCurrentBlock(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.appendInstructionToCurrentBlock(BinaryAcc.create( - INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_OR, resultRegister, resultRegister, new OPT_IntConstantOperand(0x80000000))); + //nextBlock + translator.arm2ir.setCurrentBlock(nextBlock); + translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 0); break; default: @@ -516,7 +608,6 @@ } translator.arm2ir.setCurrentBlock(nextBlock); - translator.arm2ir.setNextBlock( translator.arm2ir.createBlockAfterCurrent() ); return resultRegister; } } @@ -1030,24 +1121,22 @@ OPT_BasicBlock addWithCarry = arm2ir.createBlockAfterCurrentNotInCFG(); //Is the carry set at all? if not, just jump to addWithoutCarry - arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand1)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand())); arm2ir.getCurrentBlock().insertOut(addWithCarry); //Yes, the carry flag is set. Pre-increase the result by one to account for the carry. arm2ir.setCurrentBlock(addWithCarry); - arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_ADD_ACC, result, new OPT_IntConstantOperand(1))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, result, new OPT_IntConstantOperand(1))); addWithCarry.insertOut(addWithoutCarry); //Finally, add the second operands to the result - arm2ir.setCurrentBlock(addWithoutCarry); - arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_ADD_ACC, result, operand2)); - + arm2ir.setCurrentBlock(addWithoutCarry); setAddResult(result, operand1, operand2); } } - /** Subtract with carry. <code>Rd = op1 - op2 + CARRY</code>.*/ + /** Subtract with carry. <code>Rd = op1 - op2 - NOT(CARRY)</code>.*/ private class DataProcessing_Sbc extends DataProcessing { protected DataProcessing_Sbc(int instr) { @@ -1063,24 +1152,22 @@ OPT_BasicBlock subWithCarry = arm2ir.createBlockAfterCurrentNotInCFG(); //Is the carry set? if yes, just jump to subWithoutCarry - arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand1)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), subWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand())); arm2ir.getCurrentBlock().insertOut(subWithCarry); //No, the carry flag is not set. That means, we have to use the carry within the subtraction (weird arm logic). arm2ir.setCurrentBlock(subWithCarry); - arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_SUB_ACC, result, new OPT_IntConstantOperand(1))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, result, new OPT_IntConstantOperand(1))); subWithCarry.insertOut(subWithoutCarry); //Finally, subtract the second operands from the result arm2ir.setCurrentBlock(subWithoutCarry); - arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_SUB_ACC, result, operand2)); - setSubResult(result, operand1, operand2); } } - /** Reserve subtract with carry. <code>Rd = -op1 + op2 + CARRY</code>.*/ + /** Reserve subtract with carry. <code>Rd = -op1 + op2 - NOT(CARRY)</code>.*/ private final class DataProcessing_Rsc extends DataProcessing_Sbc { protected DataProcessing_Rsc(int instr) { Modified: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java 2007-05-16 18:14:22 UTC (rev 117) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java 2007-05-16 18:15:51 UTC (rev 118) @@ -15,7 +15,7 @@ protected ReadableFile openCpuInfo() { String output = ""; - output += "Processor : XScale-IOP80321 rev 2 (v5l)\n"; + output += "Processor : XScale-IOP80321 rev 2 (v5l)\n"; output += "BogoMIPS : 599.65\n"; output += "Features : swp half thumb fastmult edsp\n"; output += "\n"; Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-05-16 18:14:22 UTC (rev 117) +++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-05-16 18:15:51 UTC (rev 118) @@ -143,7 +143,7 @@ private String previousInputLine = null; public void close() { - throw new RuntimeException("The stdin and stdout are not closeable."); + throw new RuntimeException("Stdin and stdout are not closeable."); } public int getLength() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-16 18:14:22
|
Revision: 117 http://svn.sourceforge.net/pearcolator/?rev=117&view=rev Author: michael_baer Date: 2007-05-16 11:14:22 -0700 (Wed, 16 May 2007) Log Message: ----------- Removed a warning Modified Paths: -------------- src/org/binarytranslator/generic/fault/SegmentationFault.java Modified: src/org/binarytranslator/generic/fault/SegmentationFault.java =================================================================== --- src/org/binarytranslator/generic/fault/SegmentationFault.java 2007-05-16 18:14:08 UTC (rev 116) +++ src/org/binarytranslator/generic/fault/SegmentationFault.java 2007-05-16 18:14:22 UTC (rev 117) @@ -12,7 +12,7 @@ * @author Ian Rogers */ public class SegmentationFault extends RuntimeException { - private final int address; + protected final int address; /** * Constructor */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-16 18:14:17
|
Revision: 116 http://svn.sourceforge.net/pearcolator/?rev=116&view=rev Author: michael_baer Date: 2007-05-16 11:14:08 -0700 (Wed, 16 May 2007) Log Message: ----------- Enhanced virtual file system with capabilities to query a file's size Modified Paths: -------------- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/abi/linux/files/ConsoleIn.java src/org/binarytranslator/generic/os/abi/linux/files/ConsoleOut.java src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java src/org/binarytranslator/generic/os/abi/linux/files/HostFile.java src/org/binarytranslator/generic/os/abi/linux/files/OpenFile.java src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-15 21:58:53 UTC (rev 115) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-16 18:14:08 UTC (rev 116) @@ -8,13 +8,19 @@ */ package org.binarytranslator.generic.os.abi.linux; +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; + import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; +import org.binarytranslator.generic.os.abi.linux.LinuxConstants.errno; +import org.binarytranslator.generic.os.abi.linux.LinuxConstants.fcntl; +import org.binarytranslator.generic.os.abi.linux.LinuxConstants.mman; import org.binarytranslator.generic.os.abi.linux.files.ConsoleIn; import org.binarytranslator.generic.os.abi.linux.files.ConsoleOut; -import org.binarytranslator.generic.os.abi.linux.files.HostFile; import org.binarytranslator.generic.os.abi.linux.files.OpenFile; import org.binarytranslator.generic.os.abi.linux.files.OpenFileList; import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; @@ -25,15 +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.abi.linux.LinuxConstants.*; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.net.InetAddress; -import java.net.UnknownHostException; - /** * Linux system call handling class */ @@ -344,6 +342,9 @@ // accordingly. args[0] points to the file name. String fileName = memoryReadString(pathname); + if (DBT_Options.debugSyscall) + System.err.println("Program tries to open: " + fileName); + FileMode mode; //shall we create the target file? @@ -459,6 +460,7 @@ public class SysFstat64 extends SystemCall { public void doSysCall() { int fd = arguments.nextInt(); + int structAddr = arguments.nextInt(); LinuxStructureFactory.stat64 buf = structures.new_stat64(); @@ -467,10 +469,22 @@ buf.st_rdev = (short) 0x8800; buf.__st_ino = buf.st_ino = 2; buf.st_blksize = 0x400; - } else - throw new RuntimeException("Unimplemented system call."); + } else { + + try { + //get the file from the file descriptor table + OpenFile file = openFiles.get(fd); + OpenFile.Info info = file.getFileInfo(); - buf.write(src.getProcessSpace().memory, arguments.nextInt()); + buf.st_size = info.size; + } catch (InvalidFileDescriptor e) { + src.setSysCallError(errno.EBADF); + } catch (Exception e) { + src.setSysCallError(errno.EIO); + } + } + + buf.write(src.getProcessSpace().memory, structAddr); src.setSysCallReturn(0); } } Modified: src/org/binarytranslator/generic/os/abi/linux/files/ConsoleIn.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/ConsoleIn.java 2007-05-15 21:58:53 UTC (rev 115) +++ src/org/binarytranslator/generic/os/abi/linux/files/ConsoleIn.java 2007-05-16 18:14:08 UTC (rev 116) @@ -15,4 +15,8 @@ //no-op } + public Info getFileInfo() { + return null; + } + } Modified: src/org/binarytranslator/generic/os/abi/linux/files/ConsoleOut.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/ConsoleOut.java 2007-05-15 21:58:53 UTC (rev 115) +++ src/org/binarytranslator/generic/os/abi/linux/files/ConsoleOut.java 2007-05-16 18:14:08 UTC (rev 116) @@ -21,4 +21,8 @@ public void close() throws IOException { //no-op } + + public Info getFileInfo() { + return null; + } } Modified: src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java 2007-05-15 21:58:53 UTC (rev 115) +++ src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java 2007-05-16 18:14:08 UTC (rev 116) @@ -48,4 +48,8 @@ //no-op } + public Info getFileInfo() { + return new Info(data.length); + } + } Modified: src/org/binarytranslator/generic/os/abi/linux/files/HostFile.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/HostFile.java 2007-05-15 21:58:53 UTC (rev 115) +++ src/org/binarytranslator/generic/os/abi/linux/files/HostFile.java 2007-05-16 18:14:08 UTC (rev 116) @@ -47,4 +47,9 @@ file.write(bytes); } } + + public Info getFileInfo() throws IOException { + + return new Info((int)file.length()); + } } Modified: src/org/binarytranslator/generic/os/abi/linux/files/OpenFile.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/OpenFile.java 2007-05-15 21:58:53 UTC (rev 115) +++ src/org/binarytranslator/generic/os/abi/linux/files/OpenFile.java 2007-05-16 18:14:08 UTC (rev 116) @@ -6,5 +6,15 @@ * A base interface for all open files within linux. */ public interface OpenFile { + Info getFileInfo() throws IOException; void close() throws IOException; + + + public class Info { + public int size; + + public Info(int size) { + this.size = size; + } + } } Modified: src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java 2007-05-15 21:58:53 UTC (rev 115) +++ src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java 2007-05-16 18:14:08 UTC (rev 116) @@ -51,6 +51,10 @@ if (files.get(preferredFd) != null) { preferredFd = nextFileHandle++; } + else { + if (preferredFd >= nextFileHandle) + nextFileHandle = preferredFd + 1; + } files.put(preferredFd, file); return preferredFd; Modified: src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java 2007-05-15 21:58:53 UTC (rev 115) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java 2007-05-16 18:14:08 UTC (rev 116) @@ -5,15 +5,21 @@ /** * A file system decorator, that prevents all write-accesses to this file system. */ -public final class ReadonlyFilesystem implements FileProvider { +public final class ReadonlyFilesystem extends ChainedFileProvider { private final FileProvider filesystem; public ReadonlyFilesystem(FileProvider filesystem) { + this(filesystem, null); + } + + public ReadonlyFilesystem(FileProvider filesystem, FileProvider nextFilesystem) { + super(nextFilesystem); this.filesystem = filesystem; } - public OpenFile openFile(String file, FileMode mode) { + @Override + protected OpenFile tryOpen(String file, FileMode mode) { if (mode != FileMode.Read) return null; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-15 21:59:10
|
Revision: 115 http://svn.sourceforge.net/pearcolator/?rev=115&view=rev Author: michael_baer Date: 2007-05-15 14:58:53 -0700 (Tue, 15 May 2007) Log Message: ----------- Added more flexible support for file system emulation Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java Added Paths: ----------- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java src/org/binarytranslator/generic/os/abi/linux/filesystem/ src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java Modified: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-05-14 22:14:10 UTC (rev 114) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_LinuxSystemCalls.java 2007-05-15 21:58:53 UTC (rev 115) @@ -3,6 +3,7 @@ import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider; public class ARM_LinuxSystemCalls extends LinuxSystemCalls { @@ -32,12 +33,10 @@ systemCallTable[202] = new LinuxSystemCalls.SysGetEGID(); systemCallTable[221] = new LinuxSystemCalls.SysFcntl64(); systemCallTable[252] = new LinuxSystemCalls.SysExitGroup(); - } @Override public void doSysCall() { - super.doSysCall(); } @@ -46,6 +45,12 @@ //TODO: Grab this from a real machine return "ARM"; } + + @Override + protected FileProvider buildFileSystem() { + ARM_ProcFileSystem fs = new ARM_ProcFileSystem(super.buildFileSystem()); + return fs; + } @Override public String sysCallToString(int syscall) { Added: src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java =================================================================== --- src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java (rev 0) +++ src/org/binarytranslator/arch/arm/os/abi/linux/ARM_ProcFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,29 @@ +package org.binarytranslator.arch.arm.os.abi.linux; + +import org.binarytranslator.generic.os.abi.linux.files.FixedContentFile; +import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider; +import org.binarytranslator.generic.os.abi.linux.filesystem.ProcFileSystem; + +public class ARM_ProcFileSystem extends ProcFileSystem { + + public ARM_ProcFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected ReadableFile openCpuInfo() { + + String output = ""; + output += "Processor : XScale-IOP80321 rev 2 (v5l)\n"; + output += "BogoMIPS : 599.65\n"; + output += "Features : swp half thumb fastmult edsp\n"; + output += "\n"; + output += "Hardware : Iyonix\n"; + output += "Revision : 0000\n"; + output += "Serial : 0000000000000000\n"; + + return new FixedContentFile(output); + } + +} Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-14 22:14:10 UTC (rev 114) +++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-05-15 21:58:53 UTC (rev 115) @@ -8,6 +8,7 @@ */ package org.binarytranslator.generic.os.abi.linux; +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.generic.memory.Memory; import org.binarytranslator.generic.memory.MemoryMapException; @@ -19,6 +20,11 @@ import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; import org.binarytranslator.generic.os.abi.linux.files.WriteableFile; import org.binarytranslator.generic.os.abi.linux.files.OpenFileList.InvalidFileDescriptor; +import org.binarytranslator.generic.os.abi.linux.filesystem.FileProvider; +import org.binarytranslator.generic.os.abi.linux.filesystem.HostFileSystem; +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.abi.linux.LinuxConstants.*; import java.io.File; @@ -46,6 +52,9 @@ /** List of currently opened files. */ protected OpenFileList openFiles; + /** List of currently opened files. */ + protected FileProvider filesystem; + /** The top of the bss segment */ protected int brk; @@ -144,16 +153,32 @@ openFiles = new OpenFileList(); - if (openFiles.open(new ConsoleIn(), 0) != 0 - || openFiles.open(new ConsoleOut(System.out), 1) != 1 - || openFiles.open(new ConsoleOut(System.err), 2) != 2) { + if (openFiles.add(new ConsoleIn(), 0) != 0 + || openFiles.add(new ConsoleOut(System.out), 1) != 1 + || openFiles.add(new ConsoleOut(System.err), 2) != 2) { throw new RuntimeException( "File descriptors for standard streams could not be assigned correctly."); } structures = new LinuxStructureFactory(); + filesystem = buildFileSystem(); } + + /** + * This method creates a virtual file system for this linux host. Override it, to create a specific file systems + * for an architecture. + * + * The standard implementation mounts the host's file system readonly but enables writes to the host's temp directory. + * @return + * A {@link FileProvider} that will be used to access the file system for this host. + */ + protected FileProvider buildFileSystem() { + FileProvider fs = new HostFileSystem(null); + fs = new ReadonlyFilesystem(fs); + fs = new TempFileSystem(fs); + return fs; + } /** * Handle a system call @@ -318,42 +343,51 @@ // Examine the flags argument and open read or read-write // accordingly. args[0] points to the file name. String fileName = memoryReadString(pathname); + + FileMode mode; - // Create a File object so we can test for the existance and - // properties of the file. - File testFile = new File(fileName); - - if (((flags & fcntl.O_CREAT) != 0) && ((flags & fcntl.O_EXCL) != 0) - && testFile.exists()) { - // O_CREAT specified. If O_EXCL also specified, we require - // that the file does not already exist - src.setSysCallError(errno.EEXIST); - return; - } else if (((flags & fcntl.O_CREAT) != 0) && !testFile.exists()) { - // O_CREAT not specified. We require that the file exists. - src.setSysCallError(errno.ENOENT); - return; + //shall we create the target file? + if ((flags & fcntl.O_CREAT) != 0) { + //We want to create a file. This also implies that we're gonna write to it + mode = FileMode.WriteCreate; + if (DBT.VerifyAssertions) DBT._assert((flags & 0x3) != fcntl.O_RDONLY); + + //Yes, we want to create that file. Do we demand that it does not yet exist? + if ((flags & fcntl.O_EXCL) != 0) { + //check if it does not exist by trying to open it + OpenFile testfile = filesystem.openFile(fileName, FileMode.Read); + + if (testfile != null) { + //the file we're trying to create already exists. With O_EXCL, this is an error condition. + src.setSysCallError(errno.EEXIST); + try { + testfile.close(); + } catch (IOException e) {} + + return; + } + } } - - // we have not found an error, so we go ahead and try to open the file - try { - RandomAccessFile raFile; - int fd; - - if ((flags & 0x3) == fcntl.O_RDONLY) { - raFile = new RandomAccessFile(fileName, "r"); - fd = openFiles.open(HostFile.forReading(raFile)); - } else { - // NB Java RandomAccessFile has no write only - raFile = new RandomAccessFile(fileName, "rw"); - fd = openFiles.open(HostFile.forWriting(raFile)); - } - src.setSysCallReturn(fd); - } catch (FileNotFoundException e) { - System.err.println("Open tried to open non-existent file: " + fileName); + else { + //we shall not create the file. Check if we're supposed to open it for reading, though + if ((flags & 0x3) == fcntl.O_RDONLY) + mode = FileMode.Read; + else + mode = FileMode.Write; + } + + OpenFile file = filesystem.openFile(fileName, mode); + + //did we successfully open the file? + if (file == null) { + //if not, return with an error src.setSysCallError(errno.ENOENT); return; } + + //otherwise add it to the list of open files and return a handle to the file + int fd = openFiles.add(file); + src.setSysCallReturn(fd); // NOT YET HANDLING ALL THE flags OPTIONS (IW have included // TRUNC & APPEND but not properly!) Added: src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/files/FixedContentFile.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,51 @@ +package org.binarytranslator.generic.os.abi.linux.files; + +import java.io.IOException; + +/** + * This is a file, for which the content is given by a constant string or byte array. + */ +public class FixedContentFile implements ReadableFile { + + /** The data that is actually returned to a reader. */ + protected final byte[] data; + + /** An integer offset into the {@link #data} array, that points at the next byte that is to be read. */ + protected int readPtr; + + public FixedContentFile(byte[] data) { + readPtr = 0; + this.data = data; + } + + public FixedContentFile(String asciiData) { + readPtr = 0; + data = new byte[asciiData.length()]; + + for (int i = 0; i < asciiData.length(); i++) + data[i] = (byte)asciiData.charAt(i); + } + + public int read(byte[] buffer) throws IOException { + + if (readPtr == data.length) { + return -1; + } + + for (int i = 0; i < buffer.length; i++) { + + if (readPtr == data.length) { + return i; + } + + buffer[i] = data[readPtr++]; + } + + return buffer.length; + } + + public void close() throws IOException { + //no-op + } + +} Modified: src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java 2007-05-14 22:14:10 UTC (rev 114) +++ src/org/binarytranslator/generic/os/abi/linux/files/OpenFileList.java 2007-05-15 21:58:53 UTC (rev 115) @@ -27,7 +27,7 @@ * @return * The file descriptor that identifies this file. */ - public int open(OpenFile file) { + public int add(OpenFile file) { int handle = nextFileHandle++; files.put(nextFileHandle, file); @@ -47,7 +47,7 @@ * @return * The file descriptor that identifies this file. */ - public int open(OpenFile file, int preferredFd) { + public int add(OpenFile file, int preferredFd) { if (files.get(preferredFd) != null) { preferredFd = nextFileHandle++; } Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/ChainedFileProvider.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,34 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * This is a base class for file system that follow the chain of responsibility pattern. + * In this pattern, all file systems are chained and if one file system cannot handle the request to + * open a specific file, the request is forwarded to the next file system until either one system + * can provide the file or the end of the chain is reached. + * + */ +public abstract class ChainedFileProvider implements FileProvider { + + protected final FileProvider nextProvider; + + public ChainedFileProvider(FileProvider nextProvider) { + + if (nextProvider == null) + nextProvider = new NullFileSystem(); + + this.nextProvider = nextProvider; + } + + public OpenFile openFile(String file, FileMode mode) { + OpenFile result = tryOpen(file, mode); + + if (result == null) + result = nextProvider.openFile(file, mode); + + return result; + } + + protected abstract OpenFile tryOpen(String file, FileMode mode); +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/FileProvider.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,26 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * The FileProvider interface defines the methods that any class shall implement, that serves as (part) + * of the virtual file system that is simulated for the linux guest OS. */ +public interface FileProvider { + + public enum FileMode { + Read, + Write, + WriteCreate + } + + /** + * Opens the given file on the host. + * @param file + * The path of the file that is to be opened. + * @param mode + * The mode with which the file shall be opened. + * @return + * A file object representing the file on success or null otherwise. + */ + public OpenFile openFile(String file, FileMode mode); +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/HostFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,50 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.RandomAccessFile; + +import org.binarytranslator.generic.os.abi.linux.files.HostFile; +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +public class HostFileSystem extends ChainedFileProvider { + + + public HostFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected OpenFile tryOpen(String file, FileMode mode) { + + try { + File f = new File(file); + + if (!f.isFile()) + return null; + + switch (mode) { + case Read: + if (!f.exists()) + return null; + + return HostFile.forReading(new RandomAccessFile(f, "r")); + + case Write: + if (!f.exists()) + return null; + + return HostFile.forWriting(new RandomAccessFile(f, "rw")); + + case WriteCreate: + return HostFile.forWriting(new RandomAccessFile(f, "rw")); + + default: + throw new RuntimeException("Invalid file open mode: " + mode); + } + + } catch (FileNotFoundException e) { + return null; + } + } +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/NullFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,15 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * A NULL filesystem object. + * + */ +public class NullFileSystem implements FileProvider { + + public OpenFile openFile(String file, FileMode mode) { + //no-nop + return null; + } +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/ProcFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,32 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; +import org.binarytranslator.generic.os.abi.linux.files.ReadableFile; + +/** Represents the Unix /proc/ file system. */ +public abstract class ProcFileSystem extends ChainedFileProvider { + + /** A string that defines the path of the virtual proc file system on the guest. */ + protected final static String PROC_DIRECTORY_PATH = "/proc/"; + + public ProcFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected OpenFile tryOpen(String file, FileMode mode) { + if (!file.startsWith(PROC_DIRECTORY_PATH)) + return null; + + if (file.equals(PROC_DIRECTORY_PATH + "cpuinfo") && mode == FileMode.Read) + return openCpuInfo(); + + return null; + } + + /** + * Called when the application tries to open /proc/cpuinfo. + * Implement it by returning a {@link ReadableFile} that contains the information usually returned by /proc/cpuinfo. + */ + protected abstract ReadableFile openCpuInfo(); +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/ReadonlyFilesystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,22 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** + * A file system decorator, that prevents all write-accesses to this file system. + */ +public final class ReadonlyFilesystem implements FileProvider { + + private final FileProvider filesystem; + + public ReadonlyFilesystem(FileProvider filesystem) { + this.filesystem = filesystem; + } + + public OpenFile openFile(String file, FileMode mode) { + if (mode != FileMode.Read) + return null; + + return filesystem.openFile(file, mode); + } +} Added: src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java =================================================================== --- src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java (rev 0) +++ src/org/binarytranslator/generic/os/abi/linux/filesystem/TempFileSystem.java 2007-05-15 21:58:53 UTC (rev 115) @@ -0,0 +1,22 @@ +package org.binarytranslator.generic.os.abi.linux.filesystem; + +import org.binarytranslator.generic.os.abi.linux.files.OpenFile; + +/** This class allows write-access to the /tmp file system from the guest. */ +public class TempFileSystem extends HostFileSystem { + + /** A string that defines the location of the tmp file system on the guest. */ + protected final static String TMP_FILE_PATH = "/tmp/"; + + public TempFileSystem(FileProvider nextProvider) { + super(nextProvider); + } + + @Override + protected OpenFile tryOpen(String file, FileMode mode) { + if (!file.startsWith(TMP_FILE_PATH)) + return null; + + return super.tryOpen(file, mode); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-14 22:14:09
|
Revision: 114 http://svn.sourceforge.net/pearcolator/?rev=114&view=rev Author: michael_baer Date: 2007-05-14 15:14:10 -0700 (Mon, 14 May 2007) Log Message: ----------- First ARM DBT version that runs glibc "Hello World" Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.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/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-11 17:38:08 UTC (rev 113) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-14 22:14:10 UTC (rev 114) @@ -371,17 +371,8 @@ @Override protected int translateInstruction(Laziness lazy, int pc) { - System.out.println("Translating address: 0x" + Integer.toHexString(pc)); - System.out.println("Instruction: " + ARM_Disassembler.disassemble(pc, ps).asString()); - OPT_BasicBlock curBlock = getCurrentBlock(); - - int nextAddr = translator.translateInstruction(pc, (ARM_Laziness)lazy); - - if (nextAddr == -1) { - printNextBlocks(curBlock, 5); - } - + int nextAddr = translator.translateInstruction(pc, (ARM_Laziness)lazy); return nextAddr; } @@ -390,7 +381,7 @@ * @param block * @param count */ - private void printNextBlocks(OPT_BasicBlock block, int count) { + public void printNextBlocks(OPT_BasicBlock block, int count) { do { block.printExtended(); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-11 17:38:08 UTC (rev 113) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-14 22:14:10 UTC (rev 114) @@ -639,7 +639,7 @@ } else if (operand2 != Integer.MAX_VALUE) { operand2++; } else { - regs.setFlags(operand1 > 0, operand1 != 0, true, true); + regs.setFlags(true, true, true, true); //set the result to any of the operands regs.set(Rd, operand1); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-11 17:38:08 UTC (rev 113) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-14 22:14:10 UTC (rev 114) @@ -104,10 +104,6 @@ return value; } - protected OPT_RegisterOperand getTempInt() { - return translator.arm2ir.getTempInt(0); - } - private static class ResolvedOperand_WithoutShifterCarryOut extends ResolvedOperand { @@ -181,7 +177,7 @@ .getShiftingRegister()); } - OPT_RegisterOperand resultRegister = getTempInt(); + OPT_RegisterOperand resultRegister = translator.arm2ir.getTempInt(9); switch (operand.getShiftType()) { case ASR: @@ -221,18 +217,18 @@ case RRX: /* - * value = resultRegister >>> 1; - * if (regs.isCarrySet()) value |= 0x80000000; + * result = shiftedOperand >>> 1; + * if (regs.isCarrySet()) result |= 0x80000000; */ - // resultRegister = resultRegister >>> 1 - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( - INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + // resultRegister = shiftedOperand >>> 1 + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); //conditionally, set resultRegister = resultRegister | 0x80000000; OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); - OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); + OPT_BasicBlock nextBlock = translator.arm2ir.createBlockAfterCurrent(); OPT_BasicBlock block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); //Current block @@ -247,7 +243,7 @@ translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + translator.arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create( INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); translator.arm2ir.setCurrentBlock(nextBlock); @@ -261,11 +257,6 @@ } } - - - - - private static class ResolvedOperand_WithShifterCarryOut extends ResolvedOperand { @@ -350,15 +341,13 @@ .getShiftingRegister()); } - OPT_RegisterOperand resultRegister = getTempInt(); + OPT_RegisterOperand resultRegister = translator.arm2ir.getTempInt(8); + OPT_RegisterOperand tmp = translator.arm2ir.getTempInt(9); + OPT_RegisterOperand validation = translator.arm2ir.getTempValidation(0); - OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); + OPT_BasicBlock nextBlock = translator.arm2ir.createBlockAfterCurrent(); OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); OPT_BasicBlock block1, block2, block3; - - OPT_RegisterOperand validation = translator.arm2ir.getTempValidation(0); - - OPT_RegisterOperand tmp = translator.arm2ir.getTempInt(9); switch (operand.getShiftType()) { case ASR: @@ -492,13 +481,13 @@ case RRX: /* - * value = resultRegister >>> 1; + * value = shiftedOperand >>> 1; * if (regs.isCarrySet()) value |= 0x80000000; */ - // resultRegister = resultRegister >>> 1 - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( - INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + // resultRegister = shiftedOperand >>> 1 + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_USHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(1))); translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, new OPT_IntConstantOperand(1), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); //conditionally, set resultRegister = resultRegister | 0x80000000; @@ -516,7 +505,7 @@ translator.arm2ir.setCurrentBlock(block1); block1.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + translator.arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create( INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); break; @@ -662,7 +651,7 @@ default: throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); } - + arm2ir.setCurrentBlock(condBlock); conditionalInstruction.translate(); @@ -685,7 +674,7 @@ private void translateCondition_HI(OPT_BasicBlock nextInstruction) { //return regs.isCarrySet() && !regs.isZeroSet(); OPT_Operand carry = arm2ir.getCarryFlag(); - OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, carry, @@ -697,7 +686,7 @@ private void translateCondition_LS(OPT_BasicBlock nextInstruction) { //return !regs.isCarrySet() || regs.isZeroSet(); OPT_Operand carry = arm2ir.getCarryFlag(); - OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, carry, @@ -710,7 +699,7 @@ //return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); OPT_Operand negative = arm2ir.getNegativeFlag(); OPT_Operand overflow = arm2ir.getOverflowFlag(); - OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, negative, @@ -723,7 +712,7 @@ //return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); OPT_Operand negative = arm2ir.getNegativeFlag(); OPT_Operand overflow = arm2ir.getOverflowFlag(); - OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getZeroFlag(); OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, negative, @@ -732,7 +721,6 @@ arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } - public Condition getCondition() { return conditionalInstruction.getCondition(); } @@ -802,7 +790,7 @@ * @param rhs * The add's right-hand-side operator. */ - protected void setAddFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setAddFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { //set the carry flag arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.CARRY_FROM_ADD(), new OPT_BranchProfileOperand())); @@ -848,7 +836,7 @@ * @param rhs * The sub's right-hand-side operator. */ - protected void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { //set the carry flag to not(Borrow) arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); @@ -888,7 +876,7 @@ protected OPT_Operand resolveOperand2() { if (updateConditionCodes) { - return ResolvedOperand.resolveAndStoreShifterCarryOutToCarry(ARM_Translator.this, operand2); + return ResolvedOperand.resolveAndStoreShifterCarryOutToCarry(ARM_Translator.this, operand2); } else { return super.resolveOperand2(); @@ -918,7 +906,7 @@ * @param result * The result of the logical operation */ - protected void setLogicalFlags(OPT_Operand result) { + protected final void setLogicalFlags(OPT_Operand result) { //the shifter carry out has already been set during the resolve-phase //set the negative flag @@ -1016,7 +1004,7 @@ OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = getResultRegister(); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand2, operand1)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand2, operand1)); setSubResult(result, operand2, operand1); } @@ -1034,43 +1022,28 @@ @Override public void translate() { - throw new RuntimeException("Not yet implemented"); - - /* OPT_Operand operand1 = resolveOperand1(); OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = getResultRegister(); - OPT_RegisterOperand long_op1 = arm2ir.getTempLong(0); - OPT_RegisterOperand long_op2 = arm2ir.getTempLong(1); - OPT_RegisterOperand long_result = arm2ir.getTempLong(2); - OPT_RegisterOperand long_tmp = arm2ir.getTempLong(3); + OPT_BasicBlock addWithoutCarry = arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock addWithCarry = arm2ir.createBlockAfterCurrentNotInCFG(); + + //Is the carry set at all? if not, just jump to addWithoutCarry + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand1)); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.getCurrentBlock().insertOut(addWithCarry); + + //Yes, the carry flag is set. Pre-increase the result by one to account for the carry. + arm2ir.setCurrentBlock(addWithCarry); + arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_ADD_ACC, result, new OPT_IntConstantOperand(1))); + addWithCarry.insertOut(addWithoutCarry); + + //Finally, add the second operands to the result + arm2ir.setCurrentBlock(addWithoutCarry); + arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_ADD_ACC, result, operand2)); - //convert the operands to longs. Be careful to treat them as unsigned ints during the conversion - arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, long_op1, operand1)); - arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_op1, long_op1, new OPT_LongConstantOperand(0xFFFFFFFF))); - arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, long_op2, operand2)); - arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_op2, long_op2, new OPT_LongConstantOperand(0xFFFFFFFF))); - - //perform the actual addition - arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_ADD, long_result, long_op1, long_op2)); - arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_ADD, long_result, long_result, new OPT_LongConstantOperand(1))); - arm2ir.appendInstructionToCurrentBlock(Unary.create(LONG_2INT, result, long_result)); - - //set the carry flag if the upper 32 bit of the result are != 0 - arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_tmp, long_result, new OPT_LongConstantOperand(0xFFFFFFFF))); - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), long_tmp, new OPT_LongConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), OPT_BranchProfileOperand.unlikely())); - - //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); - - //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - - //commit the result - setResult(result);*/ + setAddResult(result, operand1, operand2); } } @@ -1084,28 +1057,26 @@ public void translate() { OPT_Operand operand1 = resolveOperand1(); OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); - //TODO: Implement - throw new RuntimeException("Not yet implemented"); - - /* - if (!regs.isCarrySet()) { - if (operand1 != Integer.MIN_VALUE) { - operand1--; - } else if (operand2 != Integer.MIN_VALUE) { - operand2--; - } else { - //TODO: Remove this exception, when the correct behavior has been verified. - throw new RuntimeException("I'm interested in finding a case where this occurs, so this exception is sooner or later going to 'notify' me.."); - //regs.setFlags(operand1 > 0, operand1 != 0, true, true); - //return; - } - } + OPT_BasicBlock subWithoutCarry = arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock subWithCarry = arm2ir.createBlockAfterCurrentNotInCFG(); - int result = operand1 - operand2; + //Is the carry set? if yes, just jump to subWithoutCarry + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand1)); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), subWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.getCurrentBlock().insertOut(subWithCarry); + + //No, the carry flag is not set. That means, we have to use the carry within the subtraction (weird arm logic). + arm2ir.setCurrentBlock(subWithCarry); + arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_SUB_ACC, result, new OPT_IntConstantOperand(1))); + subWithCarry.insertOut(subWithoutCarry); - regs.set(Rd, result); - setFlagsForSub(operand1, operand2);*/ + //Finally, subtract the second operands from the result + arm2ir.setCurrentBlock(subWithoutCarry); + arm2ir.appendInstructionToCurrentBlock(BinaryAcc.create(INT_SUB_ACC, result, operand2)); + + setSubResult(result, operand1, operand2); } } @@ -1950,15 +1921,23 @@ switch (size) { case Word: + //perform the actual memory access ps.memory.translateLoad32(address, value); //according to the ARM reference, the last two bits cause the value to be right-rotated - OPT_RegisterOperand rotation = arm2ir.getTempInt(0); + OPT_RegisterOperand rotation = arm2ir.getTempInt(1); + + //make sure that we're not loosing the address due to the shifting + OPT_RegisterOperand adrCopy = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, adrCopy, address)); //rotation = (address & 0x3) * 8 arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, rotation, address, new OPT_IntConstantOperand(0x3))); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHL, rotation, rotation, new OPT_IntConstantOperand(3))); arm2ir.appendRotateRight(value, value, rotation); + + //allow further usage of the memory address + address = adrCopy; break; case HalfWord: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-11 17:38:06
|
Revision: 113 http://svn.sourceforge.net/pearcolator/?rev=113&view=rev Author: michael_baer Date: 2007-05-11 10:38:08 -0700 (Fri, 11 May 2007) Log Message: ----------- - Loads of bugfixes concerning the ARM DBT 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_Translator.java src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-11 17:37:08 UTC (rev 112) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-11 17:38:08 UTC (rev 113) @@ -209,6 +209,7 @@ //first resolve the current lazy state (i.e. calculate the values of registers that are not yet resolved) resolveLaziness(lazyState); + spillAllFlags(); } private void spillAllFlags() { @@ -236,6 +237,13 @@ //get an operand that contains a reference to the current ps.registers field. OPT_RegisterOperand ps_registersOp = getArmRegistersReference(); + + if (carryFlag == null) { + carryFlag = gc.temps.getReg(VM_TypeReference.Boolean); + negativeFlag = gc.temps.getReg(VM_TypeReference.Boolean); + zeroFlag = gc.temps.getReg(VM_TypeReference.Boolean); + overflowFlag = gc.temps.getReg(VM_TypeReference.Boolean); + } //get the carry flag OPT_RegisterOperand flag = new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); @@ -364,12 +372,34 @@ @Override protected int translateInstruction(Laziness lazy, int pc) { System.out.println("Translating address: 0x" + Integer.toHexString(pc)); - System.out.println("Instruction: " + ARM_Disassembler.disassemble(pc, ps)); + System.out.println("Instruction: " + ARM_Disassembler.disassemble(pc, ps).asString()); - return translator.translateInstruction(pc, (ARM_Laziness)lazy); + OPT_BasicBlock curBlock = getCurrentBlock(); + + int nextAddr = translator.translateInstruction(pc, (ARM_Laziness)lazy); + + if (nextAddr == -1) { + printNextBlocks(curBlock, 5); + } + + return nextAddr; } /** + * Prints the given BasicBlock and the <code>count</code> blocks following it in code order. + * @param block + * @param count + */ + private void printNextBlocks(OPT_BasicBlock block, int count) { + do + { + block.printExtended(); + block = block.nextBasicBlockInCodeOrder(); + } + while (block != null && count-- > 0); + } + + /** * Adds code to the current block that will rotate <code>rotatedOperand</code> by * <code>rotation</code> and stores the rotated integer into <code>result</code>. * @param result @@ -394,8 +424,8 @@ OPT_MethodOperand methOp = OPT_MethodOperand .STATIC(rotateRightMethod); - Call.setParam(s, 1, rotatedOperand); - Call.setParam(s, 2, rotation); + Call.setParam(s, 0, rotatedOperand); + Call.setParam(s, 1, rotation); Call.setResult(s, result); Call.setGuard(s, new OPT_TrueGuardOperand()); Call.setMethod(s, methOp); Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-05-11 17:37:08 UTC (rev 112) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-05-11 17:38:08 UTC (rev 113) @@ -84,6 +84,11 @@ public String asString() { return instruction; } + + @Override + public String toString() { + return asString(); + } /** @see DisassembledInstruction#getSuccessor(int) */ public int getSuccessor(int pc) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-11 17:37:08 UTC (rev 112) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-11 17:38:08 UTC (rev 113) @@ -107,12 +107,7 @@ protected OPT_RegisterOperand getTempInt() { return translator.arm2ir.getTempInt(0); } - - protected OPT_RegisterOperand getTempValidation() { - return translator.arm2ir.getGenerationContext().temps - .makeTempValidation(); - } - + private static class ResolvedOperand_WithoutShifterCarryOut extends ResolvedOperand { @@ -243,7 +238,7 @@ //Current block curBlock.insertOut(block1); translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, getTempValidation(), translator.arm2ir.getCarryFlag(), + INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand .EQUAL(), block1.makeJumpTarget(), new OPT_BranchProfileOperand())); @@ -361,8 +356,7 @@ OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); OPT_BasicBlock block1, block2, block3; - OPT_RegisterOperand validation1 = translator.arm2ir.getTempValidation(9); - OPT_RegisterOperand validation2 = translator.arm2ir.getTempValidation(8); + OPT_RegisterOperand validation = translator.arm2ir.getTempValidation(0); OPT_RegisterOperand tmp = translator.arm2ir.getTempInt(9); @@ -385,13 +379,13 @@ //current block curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation2, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 2 translator.arm2ir.setCurrentBlock(block2); @@ -419,13 +413,13 @@ //current block curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation2, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 2 translator.arm2ir.setCurrentBlock(block2); @@ -455,13 +449,13 @@ //current block curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); block1.insertOut(block2); block1.insertOut(block3); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation2, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 2 translator.arm2ir.setCurrentBlock(block2); @@ -485,7 +479,7 @@ //current block curBlock.insertOut(block1); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); //block 1 translator.arm2ir.setCurrentBlock(block1); @@ -513,7 +507,7 @@ //Current block curBlock.insertOut(block1); translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, getTempValidation(), translator.arm2ir.getCarryFlag(), + INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand .EQUAL(), block1.makeJumpTarget(), new OPT_BranchProfileOperand())); @@ -537,22 +531,6 @@ return resultRegister; } } - - - - - - - - - - - - - - - - } /** All ARM interpreter instructions implement this interface. */ @@ -591,11 +569,21 @@ public void translate() { //conditionals are implemented easily: if the condition does not hold, then just //jump to the block following the conditional instruction - OPT_BasicBlock nextInstruction = arm2ir.getNextBlock(); + OPT_BasicBlock nextInstruction; + OPT_BasicBlock condBlock; + + if (getSuccessor(pc) != -1) { + nextInstruction = arm2ir.getNextBlock(); + condBlock = arm2ir.createBlockAfterCurrent(); + condBlock.insertOut(nextInstruction); + } + else { + nextInstruction = arm2ir.createBlockAfterCurrent(); + condBlock = arm2ir.createBlockAfterCurrent(); + } + arm2ir.getCurrentBlock().insertOut(nextInstruction); - OPT_BasicBlock currentInstruction = arm2ir.createBlockAfterCurrent(); - switch (conditionalInstruction.getCondition()) { case AL: throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator."); @@ -675,7 +663,13 @@ throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); } - arm2ir.setCurrentBlock(currentInstruction); + arm2ir.setCurrentBlock(condBlock); + conditionalInstruction.translate(); + + if (getSuccessor(pc) == -1) { + arm2ir.setCurrentBlock(nextInstruction); + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc+4)); + } } private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand operand, OPT_ConditionOperand condition) { @@ -685,31 +679,31 @@ private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand lhs, OPT_ConditionOperand condition, OPT_Operand rhs) { condition = condition.flipCode(); - arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(9), lhs, rhs, condition, nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), lhs, rhs, condition, nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_HI(OPT_BasicBlock nextInstruction) { //return regs.isCarrySet() && !regs.isZeroSet(); OPT_Operand carry = arm2ir.getCarryFlag(); OPT_Operand zero = arm2ir.getCarryFlag(); - OPT_RegisterOperand result = arm2ir.getTempValidation(9); + OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(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.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_LS(OPT_BasicBlock nextInstruction) { //return !regs.isCarrySet() || regs.isZeroSet(); OPT_Operand carry = arm2ir.getCarryFlag(); OPT_Operand zero = arm2ir.getCarryFlag(); - OPT_RegisterOperand result = arm2ir.getTempValidation(9); + OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(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.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_GT(OPT_BasicBlock nextInstruction) { @@ -717,12 +711,12 @@ OPT_Operand negative = arm2ir.getNegativeFlag(); OPT_Operand overflow = arm2ir.getOverflowFlag(); OPT_Operand zero = arm2ir.getCarryFlag(); - OPT_RegisterOperand result = arm2ir.getTempValidation(9); + OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(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.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } private void translateCondition_LE(OPT_BasicBlock nextInstruction) { @@ -730,12 +724,12 @@ OPT_Operand negative = arm2ir.getNegativeFlag(); OPT_Operand overflow = arm2ir.getOverflowFlag(); OPT_Operand zero = arm2ir.getCarryFlag(); - OPT_RegisterOperand result = arm2ir.getTempValidation(9); + OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean(); arm2ir.appendInstructionToCurrentBlock(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.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); } @@ -774,7 +768,8 @@ /** Returns the register into which the result of a data processing operation shall be stored. */ protected OPT_RegisterOperand getResultRegister() { - return arm2ir.getRegister(Rd); + //return arm2ir.getRegister(Rd); + return arm2ir.getGenerationContext().temps.makeTempInt(); } public abstract void translate(); @@ -792,6 +787,8 @@ } } + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + if (Rd == 15) arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } @@ -836,6 +833,8 @@ } } + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + if (Rd == 15) arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } @@ -908,6 +907,8 @@ } } + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(Rd), result) ); + if (Rd == 15) arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } @@ -1439,20 +1440,18 @@ //nextAddress += 4; arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); - OPT_RegisterOperand target = arm2ir.getRegister(ARM_Registers.PC); - ps.memory.translateLoad32(nextAddress, target); + OPT_RegisterOperand regPC = arm2ir.getRegister(ARM_Registers.PC); + ps.memory.translateLoad32(nextAddress, regPC); - //TODO: Use the first bit of (target) before the following instruction to determine if we should be in thumb mode... - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, target, target, new OPT_IntConstantOperand(0xFFFFFFFE))); - - throw new RuntimeException("Not yet implemented"); - /* if (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. //Therefore, sync both first by switching the operating mode to user (which is what our register layout //is anyway). + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + /* regs.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); regs.restoreSPSR2CPSR(); @@ -1463,13 +1462,37 @@ regs.set(ARM_Registers.PC, newpc); //there is no write-back for this instruction. - return; + return;*/ } else { - //shall we switch to thumb mode - regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); - regs.setThumbMode((newpc & 0x1) != 0); - }*/ + //first translate the register write back + translateWriteback(startAddress, nextAddress); + + //shall we switch to thumb mode? + /*OPT_BasicBlock finishInstruction = arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock switchToARMBlock = arm2ir.createBlockAfterCurrent(); + OPT_BasicBlock switchToThumbBlock = arm2ir.createBlockAfterCurrentNotInCFG(); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), regPC, new OPT_IntConstantOperand(1), OPT_ConditionOperand.BIT_TEST(), switchToThumbBlock.makeJumpTarget(), OPT_BranchProfileOperand.never())); + arm2ir.getCurrentBlock().insertOut(switchToThumbBlock); + + //Yes, switch to thumb mode + arm2ir.setCurrentBlock(switchToThumbBlock); + switchToThumbBlock.insertOut(finishInstruction); + OPT_Instruction call_setThumbMode = createCallToRegisters("setThumbMode", "(Z)V", 1); + Call.setParam(call_setThumbMode, 1, new OPT_IntConstantOperand(1)); + arm2ir.appendInstructionToCurrentBlock(call_setThumbMode); + + //No, don't switch to thumb mode + arm2ir.setCurrentBlock(switchToARMBlock); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, regPC, regPC, new OPT_IntConstantOperand(0xFFFFFFFE))); + OPT_Instruction call_setArmMode = createCallToRegisters("setThumbMode", "(Z)V", 1); + Call.setParam(call_setArmMode, 1, new OPT_IntConstantOperand(0)); + arm2ir.appendInstructionToCurrentBlock(call_setArmMode); + + arm2ir.setCurrentBlock(finishInstruction);*/ + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, regPC); + } + return; } } else { int nextReg = 0; @@ -1492,8 +1515,13 @@ //TODO: Implement.... ps.registers.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); ps.registers.switchOperatingMode(previousMode); + throw new RuntimeException("Not yet implemented"); } + translateWriteback(startAddress, nextAddress); + } + + private void translateWriteback(OPT_RegisterOperand startAddress, OPT_RegisterOperand nextAddress) { if (writeBack) { OPT_RegisterOperand writeBackTarget = arm2ir.getRegister(baseRegister); @@ -1520,6 +1548,7 @@ } } } + public int getSuccessor(int pc) { //if we're loading values into the PC, then we can't tell where this instruction will be going @@ -1838,6 +1867,7 @@ public void translate() { arm2ir.plantSystemCall(lazy, pc); + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, arm2ir.getRegister(ARM_Registers.PC)); } public int getSuccessor(int pc) { @@ -1994,6 +2024,11 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, writeBackTarget, address, resolvedOffset)); } } + + if (isLoad && Rd == ARM_Registers.PC) { + //we are actually loading to the program counter here + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, arm2ir.getRegister(Rd)); + } } 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-11 17:37:08 UTC (rev 112) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-11 17:38:08 UTC (rev 113) @@ -3,6 +3,7 @@ import java.io.IOException; import org.binarytranslator.DBT_Options; import org.binarytranslator.arch.arm.decoder.ARM2IR; +import org.binarytranslator.arch.arm.decoder.ARM_Disassembler; 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; @@ -95,7 +96,7 @@ */ @Uninterruptible public String disassembleInstruction(int pc) { - return "TODO"; + return ARM_Disassembler.disassemble(pc, this).asString(); } /** Modified: src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-05-11 17:37:08 UTC (rev 112) +++ src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java 2007-05-11 17:38:08 UTC (rev 113) @@ -433,4 +433,29 @@ public boolean isNegativeSet() { return flagNegative; } + + /** Returns a string representation of the values in the ARM registers. */ + @Override + public String toString() { + + StringBuilder result = new StringBuilder(); + for (int i = 0; i < regs.length; i++) { + result.append('r'); + result.append(i); + result.append(": x"); + result.append(Integer.toHexString(regs[i])); + result.append(", "); + } + + result.append("C:"); + result.append(flagCarry ? '1' : '0'); + result.append(", Z:"); + result.append(flagZero ? '1' : '0'); + result.append(", N:"); + result.append(flagNegative ? '1' : '0'); + result.append(", O:"); + result.append(flagOverflow ? '1' : '0'); + + return result.toString(); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-11 17:37:08
|
Revision: 112 http://svn.sourceforge.net/pearcolator/?rev=112&view=rev Author: michael_baer Date: 2007-05-11 10:37:08 -0700 (Fri, 11 May 2007) Log Message: ----------- - Disabled printing of stack trace before dynamic bridging Modified Paths: -------------- src/org/binarytranslator/vmInterface/DynamicCodeRunner.java Modified: src/org/binarytranslator/vmInterface/DynamicCodeRunner.java =================================================================== --- src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-05-10 15:21:58 UTC (rev 111) +++ src/org/binarytranslator/vmInterface/DynamicCodeRunner.java 2007-05-11 17:37:08 UTC (rev 112) @@ -41,7 +41,7 @@ // Useful when debugging in GDB: if (DBT_Options.debugRuntime) { VM.sysWriteln(ps.toString()); - ps.dumpStack(20); + //ps.dumpStack(20); VM.sysWrite("Running PC="); VM.sysWriteHex(ps.getCurrentInstructionAddress()); VM.sysWrite(" "); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-10 15:21:58
|
Revision: 111 http://svn.sourceforge.net/pearcolator/?rev=111&view=rev Author: michael_baer Date: 2007-05-10 08:21:58 -0700 (Thu, 10 May 2007) Log Message: ----------- - fixed various problems in ARM's DBT part - fixed an interpreter bug, where LSL and ROR by 32 would produce a wrong result Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.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/arm/os/process/image/ARM_ImageProcessSpace.java src/org/binarytranslator/generic/decoder/DecoderUtils.java src/org/binarytranslator/generic/memory/AutoMappingMemory.java src/org/binarytranslator/generic/memory/DebugMemory.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-09 17:28:51 UTC (rev 110) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-10 15:21:58 UTC (rev 111) @@ -20,10 +20,22 @@ public class ARM2IR extends DecoderUtils implements OPT_HIRGenerator { /** Mapping of ARM registers to HIR registers */ - protected OPT_Register regMap[] = new OPT_Register[16]; + private OPT_Register regMap[] = new OPT_Register[16]; + /** The ARM carry flag. */ + private OPT_Register carryFlag; + + /** The ARM zero flag. */ + private OPT_Register zeroFlag; + + /** The ARM negative flag. */ + private OPT_Register negativeFlag; + + /** The ARM overflow flag. */ + private OPT_Register overflowFlag; + /** Set to true for each register that is in use during the current trace */ - protected boolean regUsed[] = new boolean[16]; + private boolean regUsed[] = new boolean[16]; /** Type reference to the ARM process space */ private static final VM_TypeReference psTref; @@ -38,15 +50,29 @@ private static final VM_FieldReference registers_regs_Fref; /** A type reference to the ARM registers array within the ARM_Registers class */ - private static final VM_TypeReference registers_regs_Tref; + private static final VM_TypeReference registers_regs_Tref; + /** A field reference to the carry flag within the ARM registers. */ + private static final VM_FieldReference registers_carryFlag_Fref; + + /** A field reference to the zero flag within the ARM registers. */ + private static final VM_FieldReference registers_zeroFlag_Fref; + + /** A field reference to the negative flag within the ARM registers. */ + private static final VM_FieldReference registers_negativeFlag_Fref; + + /** A field reference to the overflow flag within the ARM registers. */ + private static final VM_FieldReference registers_overflowFlag_Fref; + /** A register holding a reference to ps.registers */ private OPT_Register ps_registers; /** A register holding a reference to ps.registers.regs */ private OPT_Register ps_registers_regs; - + /** The class performing the actual translation of the bytecode. */ + private final ARM_Translator translator; + static { psTref = VM_TypeReference.findOrCreate(ARM_ProcessSpace.class); @@ -73,11 +99,40 @@ registers_regs_Tref = registers_regs_Fref.getFieldContentsType(); if (DBT.VerifyAssertions) DBT._assert(registers_regs_Tref != null); + + registers_carryFlag_Fref = VM_MemberReference + .findOrCreate(registersTref, + VM_Atom.findOrCreateAsciiAtom("flagCarry"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + + if (DBT.VerifyAssertions) DBT._assert(registers_carryFlag_Fref != null); + + registers_zeroFlag_Fref = VM_MemberReference + .findOrCreate(registersTref, + VM_Atom.findOrCreateAsciiAtom("flagZero"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + + if (DBT.VerifyAssertions) DBT._assert(registers_zeroFlag_Fref != null); + + registers_negativeFlag_Fref = VM_MemberReference + .findOrCreate(registersTref, + VM_Atom.findOrCreateAsciiAtom("flagNegative"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + + if (DBT.VerifyAssertions) DBT._assert(registers_negativeFlag_Fref != null); + + registers_overflowFlag_Fref = VM_MemberReference + .findOrCreate(registersTref, + VM_Atom.findOrCreateAsciiAtom("flagOverflow"), + VM_Atom.findOrCreateAsciiAtom("Z")).asFieldReference(); + + if (DBT.VerifyAssertions) DBT._assert(registers_overflowFlag_Fref != null); } public ARM2IR(OPT_GenerationContext context) { super(context); + translator = new ARM_Translator((ARM_ProcessSpace)ps, this); } @Override @@ -132,7 +187,7 @@ public OPT_RegisterOperand getArmRegistersReference() { OPT_RegisterOperand ps_registersOp; - if (ps_registers != null) { + if (ps_registers == null) { ps_registersOp = gc.temps.makeTemp(registersTref); ps_registers = ps_registersOp.register; appendInstructionToCurrentBlock(GetField.create(GETFIELD, ps_registersOp, @@ -154,14 +209,49 @@ //first resolve the current lazy state (i.e. calculate the values of registers that are not yet resolved) resolveLaziness(lazyState); + } + + private void spillAllFlags() { + + OPT_RegisterOperand ps_registersOp = getArmRegistersReference(); - //TODO: Implement - throw new RuntimeException("Not yet implemented"); + //store the carry flag + OPT_RegisterOperand flag = new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(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); + appendInstructionToCurrentBlock(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); + appendInstructionToCurrentBlock(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); + appendInstructionToCurrentBlock(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() { - //TODO: Implement - throw new RuntimeException("Not yet implemented"); + + //get an operand that contains a reference to the current ps.registers field. + OPT_RegisterOperand ps_registersOp = getArmRegistersReference(); + + //get the carry flag + OPT_RegisterOperand flag = new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_carryFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_carryFlag_Fref), new OPT_TrueGuardOperand()) ); + + //get the negative flag + flag = new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_negativeFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_negativeFlag_Fref), new OPT_TrueGuardOperand()) ); + + //get the zero flag + flag = new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_zeroFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_zeroFlag_Fref), new OPT_TrueGuardOperand()) ); + + //get the overflow flag + flag = new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean); + appendInstructionToCurrentBlock(GetField.create(GETFIELD, flag, ps_registersOp.copyRO(), new OPT_AddressConstantOperand(registers_overflowFlag_Fref.peekResolvedField().getOffset()), new OPT_LocationOperand(registers_overflowFlag_Fref), new OPT_TrueGuardOperand()) ); } @Override @@ -199,6 +289,9 @@ new OPT_LocationOperand(VM_TypeReference.Int), new OPT_TrueGuardOperand())); } + + //fill all flags from the process space + fillAllFlags(); } public OPT_RegisterOperand getRegister(int r) { @@ -207,26 +300,21 @@ } public OPT_RegisterOperand getCarryFlag() { - //TODO: Implement - throw new RuntimeException("Not yet implemented"); + return new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean); } public OPT_RegisterOperand getZeroFlag() { - //TODO: Implement - throw new RuntimeException("Not yet implemented"); + return new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean); } public OPT_RegisterOperand getNegativeFlag() { - //TODO: Implement - throw new RuntimeException("Not yet implemented"); + return new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean); } public OPT_RegisterOperand getOverflowFlag() { - //TODO: Implement - throw new RuntimeException("Not yet implemented"); + return new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean); } - @Override protected OPT_Register[] getUnusedRegisters() { @@ -268,13 +356,17 @@ new OPT_TrueGuardOperand())); } } + + //spill all flags to the process space + spillAllFlags(); } @Override protected int translateInstruction(Laziness lazy, int pc) { - return 0xEBADC0DE; - //ARM_InstructionDecoder.translateInstruction(this, - // (ARM_ProcessSpace) ps, (ARM_Laziness) lazy, pc); + System.out.println("Translating address: 0x" + Integer.toHexString(pc)); + System.out.println("Instruction: " + ARM_Disassembler.disassemble(pc, ps)); + + return translator.translateInstruction(pc, (ARM_Laziness)lazy); } /** Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-09 17:28:51 UTC (rev 110) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-10 15:21:58 UTC (rev 111) @@ -272,7 +272,7 @@ } if (shiftAmount == 32) { - shifterCarryOut = Utils.getBit(value, 31); + shifterCarryOut = (value & 0x1) != 0; return 0; } @@ -311,7 +311,7 @@ return value; } else { - shifterCarryOut = Utils.getBit(value, shiftAmount & 0x1F); + shifterCarryOut = Utils.getBit(value, (shiftAmount-1) & 0x1F); return Integer.rotateRight(value, shiftAmount); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-09 17:28:51 UTC (rev 110) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-10 15:21:58 UTC (rev 111) @@ -30,12 +30,29 @@ /** A "quick" pointer to the ARM registers within the process space*/ protected final ARM_Registers regs = null; + + private final ARM_InstructionDecoder.ARM_InstructionFactory<ARM_Instruction> translatorFactory = new TranslatorFactory(); public ARM_Translator(ARM_ProcessSpace ps, ARM2IR arm2ir) { this.ps = ps; this.arm2ir = arm2ir; } + public int translateInstruction(int pc, ARM_Laziness lazy) { + this.pc = pc; + this.lazy = lazy; + + int instruction = ps.memory.loadInstruction32(pc); + ARM_Instruction instr = ARM_InstructionDecoder.decode(instruction, translatorFactory); + + if (instr.getCondition() != Condition.AL) { + instr = new ConditionalDecorator(instr); + } + + instr.translate(); + return instr.getSuccessor(pc); + } + private OPT_Instruction createCallToRegisters(String methodName, String signature, int numParameters) { VM_TypeReference RegistersType = VM_TypeReference @@ -69,9 +86,11 @@ protected ARM_Translator translator; - public static ResolvedOperand resolveAndStoreShifterCarryOutToCarry( + public static OPT_Operand resolveAndStoreShifterCarryOutToCarry( ARM_Translator translator, OperandWrapper operand) { - throw new RuntimeException("Not yet implemented"); + + ResolvedOperand result = new ResolvedOperand_WithShifterCarryOut(translator, operand); + return result.getValue(); } public static OPT_Operand resolve(ARM_Translator translator, @@ -167,96 +186,36 @@ .getShiftingRegister()); } - OPT_BasicBlock currentBlock = translator.arm2ir.getCurrentBlock(); - OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); - - OPT_BasicBlock ifBlock; - OPT_BasicBlock elseBlock; - OPT_RegisterOperand resultRegister = getTempInt(); switch (operand.getShiftType()) { case ASR: /* - * if (shiftAmout >= 32) { value = shiftedOperand >> 31; shiftedOperand >> 1; } - * else - * value = shiftedOperand >> shiftAmount; + * shiftedOperand >> shiftAmount; */ - ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - elseBlock = translator.arm2ir.createBlockAfterCurrent(); - ifBlock.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, getTempValidation(), shiftAmount, - new OPT_IntConstantOperand(32), OPT_ConditionOperand - .GREATER_EQUAL(), ifBlock.makeJumpTarget(), - OPT_BranchProfileOperand.unlikely())); - currentBlock.insertOut(ifBlock); - - //shift - translator.arm2ir.setCurrentBlock(ifBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHR, resultRegister, shiftedOperand, - new OPT_IntConstantOperand(31))); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHR, resultRegister, shiftedOperand, - new OPT_IntConstantOperand(1))); - - translator.arm2ir.setCurrentBlock(elseBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_SHR, resultRegister, shiftedOperand, shiftAmount)); - break; + return resultRegister; case LSL: /* - * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand << - * shiftAmount; + * value = shiftedOperand << shiftAmount; */ - ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - elseBlock = translator.arm2ir.createBlockAfterCurrent(); - ifBlock.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, getTempValidation(), shiftAmount, - new OPT_IntConstantOperand(32), OPT_ConditionOperand - .GREATER_EQUAL(), ifBlock.makeJumpTarget(), - OPT_BranchProfileOperand.unlikely())); - currentBlock.insertOut(ifBlock); - - translator.arm2ir.setCurrentBlock(ifBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( - INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); - - translator.arm2ir.setCurrentBlock(elseBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + return resultRegister; - break; - case LSR: /* - * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand >>> - * shiftAmount; + * value = shiftedOperand >>> shiftAmount; + */ - ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - elseBlock = translator.arm2ir.createBlockAfterCurrent(); - ifBlock.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, getTempValidation(), shiftAmount, - new OPT_IntConstantOperand(32), OPT_ConditionOperand - .GREATER_EQUAL(), ifBlock.makeJumpTarget(), - OPT_BranchProfileOperand.unlikely())); - currentBlock.insertOut(ifBlock); - - translator.arm2ir.setCurrentBlock(ifBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( - INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); - - translator.arm2ir.setCurrentBlock(elseBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_USHR, resultRegister, shiftedOperand, shiftAmount)); - break; + return resultRegister; case ROR: /* @@ -267,8 +226,8 @@ case RRX: /* - * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; - * else return resultRegister >>> 1; + * value = resultRegister >>> 1; + * if (regs.isCarrySet()) value |= 0x80000000; */ // resultRegister = resultRegister >>> 1 @@ -276,28 +235,34 @@ INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); //conditionally, set resultRegister = resultRegister | 0x80000000; - ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - ifBlock.insertOut(nextBlock); + OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); + + OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); + OPT_BasicBlock block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + //Current block + curBlock.insertOut(block1); translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( INT_IFCMP, getTempValidation(), translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand - .EQUAL(), ifBlock.makeJumpTarget(), - OPT_BranchProfileOperand.unlikely())); - currentBlock.insertOut(ifBlock); + .EQUAL(), block1.makeJumpTarget(), + new OPT_BranchProfileOperand())); + + //Block 1 + translator.arm2ir.setCurrentBlock(block1); + block1.insertOut(nextBlock); - translator.arm2ir.setCurrentBlock(ifBlock); translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); + + translator.arm2ir.setCurrentBlock(nextBlock); + translator.arm2ir.setNextBlock(translator.arm2ir.createBlockAfterCurrent()); + return resultRegister; - break; - default: throw new RuntimeException("Unexpected shift type: " + operand.getShiftType()); } - - translator.arm2ir.setCurrentBlock(nextBlock); - return resultRegister; } } @@ -356,21 +321,9 @@ } } - /** - * Translates a bit test, where bit <code>shifterResultBit</code> is tested within <code>value</code> and the result - * is put into the carry flag If <code>shifterResultBit</code> is less than 0, the carry is not changed. - * - */ - private void translateShifterCarryOut(OPT_Operand value, OPT_Operand shifterResultBit) { - - OPT_RegisterOperand carryFlag = translator.arm2ir.getCarryFlag(); - - - OPT_RegisterOperand tmp = getTempInt(); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, - tmp, shifterResultBit, new OPT_IntConstantOperand(1))); - translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, carryFlag, value, tmp.copyRO(), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand())); + /** Returns the register that receives the shifte carry out*/ + private OPT_RegisterOperand getShifterCarryOutTarget() { + return translator.arm2ir.getCarryFlag(); } /** @@ -402,140 +355,185 @@ .getShiftingRegister()); } - OPT_BasicBlock currentBlock = translator.arm2ir.getCurrentBlock(); + OPT_RegisterOperand resultRegister = getTempInt(); + OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); + OPT_BasicBlock curBlock = translator.arm2ir.getCurrentBlock(); + OPT_BasicBlock block1, block2, block3; + + OPT_RegisterOperand validation1 = translator.arm2ir.getTempValidation(9); + OPT_RegisterOperand validation2 = translator.arm2ir.getTempValidation(8); + + OPT_RegisterOperand tmp = translator.arm2ir.getTempInt(9); - OPT_BasicBlock ifBlock; - OPT_BasicBlock elseBlock; - - OPT_RegisterOperand resultRegister = getTempInt(); - switch (operand.getShiftType()) { case ASR: /* - * if (shiftAmout >= 32) { value = shiftedOperand >> 31; shiftedOperand >> 1; } - * else - * value = shiftedOperand >> shiftAmount; + * shiftedOperand >> shiftAmount; + * + * if (shiftAmount != 0) { + * shiftAmount = MIN(shiftAmount, 32); + * carry = shiftedOperand[shiftAmount] + * } */ - ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - ifBlock.insertOut(nextBlock); - elseBlock = translator.arm2ir.createBlockAfterCurrent(); - - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, getTempValidation(), shiftAmount, - new OPT_IntConstantOperand(32), OPT_ConditionOperand - .GREATER_EQUAL(), ifBlock.makeJumpTarget(), - new OPT_BranchProfileOperand())); - currentBlock.insertOut(ifBlock); - - //shift twice to simulate arithmetic shift-right by 32 - //circumvents java doing (shiftAmount MOD 32). - translator.arm2ir.setCurrentBlock(ifBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHR, resultRegister, shiftedOperand, - new OPT_IntConstantOperand(31))); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( - INT_SHR, resultRegister, shiftedOperand, - new OPT_IntConstantOperand(1))); - - translator.arm2ir.setCurrentBlock(elseBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_SHR, resultRegister, shiftedOperand, shiftAmount)); - translateShifterCarryOut(resultRegister, shiftAmount); + + block3 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + //current block + curBlock.insertOut(block1); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + + //block 1 + translator.arm2ir.setCurrentBlock(block1); + block1.insertOut(block2); + block1.insertOut(block3); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation2, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + + //block 2 + translator.arm2ir.setCurrentBlock(block2); + block2.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, shiftAmount, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + + //block 3 + translator.arm2ir.setCurrentBlock(block3); + block3.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, new OPT_IntConstantOperand(32), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + break; case LSL: /* - * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand << - * shiftAmount; + * value = shiftedOperand << shiftAmount; */ - ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - elseBlock = translator.arm2ir.createBlockAfterCurrent(); - ifBlock.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, getTempValidation(), shiftAmount, - new OPT_IntConstantOperand(32), OPT_ConditionOperand - .GREATER_EQUAL(), ifBlock.makeJumpTarget(), - OPT_BranchProfileOperand.unlikely())); - currentBlock.insertOut(ifBlock); - - translator.arm2ir.setCurrentBlock(ifBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( - INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); - - translator.arm2ir.setCurrentBlock(elseBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + + block3 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + //current block + curBlock.insertOut(block1); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + + //block 1 + translator.arm2ir.setCurrentBlock(block1); + block1.insertOut(block2); + block1.insertOut(block3); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation2, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + + //block 2 + translator.arm2ir.setCurrentBlock(block2); + block2.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock( Binary.create(INT_SUB, tmp, new OPT_IntConstantOperand(32), shiftAmount) ); + translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, tmp, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + + //block 3 + translator.arm2ir.setCurrentBlock(block3); + block3.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock( Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); break; case LSR: /* - * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand >>> - * shiftAmount; + * value = shiftedOperand >>> shiftAmount; + */ - ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - elseBlock = translator.arm2ir.createBlockAfterCurrent(); - ifBlock.insertOut(nextBlock); - translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( - INT_IFCMP, getTempValidation(), shiftAmount, - new OPT_IntConstantOperand(32), OPT_ConditionOperand - .GREATER_EQUAL(), ifBlock.makeJumpTarget(), - OPT_BranchProfileOperand.unlikely())); - currentBlock.insertOut(ifBlock); - - translator.arm2ir.setCurrentBlock(ifBlock); - translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( - INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); - - translator.arm2ir.setCurrentBlock(elseBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + block3 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block2 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + //current block + curBlock.insertOut(block1); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + + //block 1 + translator.arm2ir.setCurrentBlock(block1); + block1.insertOut(block2); + block1.insertOut(block3); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation2, shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand.GREATER(), block3.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + + //block 2 + translator.arm2ir.setCurrentBlock(block2); + block2.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, shiftAmount, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + + //block 3 + translator.arm2ir.setCurrentBlock(block3); + block3.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock( Move.create(INT_MOVE, getShifterCarryOutTarget(), new OPT_IntConstantOperand(0)) ); + break; case ROR: /* * return Integer.rotateRight(value, shiftAmount); */ - translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, - shiftAmount); - return resultRegister; + translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); + + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + //current block + curBlock.insertOut(block1); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, validation1, shiftAmount, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), nextBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); + + //block 1 + translator.arm2ir.setCurrentBlock(block1); + block1.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock( Binary.create(INT_SUB, tmp, shiftAmount, new OPT_IntConstantOperand(1)) ); + translator.arm2ir.appendInstructionToCurrentBlock( Binary.create(INT_AND, tmp, shiftAmount, new OPT_IntConstantOperand(0x1F)) ); + translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, tmp, OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); + + break; case RRX: /* - * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; - * else return resultRegister >>> 1; + * value = resultRegister >>> 1; + * if (regs.isCarrySet()) value |= 0x80000000; */ // resultRegister = resultRegister >>> 1 translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, getShifterCarryOutTarget(), shiftedOperand, new OPT_IntConstantOperand(1), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand()) ); - ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); - ifBlock.insertOut(nextBlock); + //conditionally, set resultRegister = resultRegister | 0x80000000; + block1 = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + + //Current block + curBlock.insertOut(block1); translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( INT_IFCMP, getTempValidation(), translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand - .EQUAL(), ifBlock.makeJumpTarget(), - OPT_BranchProfileOperand.unlikely())); - currentBlock.insertOut(ifBlock); + .EQUAL(), block1.makeJumpTarget(), + new OPT_BranchProfileOperand())); + + //Block 1 + translator.arm2ir.setCurrentBlock(block1); + block1.insertOut(nextBlock); - translator.arm2ir.setCurrentBlock(ifBlock); translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( - INT_AND_ACC, resultRegister, new OPT_IntConstantOperand( - 0x80000000))); - + INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); + break; default: throw new RuntimeException("Unexpected shift type: " + operand.getShiftType()); } - + translator.arm2ir.setCurrentBlock(nextBlock); + translator.arm2ir.setNextBlock( translator.arm2ir.createBlockAfterCurrent() ); return resultRegister; } } @@ -564,6 +562,9 @@ /** performs the actual translation.*/ void translate(); + + /** Return the instruction following this one or -1, if that is not yet known. */ + int getSuccessor(int pc); } /** All ARM instructions that are supposed to be executed conditionally @@ -579,6 +580,14 @@ conditionalInstruction = i; } + 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; + else + return -1; + } + public void translate() { //conditionals are implemented easily: if the condition does not hold, then just //jump to the block following the conditional instruction @@ -880,8 +889,7 @@ protected OPT_Operand resolveOperand2() { if (updateConditionCodes) { - ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveAndStoreShifterCarryOutToCarry(ARM_Translator.this, operand2); - return resolvedOperand2.getValue(); + return ResolvedOperand.resolveAndStoreShifterCarryOutToCarry(ARM_Translator.this, operand2); } else { return super.resolveOperand2(); @@ -2032,9 +2040,9 @@ } - /** This class will create instances of the different interpreter instructions. It is being "controlled" by + /** This class will create instances of the different translated instructions. It is being "controlled" by * the ARM_InstructionDecoder, which uses an abstract factory pattern to decode an instruction. */ - private class InterpreterFactory implements + private class TranslatorFactory implements ARM_InstructionFactory<ARM_Instruction> { public ARM_Instruction createDataProcessing(int instr) { Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-09 17:28:51 UTC (rev 110) +++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-05-10 15:21:58 UTC (rev 111) @@ -2,6 +2,7 @@ import java.io.IOException; import org.binarytranslator.DBT_Options; +import org.binarytranslator.arch.arm.decoder.ARM2IR; 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; @@ -47,8 +48,7 @@ * @return a HIR generator */ public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) { - System.out.println("Executing instr: " + memory.load32(0)); - throw new RuntimeException("Not yet implemented"); + return new ARM2IR(context); } /** Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-05-09 17:28:51 UTC (rev 110) +++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-05-10 15:21:58 UTC (rev 111) @@ -9,8 +9,6 @@ import org.binarytranslator.generic.execution.GdbController.GdbTarget; import org.binarytranslator.generic.memory.AutoMappingMemory; import org.binarytranslator.generic.os.loader.Loader; -import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext; -import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator; public class ARM_ImageProcessSpace extends ARM_ProcessSpace { @@ -22,12 +20,6 @@ //make sure that pages of memory are automatically mapped in as they are requested. memory = new AutoMappingMemory(memory); } - - @Override - public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) - { - throw new UnsupportedOperationException("Not yet implemented."); - } @Override public void doSysCall() { @@ -37,9 +29,7 @@ ARM_Instructions.Instruction instr = ARM_InstructionDecoder.decode(instruction); if (DBT.VerifyAssertions) { - if (!(instr instanceof ARM_Instructions.SoftwareInterrupt)) { - throw new Error("The current instruction is not a valid system call."); - } + DBT._assert(instr instanceof ARM_Instructions.SoftwareInterrupt); } //Thumb system calls start from 0, while ARM calls start from 0x900000. Modified: src/org/binarytranslator/generic/decoder/DecoderUtils.java =================================================================== --- src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-05-09 17:28:51 UTC (rev 110) +++ src/org/binarytranslator/generic/decoder/DecoderUtils.java 2007-05-10 15:21:58 UTC (rev 111) @@ -447,6 +447,7 @@ * @return the next block */ public OPT_BasicBlock getNextBlock() { + return nextBlock; } Modified: src/org/binarytranslator/generic/memory/AutoMappingMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-05-09 17:28:51 UTC (rev 110) +++ src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-05-10 15:21:58 UTC (rev 111) @@ -2,8 +2,6 @@ import java.io.RandomAccessFile; -import org.binarytranslator.vmInterface.TranslationHelper; -import org.jikesrvm.classloader.VM_MethodReference; /** * A memory implementation that will automatically map pages into memory, as soon @@ -31,10 +29,6 @@ return mem.equals(arg0); } - public VM_MethodReference getMethodRef(int callAddress) { - return mem.getMethodRef(callAddress); - } - public int getPageSize() { return mem.getPageSize(); } @@ -43,10 +37,6 @@ return mem.hashCode(); } - public void initTranslate(TranslationHelper helper) { - mem.initTranslate(helper); - } - public boolean isMapped(int addr) { return mem.isMapped(addr); } Modified: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java 2007-05-09 17:28:51 UTC (rev 110) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-05-10 15:21:58 UTC (rev 111) @@ -470,7 +470,7 @@ * @return the result */ public int load32(int addr) { - return (loadSigned8(addr + 3) << 24) | (loadUnsigned8(addr + 2) << 16) + return (loadUnsigned8(addr + 3) << 24) | (loadUnsigned8(addr + 2) << 16) | (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-09 17:28:50
|
Revision: 110 http://svn.sourceforge.net/pearcolator/?rev=110&view=rev Author: michael_baer Date: 2007-05-09 10:28:51 -0700 (Wed, 09 May 2007) Log Message: ----------- Derived AutoMappingMemory decorator from CallBasedMemory to enable this decorator in non-interpreted code. Modified Paths: -------------- src/org/binarytranslator/generic/memory/AutoMappingMemory.java Modified: src/org/binarytranslator/generic/memory/AutoMappingMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-05-09 14:15:36 UTC (rev 109) +++ src/org/binarytranslator/generic/memory/AutoMappingMemory.java 2007-05-09 17:28:51 UTC (rev 110) @@ -4,8 +4,6 @@ import org.binarytranslator.vmInterface.TranslationHelper; import org.jikesrvm.classloader.VM_MethodReference; -import org.jikesrvm.compilers.opt.ir.OPT_Operand; -import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; /** * A memory implementation that will automatically map pages into memory, as soon @@ -19,11 +17,13 @@ * @author Michael Baer * */ -public class AutoMappingMemory extends Memory { +public class AutoMappingMemory extends CallBasedMemory { private Memory mem; public AutoMappingMemory(Memory memoryImplementation) { + super(AutoMappingMemory.class); + this.mem = memoryImplementation; } @@ -167,46 +167,6 @@ return mem.toString(); } - public void translateLoad32(OPT_Operand addr, OPT_RegisterOperand dest) { - //mem.translateLoad32(addr, dest); - throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); - } - - public void translateLoadSigned16(OPT_Operand addr, OPT_RegisterOperand dest) { - //mem.translateLoadSigned16(addr, dest); - throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); - } - - public void translateLoadSigned8(OPT_Operand addr, OPT_RegisterOperand dest) { - //mem.translateLoadSigned8(addr, dest); - throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); - } - - public void translateLoadUnsigned16(OPT_Operand addr, OPT_RegisterOperand dest) { - //mem.translateLoadUnsigned16(addr, dest); - throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); - } - - public void translateLoadUnsigned8(OPT_Operand addr, OPT_RegisterOperand dest) { - //mem.translateLoadUnsigned8(addr, dest); - throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); - } - - public void translateStore16(OPT_Operand addr, OPT_Operand src) { - //mem.translateStore16(addr, src); - throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); - } - - public void translateStore32(OPT_Operand addr, OPT_Operand src) { - //mem.translateStore32(addr, src); - throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); - } - - public void translateStore8(OPT_Operand addr, OPT_Operand src) { - //mem.translateStore8(addr, src); - throw new RuntimeException("Automatic mapping of pages during binary translation is currently not provided."); - } - public int truncateToNextPage(int addr) { return mem.truncateToNextPage(addr); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-09 14:16:04
|
Revision: 109 http://svn.sourceforge.net/pearcolator/?rev=109&view=rev Author: michael_baer Date: 2007-05-09 07:15:36 -0700 (Wed, 09 May 2007) Log Message: ----------- Changes to enable building with the latest JRVM Modified Paths: -------------- ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java ext/org/jikesrvm/compilers/opt/OPT_ConvertToLowLevelIR.java ext/org/jikesrvm/compilers/opt/ir/OPT_BC2IR.java Modified: ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java =================================================================== --- ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java 2007-05-09 11:23:16 UTC (rev 108) +++ ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java 2007-05-09 14:15:36 UTC (rev 109) @@ -691,8 +691,15 @@ // Use the // default options and at least pick up the verbose if requested for // base/irc - OPT_Options tmpoptions = (OPT_Options) ((OPT_Options) options) - .clone(); + OPT_Options tmpoptions = null; + + try { + tmpoptions = (OPT_Options) ((OPT_Options) options).clone(); + } + catch (Exception e) { + e.printStackTrace(); + } + tmpoptions.PRELOAD_CLASS = VM_BaselineCompiler.options.PRELOAD_CLASS; tmpoptions.PRELOAD_AS_BOOT = VM_BaselineCompiler.options.PRELOAD_AS_BOOT; if (VM_BaselineCompiler.options.PRINT_METHOD) { Modified: ext/org/jikesrvm/compilers/opt/OPT_ConvertToLowLevelIR.java =================================================================== --- ext/org/jikesrvm/compilers/opt/OPT_ConvertToLowLevelIR.java 2007-05-09 11:23:16 UTC (rev 108) +++ ext/org/jikesrvm/compilers/opt/OPT_ConvertToLowLevelIR.java 2007-05-09 14:15:36 UTC (rev 109) @@ -8,16 +8,145 @@ */ package org.jikesrvm.compilers.opt; -import org.jikesrvm.*; +import org.jikesrvm.VM; +import static org.jikesrvm.VM_Constants.LOG_BYTES_IN_ADDRESS; +import static org.jikesrvm.VM_Constants.LOG_BYTES_IN_INT; +import static org.jikesrvm.VM_Constants.NEEDS_DYNAMIC_LINK; +import static org.jikesrvm.VM_Constants.TIB_IMT_TIB_INDEX; +import static org.jikesrvm.VM_Constants.TIB_ITABLES_TIB_INDEX; +import org.jikesrvm.classloader.VM_Class; +import org.jikesrvm.classloader.VM_Field; +import org.jikesrvm.classloader.VM_InterfaceInvocation; +import org.jikesrvm.classloader.VM_InterfaceMethodSignature; +import org.jikesrvm.classloader.VM_Method; +import org.jikesrvm.classloader.VM_Type; +import org.jikesrvm.classloader.VM_TypeReference; +import static org.jikesrvm.compilers.opt.OPT_Constants.RUNTIME_SERVICES_BCI; +import org.jikesrvm.compilers.opt.ir.ALoad; +import org.jikesrvm.compilers.opt.ir.AStore; +import org.jikesrvm.compilers.opt.ir.Binary; +import org.jikesrvm.compilers.opt.ir.BoundsCheck; +import org.jikesrvm.compilers.opt.ir.BooleanCmp; +import org.jikesrvm.compilers.opt.ir.BooleanCmp2; +import org.jikesrvm.compilers.opt.ir.CacheOp; +import org.jikesrvm.compilers.opt.ir.Call; +import org.jikesrvm.compilers.opt.ir.GetField; +import org.jikesrvm.compilers.opt.ir.GetStatic; +import org.jikesrvm.compilers.opt.ir.Goto; +import org.jikesrvm.compilers.opt.ir.GuardedUnary; +import org.jikesrvm.compilers.opt.ir.IfCmp; +import org.jikesrvm.compilers.opt.ir.IfCmp2; +import org.jikesrvm.compilers.opt.ir.InlineGuard; +import org.jikesrvm.compilers.opt.ir.Load; +import org.jikesrvm.compilers.opt.ir.LookupSwitch; +import org.jikesrvm.compilers.opt.ir.LowTableSwitch; +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_IR; +import org.jikesrvm.compilers.opt.ir.OPT_IRTools; +import org.jikesrvm.compilers.opt.ir.OPT_Instruction; +import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_LocationOperand; +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 static org.jikesrvm.compilers.opt.ir.OPT_Operators.ARRAYLENGTH; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_INT; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP2_INT_AND_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP2_INT_OR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOUNDS_CHECK_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BYTE_ALOAD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BYTE_ASTORE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BYTE_LOAD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BYTE_STORE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CALL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CALL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CHECKCAST_NOTNULL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CHECKCAST_UNRESOLVED_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CHECKCAST_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_ALOAD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_ASTORE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_LOAD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_STORE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_ALOAD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_ASTORE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_LOAD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_STORE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GETFIELD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GETSTATIC_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_CLASS_OBJECT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_CLASS_TIB; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_OBJ_TIB; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_TYPE_FROM_TIB; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GOTO; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IG_CLASS_TEST_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.IG_METHOD_TEST_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INSTANCEOF_NOTNULL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INSTANCEOF_UNRESOLVED_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INSTANCEOF_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2ADDRSigExt; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2ADDRZerExt; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_ADD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_AND; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_OR; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_ALOAD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_ASTORE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_IFCMP; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_IFCMP2; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_LOAD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SHL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_STORE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_ZERO_CHECK_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_ALOAD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_ASTORE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_LOAD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_STORE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_ZERO_CHECK_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LOOKUPSWITCH; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LOOKUPSWITCH_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LOWTABLESWITCH; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.MUST_IMPLEMENT_INTERFACE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.OBJARRAY_STORE_CHECK_NOTNULL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.OBJARRAY_STORE_CHECK_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.PUTFIELD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.PUTSTATIC_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_ALOAD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_ASTORE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_IFCMP; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_LOAD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_STORE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.RESOLVE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.RESOLVE_MEMBER_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.SHORT_ALOAD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.SHORT_ASTORE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.SHORT_LOAD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.SHORT_STORE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.SYSCALL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.TABLESWITCH_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.TRAP_IF; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.UBYTE_ALOAD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.UBYTE_LOAD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.USHORT_ALOAD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.USHORT_LOAD; +import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TIBConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TrapCodeOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TypeOperand; +import org.jikesrvm.compilers.opt.ir.PutField; +import org.jikesrvm.compilers.opt.ir.PutStatic; +import org.jikesrvm.compilers.opt.ir.Store; +import org.jikesrvm.compilers.opt.ir.TableSwitch; +import org.jikesrvm.compilers.opt.ir.TrapIf; +import org.jikesrvm.compilers.opt.ir.Unary; +import org.jikesrvm.compilers.opt.ir.ZeroCheck; +import org.jikesrvm.memorymanagers.mminterface.MM_Constants; import org.jikesrvm.runtime.VM_Entrypoints; import org.jikesrvm.runtime.VM_Magic; -import org.jikesrvm.classloader.*; -import org.jikesrvm.compilers.opt.ir.*; -import org.jikesrvm.memorymanagers.mminterface.MM_Constants; -import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*; -import static org.jikesrvm.compilers.opt.OPT_Constants.*; -import static org.jikesrvm.VM_Constants.*; -import org.vmmagic.unboxed.*; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Offset; /** * Converts all remaining instructions with HIR-only operators into @@ -369,7 +498,7 @@ LookupSwitch.setBranchProfile(l, i, TableSwitch.getClearBranchProfile(s,i)); } - s.insertFront(l); + s.insertAfter(l); return s.remove(); } OPT_RegisterOperand reg = val.asRegister(); @@ -854,7 +983,7 @@ IC(methOp.getMemberRef().getId())); vp.position = v.position; vp.bcIndex = RUNTIME_SERVICES_BCI; - v.insertBack(vp); + v.insertBefore(vp); callHelper(vp, ir); Call.setAddress(v, realAddrReg.copyD2U()); return v; @@ -873,7 +1002,7 @@ RHStib, IC(methOp.getTarget().getDeclaringClass().getInterfaceId())); fi.position = v.position; fi.bcIndex = RUNTIME_SERVICES_BCI; - v.insertBack(fi); + v.insertBefore(fi); callHelper(fi, ir); OPT_RegisterOperand address = InsertLoadOffset(v, ir, REF_LOAD, @@ -959,7 +1088,7 @@ OPT_Operand o1, OPT_Operand o2) { OPT_RegisterOperand t = ir.regpool.makeTemp(type); - s.insertBack(Binary.create(operator, t, o1, o2)); + s.insertBefore(Binary.create(operator, t, o1, o2)); return t.copyD2U(); } @@ -977,7 +1106,7 @@ VM_TypeReference type, OPT_Operand o1) { OPT_RegisterOperand t = ir.regpool.makeTemp(type); - s.insertBack(Unary.create(operator, t, o1)); + s.insertBefore(Unary.create(operator, t, o1)); return t.copyD2U(); } @@ -997,7 +1126,7 @@ OPT_Operand o1, OPT_Operand guard) { OPT_RegisterOperand t = ir.regpool.makeTemp(type); - s.insertBack(GuardedUnary.create(operator, t, o1, guard)); + s.insertBefore(GuardedUnary.create(operator, t, o1, guard)); return t.copyD2U(); } @@ -1119,7 +1248,7 @@ OPT_RegisterOperand regTarget = ir.regpool.makeTemp(type); OPT_Instruction s2 = Load.create(operator, regTarget, reg2, offset, loc, guard); - s.insertBack(s2); + s.insertBefore(s2); return regTarget.copyD2U(); } @@ -1141,7 +1270,7 @@ OPT_RegisterOperand res = ir.regpool.makeTemp(VM_TypeReference.JavaLangObjectArray); OPT_Instruction s2 = GuardedUnary.create(GET_OBJ_TIB, res, obj, guard); - s.insertBack(s2); + s.insertBefore(s2); return res.copyD2U(); } @@ -1162,7 +1291,7 @@ } else if (!t.isResolved()) { OPT_RegisterOperand res = ir.regpool.makeTemp(VM_TypeReference.JavaLangObjectArray); - s.insertBack(Unary.create(GET_CLASS_TIB, res, type)); + s.insertBefore(Unary.create(GET_CLASS_TIB, res, type)); return res.copyD2U(); } else { return new OPT_TIBConstantOperand(t); Modified: ext/org/jikesrvm/compilers/opt/ir/OPT_BC2IR.java =================================================================== --- ext/org/jikesrvm/compilers/opt/ir/OPT_BC2IR.java 2007-05-09 11:23:16 UTC (rev 108) +++ ext/org/jikesrvm/compilers/opt/ir/OPT_BC2IR.java 2007-05-09 14:15:36 UTC (rev 109) @@ -3220,7 +3220,7 @@ if ((type == VM_TypeReference.JavaLangObject) && (r.getType().isMagicType()) && (r.getType() != VM_TypeReference.ObjectReference) && - !gc.method.getDeclaringClass().isMagicType() + !gc.method.getDeclaringClass().getTypeRef().isMagicType() ) { throw new OPT_OptimizingCompilerException.IllegalUpcast(r.getType()); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-09 11:23:15
|
Revision: 108 http://svn.sourceforge.net/pearcolator/?rev=108&view=rev Author: michael_baer Date: 2007-05-09 04:23:16 -0700 (Wed, 09 May 2007) Log Message: ----------- ELF Loader, version currently debugged Added Paths: ----------- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java Added: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java (rev 0) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-05-09 11:23:16 UTC (rev 108) @@ -0,0 +1,110 @@ +package org.binarytranslator.generic.os.loader.elf; + +import java.io.IOException; + +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.linux.ARM_LinuxProcessSpace; +import org.binarytranslator.generic.decoder.Interpreter; +import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.loader.elf.ELF_File.DynamicSection; +import org.binarytranslator.generic.os.process.ProcessSpace; + +public class ELF_Loader extends Loader { + + private ELF_File file; + private ELF_File loader; + + @Override + public ABI getABI() { + return file.getHeader().getABI(); + } + + @Override + public ISA getISA() { + return file.getHeader().getISA(); + } + + public int getProgramHeaderAddress() { + return file.getProgramHeaderAddress(); + } + + public int getNumberOfProgramSegmentHeaders() { + return file.getHeader().getNumberOfProgramSegmentHeaders(); + } + + public int getProgramSegmentHeaderSize() { + return file.getHeader().getProgramSegmentHeaderSize(); + } + + public static boolean conforms(String filename) { + return ELF_File.conforms(filename); + } + + @Override + public ProcessSpace readBinary(String filename) throws IOException { + + file = new ELF_File(filename); + ProcessSpace ps = ProcessSpace.createProcessSpaceFromBinary(this); + + ELF_File.SegmentHeader[] segments = file.getProgramSegmentHeaders(); + + System.out.println("ELF has segments:"); + for (ELF_File.SegmentHeader header : segments) { + System.out.println(header.toString()); + header.create(ps); + } + + int brk; + if (segments.length > 1) + brk = segments[1].getEnd(); + else + brk = segments[0].getEnd(); + + if (file.getDynamicSection() != null && file.getHeader().getABI() == ABI.ARM) { + + ARM_ProcessSpace armps = (ARM_ProcessSpace)ps; + + //invoke the runtime linker + RuntimeLinker ld = new RuntimeLinker(file, ps); + ld.link(); + + ps.initialise(this, file.getHeader().getEntryPoint(), brk); + int startInstruction = ps.getCurrentInstructionAddress(); + + //call the INITs + Interpreter interpreter = ps.createInstructionInterpreter(); + for (Integer init : ld.initMethods) { + int pc = init; + + ps.setCurrentInstructionAddress(init); + armps.registers.set(ARM_Registers.LR, init); + + while (!ps.finished) { + + Interpreter.Instruction instruction = interpreter.decode(pc); + System.out.println(String.format("[0x%x] %s", pc, instruction.toString())); + + instruction.execute(); + pc = instruction.getSuccessor(pc); + + if (pc == -1) + pc = ps.getCurrentInstructionAddress(); + else + ps.setCurrentInstructionAddress(pc); + + //we're done running the init method + if (pc == init) + break; + } + } + + ld._tmpRestore(); + ps.setCurrentInstructionAddress(startInstruction); + } + else + ps.initialise(this, file.getHeader().getEntryPoint(), brk); + + return ps; + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-08 16:54:30
|
Revision: 107 http://svn.sourceforge.net/pearcolator/?rev=107&view=rev Author: michael_baer Date: 2007-05-08 09:54:30 -0700 (Tue, 08 May 2007) Log Message: ----------- Reverted unintentionally commited change in main Modified Paths: -------------- src/org/binarytranslator/Main.java Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-05-08 16:38:23 UTC (rev 106) +++ src/org/binarytranslator/Main.java 2007-05-08 16:54:30 UTC (rev 107) @@ -98,14 +98,15 @@ //Create an execution controller and pass execution on to it ExecutionController controller; - /*if (DBT_Options.gdbStub) { + if (DBT_Options.gdbStub) { controller = new GdbController(DBT_Options.gdbStubPort, ps); } else { controller = new DynamicTranslationController(ps); - }*/ + } - controller = new InterpreterController(ps); + + //controller = new InterpreterController(ps); controller.run(); System.out.println("\nProgram has finished."); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-08 16:38:21
|
Revision: 106 http://svn.sourceforge.net/pearcolator/?rev=106&view=rev Author: michael_baer Date: 2007-05-08 09:38:23 -0700 (Tue, 08 May 2007) Log Message: ----------- Intermediate checkin of halfway working runtime linking. Modified Paths: -------------- src/org/binarytranslator/DBT.java src/org/binarytranslator/Main.java src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java src/org/binarytranslator/generic/execution/InterpreterController.java src/org/binarytranslator/generic/memory/DebugMemory.java Added Paths: ----------- src/org/binarytranslator/generic/os/loader/elf/ELF_File.java src/org/binarytranslator/generic/os/loader/elf/RuntimeLinker.java Removed Paths: ------------- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java Modified: src/org/binarytranslator/DBT.java =================================================================== --- src/org/binarytranslator/DBT.java 2007-05-08 16:35:56 UTC (rev 105) +++ src/org/binarytranslator/DBT.java 2007-05-08 16:38:23 UTC (rev 106) @@ -17,7 +17,7 @@ */ public final class DBT { /** Should the following assertion be checked? */ - public static final boolean VerifyAssertions = VM.VerifyAssertions; + public static final boolean VerifyAssertions = true; /** * Assert the following condition is true, if false then fail with stack trace @@ -27,9 +27,11 @@ if (!VerifyAssertions) { // Checking an assertion in a production build is a bad idea fail("Assertion checked when assertions should be disabled.\n" - + "Please guard the assertion with DBT.VerifyAssertions"); + + "Please guard the assertion with DBT.VerifyAssertions."); } else { - VM._assert(cond); + //VM._assert(cond); + if (!cond) + throw new RuntimeException("Assertion failed."); } } Modified: src/org/binarytranslator/Main.java =================================================================== --- src/org/binarytranslator/Main.java 2007-05-08 16:35:56 UTC (rev 105) +++ src/org/binarytranslator/Main.java 2007-05-08 16:38:23 UTC (rev 106) @@ -106,7 +106,7 @@ }*/ controller = new InterpreterController(ps); - controller.run(); + System.out.println("\nProgram has finished."); } } Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-05-08 16:35:56 UTC (rev 105) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-05-08 16:38:23 UTC (rev 106) @@ -9,6 +9,7 @@ import org.binarytranslator.generic.os.abi.linux.LinuxSystemCallGenerator; import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls; import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.loader.elf.ELF_Loader; public class ARM_LinuxProcessSpace extends ARM_ProcessSpace { @@ -54,9 +55,12 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_HWCAP, 0x97, LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 4096, //0x100 LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x17, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, 0x8034, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, 0x20, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0x6, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, + ((ELF_Loader)loader).getProgramHeaderAddress(), + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, + ((ELF_Loader)loader).getNumberOfProgramSegmentHeaders(), + LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, + ((ELF_Loader)loader).getProgramSegmentHeaderSize(), LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x40000000, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, 0x82b4, @@ -64,7 +68,7 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_EUID, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_GID, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_EGID, 0x0, - LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, 0xbffffecd, + LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, 0xbffffecd, LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0 }; registers.set(ARM_Registers.SP, LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector)); Modified: src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-05-08 16:35:56 UTC (rev 105) +++ src/org/binarytranslator/arch/ppc/os/process/linux/PPC_LinuxProcessSpace.java 2007-05-08 16:38:23 UTC (rev 106) @@ -102,9 +102,9 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, ((ELF_Loader)loader).getProgramHeaderAddress(), LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, - ((ELF_Loader)loader).elfHeader.getNumberOfProgramSegmentHeaders(), + ((ELF_Loader)loader).getNumberOfProgramSegmentHeaders(), LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, - ((ELF_Loader)loader).elfHeader.getProgramSegmentHeaderSize(), + ((ELF_Loader)loader).getProgramSegmentHeaderSize(), //LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, Modified: src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-05-08 16:35:56 UTC (rev 105) +++ src/org/binarytranslator/arch/x86/os/process/linux/X86_LinuxProcessSpace.java 2007-05-08 16:38:23 UTC (rev 106) @@ -91,7 +91,7 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_PAGESZ, 0x1000, LinuxStackInitializer.AuxiliaryVectorType.AT_CLKTCK, 0x64, LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, ((ELF_Loader)loader).getProgramHeaderAddress(), - LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, ((ELF_Loader)loader).elfHeader.getNumberOfProgramSegmentHeaders(), + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, ((ELF_Loader)loader).getNumberOfProgramSegmentHeaders(), LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, pc, Modified: src/org/binarytranslator/generic/execution/InterpreterController.java =================================================================== --- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-05-08 16:35:56 UTC (rev 105) +++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-05-08 16:38:23 UTC (rev 106) @@ -14,7 +14,7 @@ Interpreter interpreter = ps.createInstructionInterpreter(); int pc = ps.getCurrentInstructionAddress(); - + while (!ps.finished) { Interpreter.Instruction instruction = interpreter.decode(pc); Modified: src/org/binarytranslator/generic/memory/DebugMemory.java =================================================================== --- src/org/binarytranslator/generic/memory/DebugMemory.java 2007-05-08 16:35:56 UTC (rev 105) +++ src/org/binarytranslator/generic/memory/DebugMemory.java 2007-05-08 16:38:23 UTC (rev 106) @@ -11,6 +11,7 @@ import java.io.RandomAccessFile; import java.nio.channels.FileChannel; +import org.binarytranslator.DBT; import org.binarytranslator.DBT_Options; import org.binarytranslator.vmInterface.TranslationHelper; import org.jikesrvm.compilers.opt.ir.OPT_Operand; @@ -219,10 +220,12 @@ // Calculate number of pages int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE; + // Find address if not specified - if (addr == 0) { + /*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 @@ -236,15 +239,30 @@ // 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); } - // Allocate page - byte page[] = new byte[PAGE_SIZE]; + 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 @@ -252,6 +270,7 @@ } else { file.read(page); } + if (read) { readableMemory[pte + i] = page; } @@ -272,6 +291,8 @@ + Integer.toHexString(addr) + " len=" + len); } + System.out.println("Unexpected page mapping!!!!!!!!!!!!!!!!!!!!"); + byte[] page; if (write) @@ -284,7 +305,7 @@ } if (read) { - readableMemory[pte + 1] = page; + readableMemory[pte + i] = page; } if (exec) { Copied: src/org/binarytranslator/generic/os/loader/elf/ELF_File.java (from rev 83, src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java) =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_File.java (rev 0) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-05-08 16:38:23 UTC (rev 106) @@ -0,0 +1,1510 @@ +/* + * 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.os.loader.elf; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.security.InvalidParameterException; +import java.util.ArrayList; +import java.util.WeakHashMap; + +import org.binarytranslator.DBT; +import org.binarytranslator.DBT_Options; +import org.binarytranslator.generic.memory.Memory; +import org.binarytranslator.generic.memory.MemoryMapException; +import org.binarytranslator.generic.os.loader.Loader; +import org.binarytranslator.generic.os.process.ProcessSpace; + +public class ELF_File { + + /** + * Wrapper class used for reading the ELF file with the required endianness + */ + private BinaryReader reader; + + /** + * Header of ELF file + */ + private Header header; + + /** + * Program segment headers + */ + private SegmentHeader segmentHeaders[]; + + /** + * Debug information + * @param s string of debug information + */ + private static void report(String s) { + if (DBT_Options.debugLoader) { + System.out.print("ELF Loader:"); + System.out.println(s); + } + } + /** + * Reader for byte and multibyte values respecting endianness. + */ + private abstract static class BinaryReader { + + /** File to read from */ + protected RandomAccessFile rFile; + + /** + * Returns a new ELF_BinaryReader for the specified byte order and file. + * + * @param byteOrder + * The byte order that the file posesses. + * @param file + * The file that is to be read. + * @return + * An ELF_BinaryReader, that hides the details of the byte order. + */ + public static BinaryReader create(ELF_Identity.ByteOrder byteOrder, RandomAccessFile file) { + + if (byteOrder == ELF_Identity.ByteOrder.BigEndian) + return new NonSwappingReader(file); + else + return new ByteSwappingReader(file); + } + + /** Hide the constructor, because this class shall only be instantiated by using the factory method {@link #create(org.binarytranslator.generic.os.loader.elf.ELF_Loader.Header.ByteOrder, RandomAccessFile)}. */ + private BinaryReader(RandomAccessFile rFile) { + this.rFile = rFile; + } + + /** Seek to location from beginning of file */ + void seek(long pos) throws IOException { + rFile.seek(pos); + } + + /** Reads a single byte from an ELF file. */ + public byte readByte() throws IOException { + return rFile.readByte(); + } + + /** Read an integer from the file. This function is supposed to hide the difference between little and big endian reads. */ + public abstract int readInt() throws IOException; + + /** Read a short from the file. This function is supposed to hide the difference between little and big endian reads. */ + public abstract short readShort() throws IOException; + + /** Reader that performs byte swaps for each int/short read. */ + private static class ByteSwappingReader extends BinaryReader { + + ByteSwappingReader(RandomAccessFile rFile) { + super(rFile); + } + + /** Byte swap a 32-bit integer */ + private static int bswap(int x) { + return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) + | (x >>> 24); + } + + /** Byte swap a 16-bit integer */ + private static short bswap(short x) { + short result = (short) (((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); + return result; + } + + @Override + public int readInt() throws IOException { + return bswap(rFile.readInt()); + } + + @Override + public short readShort() throws IOException { + return bswap(rFile.readShort()); + } + } + + /** Reader that does not perform any byte swaps.*/ + private static class NonSwappingReader extends BinaryReader { + + NonSwappingReader(RandomAccessFile rFile) { + super(rFile); + } + + @Override + public int readInt() throws IOException { + return rFile.readInt(); + } + + @Override + public short readShort() throws IOException { + return rFile.readShort(); + } + } + } + + /** + * Returns an Object representation of this ELF's header file. + */ + public Header getHeader() { + return header; + } + + /** Returns an array of program segment headers within this elf.*/ + public SegmentHeader[] getProgramSegmentHeaders() { + return segmentHeaders; + } + + /** Returns the dynamic section, which is identifed by the PT_DYNAMIC segment header. */ + public DynamicSection getDynamicSection() throws IOException { + + for (ELF_File.SegmentHeader segment : segmentHeaders) + if (segment.p_type == ELF_File.SegmentHeader.PT_DYNAMIC) { + return segment.asDynamicSection(); + } + + return null; + } + + /** + * Reads an ELF File from a binary. + * @param filename the program file name + * @return An object representation of the ELF file + */ + public ELF_File(String filename) throws IOException { + report("Opening File: " + filename); + RandomAccessFile rFile = new RandomAccessFile(filename, "r"); + + // Read the ELF Header, which will also provide us with a reader object, that hides ELF endianness + header = new Header(rFile); + reader = header.getReader(); + + report("ELF header read successfully"); + + //read the program segment headers + report("Reading program segment headers"); + segmentHeaders = new SegmentHeader[header.getNumberOfProgramSegmentHeaders()]; + reader.seek(header.getProgramSegmentHeaderOffset()); + + for (int i = 0; i < segmentHeaders.length; i++) { + segmentHeaders[i] = new SegmentHeader(reader); + } + + /* + report("Creating program segments"); + for (int i = 0; i < segmentHeaders.length; i++) { + report("Creating: " + segmentHeaders[i]); + segmentHeaders[i].create(ps); + } + + int brk; + if (segmentHeaders.length > 1) { + brk = segmentHeaders[1].getEnd(); + } else { + brk = segmentHeaders[0].getEnd(); + } + report("Initialising the process space: " + "entry = 0x" + + Integer.toHexString(elfHeader.getEntryPoint()) + " brk = 0x" + + Integer.toHexString(brk)); + ps.initialise(this, elfHeader.getEntryPoint(), brk); + + return ps;*/ + } + + /** + * Determine if the id array corresponds with the initial part of an ELF + * binary + * @param filename Name of the file to check + * @return whether this is an ELF binary + */ + public static boolean conforms(String filename) { + + RandomAccessFile rFile = null; + report("Testing is file is ELF: " + filename); + + try { + rFile = new RandomAccessFile(filename, "r"); + byte[] id = new byte[4]; + rFile.read(id); + + return (id[0] == 0x7f) && (id[1] == 'E') && (id[2] == 'L') + && (id[3] == 'F'); + } catch (Exception e) { + return false; + } finally { + try { + rFile.close(); + } catch (Exception e) { + } + } + } + + /** + * Where did the program header get loaded in memory? + */ + public int getProgramHeaderAddress() { + return segmentHeaders[0].p_vaddr; + //return header.e_phoff - segmentHeaders[0].p_offset + segmentHeaders[0].p_vaddr; + } + + /** An interface for enums where each value is identified by an identifier.*/ + private static interface IdentifiedEnum { + int getIdentifier(); + } + + /** Returns the segment that the given virtual address belongs to. */ + public SegmentHeader virtualAddressToSegment(int virtualAddress) { + + for (int i = 0; i < segmentHeaders.length; i++) { + int offsetWithinSegment = (virtualAddress - segmentHeaders[i].p_vaddr); + + if (offsetWithinSegment > 0 && offsetWithinSegment < segmentHeaders[i].p_memsz) { + return segmentHeaders[i]; + } + } + + return null; + } + + /** + * Creates a corresponding enum value from an integer identifier for enums implementing the {@link IdentifiedEnum} interface. + * In case no corresponding enum value is available, the function returns null. */ + private static <T extends Enum<T> & IdentifiedEnum> T getEnumFromIdentifier(Class<T> enumClass, int identifier) { + for (T value : enumClass.getEnumConstants()) + if (value.getIdentifier() == identifier) + return value; + + return null; + } + + /** + * Class to read and hold ELF header indentity information + */ + @SuppressWarnings("unused") + private static class ELF_Identity { + + private BinaryReader reader; + + /** Represents acceptable ELF address sizes. */ + private enum AddressSize implements IdentifiedEnum { + Size32(1), + Size64(2); + + private int identifier; + + private AddressSize(int identifier) { + this.identifier = identifier; + } + + public int getIdentifier() { + return identifier; + } + } + + /** Represents accepted ELF byte orders. */ + private enum ByteOrder implements IdentifiedEnum { + LittleEndian(1), + BigEndian(2); + + private int identifier; + + private ByteOrder(int identifier) { + this.identifier = identifier; + } + + public int getIdentifier() { + return identifier; + } + } + + /* Symbolic names for the most widely used ABIs. This is not an enum, because the list isn't complete. */ + private static final byte ELFOSABI_SYSTEMV = 0; + private static final byte ELFOSABI_HPUX = 1; + private static final byte ELFOSABI_NETBSD = 2; + private static final byte ELFOSABI_LINUX = 3; + private static final byte ELFOSABI_SOLARIS = 6; + private static final byte ELFOSABI_AIX = 7; + private static final byte ELFOSABI_IRIX = 8; + private static final byte ELFOSABI_FREEBSD = 9; + private static final byte ELFOSABI_TRU64 = 10; + private static final byte ELFOSABI_MODESTO = 11; + private static final byte ELFOSABI_OPENBSD = 12; + private static final byte ELFOSABI_OPENVMS = 13; + private static final byte ELFOSABI_NSK = 14; + private static final byte ELFOSABI_ARM = 97; + + /** + * ELF magic values indicating an ELF file + */ + private static final byte ELF_MAGIC_VALUE[] = { 0x7f, 'E', 'L','F' }; + + /** Specifies the size of an address within this elf.*/ + private AddressSize addressSize; + + /** The byte order used by this elf.*/ + private ByteOrder byteOrder; + + /** The ABI that is used by this ELF.*/ + private byte abi; + + /** + * Construct/read ELF identity + */ + ELF_Identity(RandomAccessFile rFile) throws IOException { + // Identification is in bytes and therefore is endian agnostic + byte[] magic = new byte[ELF_MAGIC_VALUE.length]; + + if (rFile.read(magic) != magic.length) + throw new IOException("ELF file too short."); + + // Check that the ELF magic is correct + for (int i = 0; i < ELF_MAGIC_VALUE.length; i++) { + if (magic[i] != ELF_MAGIC_VALUE[i]) { + throw new IOException("Bad ELF file magic: " + rFile); + } + } + + //read the address size + addressSize = getEnumFromIdentifier(AddressSize.class, rFile.readByte()); + if (addressSize == null) + throw new IOException("Invalid address sizer specified by ELF file."); + + //read the byte order + byteOrder = getEnumFromIdentifier(ByteOrder.class, rFile.readByte()); + if (byteOrder == null) + throw new IOException("Invalid byte order specified by ELF file."); + + //Check the ELF's file version + if (rFile.readByte() != 1) { + throw new IOException("Invalid ELF File version."); + } + + //read a byte describing the target ABI + abi = rFile.readByte(); + + //skip the remaining padding bytes so that we're arriving at a 16 byte alignment. + if (rFile.skipBytes(8) != 8) { + throw new IOException("ELF file is too short."); + } + + reader = BinaryReader.create(byteOrder, rFile); + } + + public Loader.ABI getABI() + { + //read the OS ABI + switch (abi) { + case ELFOSABI_SYSTEMV: + return Loader.ABI.SystemV; + + case ELFOSABI_LINUX: + return Loader.ABI.Linux; + + case ELFOSABI_ARM: + return Loader.ABI.ARM; + + default: + return Loader.ABI.Undefined; + } + } + + protected BinaryReader getReader() { + return reader; + } + } + + /** + * Class to read and hold ELF header information + */ + @SuppressWarnings("unused") + public static class Header extends ELF_Identity { + + /** A list of possible object file types. */ + enum ObjectFileType implements IdentifiedEnum { + Relocatable(1), + Executable(2), + SharedObject(3), + Core(4); + + private int identifier; + + private ObjectFileType(int identifier) { + this.identifier = identifier; + } + + public int getIdentifier() { + return identifier; + } + } + + /** Object file type */ + private ObjectFileType e_type; + + /** + * Start of OS reserved region + */ + private static final short ET_LOOS = (short) 0xfe00; + + /** + * End of OS reserved region + */ + private static final short ET_HIOS = (short) 0xfeff; + + /** + * Start of processor-specific reserved region + */ + private static final short ET_LOPROC = (short) 0xff00; + + /** + * End of processor-specific reserved region + */ + private static final short ET_HIPROC = (short) 0xffff; + + /** + * The required architecture (machine) for the object file + */ + private short e_machine; + + /* Short names for a few known machine types. Not an enum, because this list is not complete. */ + private static final short EM_M32 = 1; + private static final short EM_SPARC = 2; + private static final short EM_386 = 3; + private static final short EM_68K = 4; + private static final short EM_88K = 5; + private static final short EM_860 = 7; + private static final short EM_MIPS = 8; + private static final short EM_PPC = 20; + private static final short EM_ARM = 40; + private static final short EM_ALPHA = 41; + private static final short EM_SPARCV9 = 43; + + /** + * Object file version + */ + private int e_version; + + /** + * Entry point virtual address. The virtual address to which the system + * first transfers control, thus starting the process. + */ + private int e_entry; + + /** + * Program header table file offset + */ + private int e_phoff; + + /** + * Section header table file offset + */ + private final int e_shoff; + + /** + * Processor-specific flags + */ + private final int e_flags; + + /** + * ELF header size in bytes + */ + private final short e_ehsize; + + /** + * Program header table entry size + */ + private final short e_phentsize; + + /** + * Program header table entry count + */ + private final short e_phnum; + + /** + * Section header table entry size + */ + private final short e_shentsize; + + /** + * Section header table entry count + */ + private final short e_shnum; + + /** + * Section header table index + */ + private final short e_shstrndx; + + /** + * Construct/read ELF header + */ + Header(RandomAccessFile file) throws IOException { + super(file); + + BinaryReader reader = getReader(); + + try { + // Read in rest of header + e_type = getEnumFromIdentifier(ObjectFileType.class, reader.readShort()); + + if (e_type == null) { + throw new Error("Invalid Object file type."); + } + + e_machine = reader.readShort(); + e_version = reader.readInt(); + + if (e_version != 1) { + throw new Error("Unexpected ELF File version: " + e_version); + } + + e_entry = reader.readInt(); + e_phoff = reader.readInt(); + e_shoff = reader.readInt(); + e_flags = reader.readInt(); + e_ehsize = reader.readShort(); + e_phentsize = reader.readShort(); + e_phnum = reader.readShort(); + e_shentsize = reader.readShort(); + e_shnum = reader.readShort(); + e_shstrndx = reader.readShort(); + } catch (IOException e) { + throw new Error(e); + } + } + + /** + * What is the offset in the file of the program headers + */ + public int getProgramSegmentHeaderOffset() { + return e_phoff; + } + + /** + * What's the size of a program segment header? + */ + public int getProgramSegmentHeaderSize() { + return e_phentsize; + } + + /** + * How many program segments are in this ELF binary? + */ + public int getNumberOfProgramSegmentHeaders() { + return e_phnum; + } + + /** + * Return the entry point of the binary + */ + public int getEntryPoint() { + return e_entry; + } + + /** Maps the ISA specified within the ELF file to an ISA supported by Pearcolator. */ + public Loader.ISA getISA() { + switch (e_machine) { + case EM_ARM: + return Loader.ISA.ARM; + + case EM_386: + return Loader.ISA.X86; + + case EM_PPC: + return Loader.ISA.PPC; + + default: + return Loader.ISA.Undefined; + } + } + } + + /** Identifies a named segment range. */ + private enum SegmentRange { + /** SUN reserved segments */ + SunReserved(0x6ffffffa, 0x6fffffff, "SUN Reserved Segment"), + + /** OS reserved segment types */ + OperatingSystem(0x60000000, 0x6fffffff, ("Operating System Segment")), + + /** processor reserved segment types */ + Processor(0x70000000, 0x7fffffff, "Processor Segment"), + + /** remaining (unknown) segment types */ + Unknown(0x0, 0xffffffff, "Unknown Segment"); + + private int lowAddress; + private int highAddress; + private String description; + + private SegmentRange(int from, int to, String description) { + + if (DBT.VerifyAssertions) DBT._assert(from < to); + + lowAddress = from; + highAddress = to; + this.description = description; + } + + public static SegmentRange fromInteger(int address) { + for (SegmentRange range : values()) { + if (range.lowAddress >= address && range.highAddress <= address) + return range; + } + + return null; + } + + @Override + public String toString() { + return description; + } + } + + public class StringTable { + + /** Every string that has been resolved is cached in this map to allow faster retrieval for the next time. */ + private WeakHashMap<Integer, String> cachedStrings = new WeakHashMap<Integer, String>(); + + /** A buffer that holds the table's contents*/ + private byte[] buffer; + + public StringTable(int virtualAddress, int size) throws IOException { + + //initialize the buffer + buffer = new byte[size]; + + //find the segment within which the string table resides + SegmentHeader strTableSeg = virtualAddressToSegment(virtualAddress); + + if (strTableSeg == null) + throw new IOException("Unable to locate the segment within which the string table resides."); + + int offsetWithinSegment = virtualAddress - strTableSeg.p_vaddr; + reader.seek(strTableSeg.p_offset + offsetWithinSegment); + + int readBytes = reader.rFile.read(buffer); + + if (readBytes != buffer.length) + throw new IOException("Unable to read string table from file."); + } + + /** Looks a string table entry up by address. */ + public String lookup(int index) { + if (index >= buffer.length) + throw new IndexOutOfBoundsException("Invalid string table index: " + index); + + String result = cachedStrings.get(index); + + if (result != null) + return result; + + int nextIndex = index; + + result = ""; + byte b = (byte)buffer[nextIndex++]; + + while (b != 0) { + result += (char)b; + b = (byte)buffer[nextIndex++]; + } + + //cache the string that we just found + cachedStrings.put(index, result); + + //and return the result + return result; + } + } + + public class SymbolHashTable { + private final SymbolTable symTab; + private final StringTable strTab; + + private final int buckets[]; + private final int chains[]; + + public SymbolHashTable(SymbolTable symTab, StringTable strTab, int virtualAddress) throws IOException { + this.symTab = symTab; + this.strTab = strTab; + + //find the hash table within the file + SegmentHeader segment = virtualAddressToSegment(virtualAddress); + + if (segment == null) + throw new IOException("Unable to locate the segment within which the hash table resides."); + + int offsetWithinSegment = virtualAddress - segment.p_vaddr; + reader.seek(segment.p_offset + offsetWithinSegment); + + //load the hash table from the file + int bucketCount = reader.readInt(); + int chainCount = reader.readInt(); + + buckets = new int[bucketCount]; + chains = new int[chainCount]; + + for (int i = 0; i < bucketCount; i++) + buckets[i] = reader.readInt(); + + for (int i = 0; i < chainCount; i++) + chains[i] = reader.readInt(); + } + + public SymbolTable.Entry lookup(String symbol) throws IOException { + int hash = getElfHash(symbol); + + //what is the index of that symbol in the symbol table? + int symbolIndex = buckets[hash % buckets.length]; + + while (symbolIndex != SymbolTable.STN_UNDEF) { + //get the symbol that we retrieved from the hash table + SymbolTable.Entry entry = symTab.getEntry(symbolIndex); + String curSymbolname = strTab.lookup(entry.nameIdx); + + //is that the symbol we're looking for? + if (curSymbolname.equals(symbol)) + return entry; + + //if not, follow the chain to the next symbol + symbolIndex = chains[symbolIndex]; + } + + //obviously, we couldn't find this symbol + return null; + } + + private int getElfHash(String symbol) { + + int h = 0; + int g = 0; + int nextChar = 0; + + while (nextChar < symbol.length()) { + h = (h << 4) + (byte) symbol.charAt(nextChar++); + + g = h & 0xf0000000; + if (g != 0) + h ^= g >>> 24; + + h &= ~g; + } + + return h; + } + + + } + + public class SymbolTable { + + /** The undefined symbol index. */ + public final static int STN_UNDEF = 0; + + /** Symbol binding values. All other values are processor-dependant. */ + public final static byte STB_LOCAL = 0; + public final static byte STB_GLOBAL = 1; + public final static byte STB_WEAK = 2; + + /** Symbol types. */ + public final static byte STT_NOTYPE = 0; + public final static byte STT_OBJECT = 1; + public final static byte STT_FUNC = 2; + public final static byte STT_SECTION = 3; + public final static byte STT_FILE = 4; + + /** Some section indices have special meanings: */ + public final static short SHN_ABS = (short)0xfff1; + public final static short SHN_COMMON = (short)0xfff2; + public final static short SHN_UNDEF = 0; + + public class Entry { + public final int nameIdx; + public final int value; + public final int size; + public final byte binding; + public final byte type; + public final short sectionIndex; + + public Entry(int nameIdx, int value, int size, byte binding, byte type, short sectionIndex) { + this.nameIdx = nameIdx; + this.value = value; + this.size = size; + this.binding = binding; + this.type = type; + this.sectionIndex = sectionIndex; + } + + final boolean isUndefined() { + return sectionIndex == SHN_UNDEF; + } + } + + /** Every symbol that has been retrieved previously is cached in this map to allow faster access for the next time. */ + private WeakHashMap<Integer, Entry> cachedSymbols = new WeakHashMap<Integer, Entry>(); + + /** Offset at which the symbol table starts within the file. */ + private final int fileOffset; + + /** size of a single entry within the symbol table */ + private final int entrySize; + + public SymbolTable(int virtualAddress, int entrySize) throws IOException { + SegmentHeader segment = virtualAddressToSegment(virtualAddress); + int offset = virtualAddress - segment.p_vaddr; + + fileOffset = segment.p_offset + offset; + this.entrySize = entrySize; + } + + public Entry getEntry(int index) throws IOException { + + //check if we already have cached version of this symbol + Entry result = cachedSymbols.get(index); + + if (result != null) + return result; + + //no, we have to read it from the file + reader.seek(fileOffset + entrySize * index); + + int name = reader.readInt(); + int addr = reader.readInt(); + int size = reader.readInt(); + byte info = reader.readByte(); + reader.readByte(); //skip an empty byte + short sectionIndex = reader.readShort(); + + //create the requested entry... + result = new Entry(name, addr, size, (byte)(info >>> 4), (byte)(info & 0xF), sectionIndex); + + //cache it for the next time + cachedSymbols.put(index, result); + + return result; + } + } + + public class RelocationTable { + + public final ArrayList<Entry> entries; + public final boolean hasAddends; + + public class Entry { + public final int offset; + public final int symbolIndex; + public final byte relocationType; + public final int addend; + + public Entry(int offset, int symbolindex, byte relocationType, int addend) { + this.offset = offset; + this.symbolIndex = symbolindex; + this.relocationType = relocationType; + this.addend = addend; + } + + @Override + public String toString() { + return String.format("Offset: %d, Symbol: %d, Type: %d, Addend: %d", offset, symbolIndex, relocationType, addend); + } + } + + public RelocationTable(int virtualAddress, int tableSize, int entrySize, boolean hasAddends) throws IOException { + + //check the parameters + if (tableSize < 0 || entrySize < 0) { + throw new InvalidParameterException("Cannot create relocation section from invalid section sizes."); + } + + this.entries = new ArrayList<Entry>(); + this.hasAddends = hasAddends; + + //find the segment within which the string table resides + SegmentHeader strTableSeg = virtualAddressToSegment(virtualAddress); + + if (strTableSeg == null) + throw new IOException("Unable to locate the segment within which the relocation section resides."); + + int offsetWithinSegment = virtualAddress - strTableSeg.p_vaddr; + virtualAddress = strTableSeg.p_offset + offsetWithinSegment; + + while (tableSize >= entrySize) { + reader.seek(virtualAddress); + + //read a single relocation entry + int offset = reader.readInt(); + int info = reader.readInt(); + int addend = 0; + + if (hasAddends) + addend = reader.readInt(); + + //add it to the list of relocation entries + entries.add(new Entry(offset, info >>> 8, (byte)(info & 0xFF), addend)); + + //skip to the next entry + virtualAddress += entrySize; + tableSize -= entrySize; + } + } + + @Override + public String toString() { + String result = ""; + + for (int i = 0; i < entries.size(); i++) + result += entries.get(i).toString() + "\n"; + + return result; + } + } + + public class DynamicSection { + public final static int DT_NULL = 0; + public final static int DT_NEEDED = 1; + public final static int DT_PLTRELSZ = 2; + public final static int DT_PLTGOT = 3; + public final static int DT_HASH = 4; + public final static int DT_STRTAB = 5; + public final static int DT_SYMTAB = 6; + public final static int DT_RELA = 7; + public final static int DT_RELASZ = 8; + public final static int DT_RELAENT = 9; + public final static int DT_STRSZ = 10; + public final static int DT_SYMENT = 11; + public final static int DT_INIT = 12; + public final static int DT_FINI = 13; + public final static int DT_SONAME = 14; + public final static int DT_RPATH = 15; + public final static int DT_SYMBOLIC = 16; + public final static int DT_REL = 17; + public final static int DT_RELSZ = 18; + public final static int DT_RELENT = 19; + public final static int DT_PLTREL = 20; + public final static int DT_DEBUG = 21; + public final static int DT_TEXTREL = 22; + public final static int DT_JMPREL = 23; + public final static int DT_BIND_NOW = 24; + + public class Entry { + public final int type; + public final int value; + + private Entry(int type, int value) { + this.type = type; + this.value = value; + } + + @Override + public String toString() { + return String.format("Type: %d, Value: 0x%x", type, value); + } + } + + /** the entries within the dynamic section */ + private ArrayList<Entry> entries = new ArrayList<Entry>(); + + /** the string table referenced by the dynamic section */ + private StringTable strTab; + + /** The symbol table referenced by this dynamic section. */ + private SymbolTable symTab; + + /** The hash table referenced by this dynamic section. */ + private SymbolHashTable hashTab; + + /** The relA section (if present) that is referenced within this dynamic section */ + private RelocationTable relaTab; + + /** The rel section (if present) that is referenced within this dynamic section */ + private RelocationTable relTab; + + public DynamicSection(SegmentHeader segment) throws IOException { + + if (segment.p_type != SegmentHeader.PT_DYNAMIC) + throw new InvalidParameterException("segment is not of type PT_DYNAMIC."); + + reader.seek(segment.p_offset); + Entry entry; + + do { + int type = reader.readInt(); + int value = reader.readInt(); + + entry = new Entry(type, value); + entries.add(entry); + } + while (entry.type != DT_NULL); + } + + public Entry getEntryByType(int type) { + for(Entry entry : entries) + if (entry.type == type) + return entry; + + return null; + } + + public Entry[] getEntriesByType(int type) { + ArrayList<Entry> matches = new ArrayList<Entry>(); + + for(Entry entry : entries) + if (entry.type == type) + matches.add(entry); + + Entry[] result = new Entry[matches.size()]; + return matches.toArray(result); + } + + public SymbolHashTable findHashTable() throws IOException { + if (hashTab != null) + return hashTab; + + Entry tabLocation = getEntryByType(DT_HASH); + + SymbolTable symTab = findSymbolTable(); + StringTable strTab = findStringTable(); + + if (symTab == null || strTab == null || tabLocation == null) + return null; + + hashTab = new SymbolHashTable(symTab, strTab, tabLocation.value); + return hashTab; + } + + public SymbolTable findSymbolTable() throws IOException { + + if (symTab != null) + return symTab; + + Entry tabLocation = getEntryByType(DT_SYMTAB); + Entry entrySize = getEntryByType(DT_SYMENT); + + if (tabLocation == null || entrySize == null) + return null; + + symTab = new SymbolTable(tabLocation.value, entrySize.value); + return symTab; + } + + public StringTable findStringTable() throws IOException { + + if (strTab != null) + return strTab; + + Entry tabLocation = getEntryByType(DT_STRTAB); + Entry tabSize = getEntryByType(DT_STRSZ); + + if (tabLocation == null || tabSize == null) + return null; + + strTab = new StringTable(tabLocation.value, tabSize.value); + return strTab; + } + + public RelocationTable findJmpRelTable() throws IOException { + + Entry tabLocation = getEntryByType(DT_JMPREL); + Entry tabSize = getEntryByType(DT_PLTRELSZ); + Entry entrySize = getEntryByType(DT_RELENT); + Entry entryType = getEntryByType(DT_PLTREL); + + if (tabLocation == null || tabSize == null || entrySize == null | entryType == null) + return null; + + relaTab = new RelocationTable(tabLocation.value, tabSize.value, entrySize.value, entryType.value == DT_RELA); + + return relaTab; + } + + public RelocationTable findRelaTable() throws IOException { + + if (relaTab != null) + return relaTab; + + Entry tabLocation = getEntryByType(DT_RELA); + Entry tabSize = getEntryByType(DT_RELASZ); + Entry entrySize = getEntryByType(DT_RELAENT); + + if (tabLocation == null || tabSize == null || entrySize == null) + return null; + + relaTab = new RelocationTable(tabLocation.value, tabSize.value, entrySize.value, true); + + return relaTab; + } + + public RelocationTable findRelTable() throws IOException { + + if (relTab != null) + return relTab; + + Entry tabLocation = getEntryByType(DT_REL); + Entry tabSize = getEntryByType(DT_RELSZ); + Entry entrySize = getEntryByType(DT_RELENT); + + if (tabLocation == null || tabSize == null || entrySize == null) + return null; + + relTab = new RelocationTable(tabLocation.value, tabSize.value, entrySize.value, false); + return relTab; + } + + @Override + public String toString() { + String result = ""; + + for(Entry entry : entries) + result = result + entry.toString() + "\n"; + + return result; + } + } + + /** + * Header representing a segment in the process (e.g. stack, heap, code aka + * text) in the ELF file. These are known as program header's in the ELF + * literature, but they don't represent programs, rather separate segments. + */ + @SuppressWarnings("unused") + public class SegmentHeader { + /** + * Type of the segment + */ + public final int p_type; + + /** + * Null header, contains no data and can be ignored + */ + public static final int PT_NULL = 0; + + /** + * A loadable segment + */ + public static final int PT_LOAD = 1; + + /** + * Segment containing dynamic linking information + */ + public static final int PT_DYNAMIC = 2; + + /** + * A segment containing a string to invoke as interpreter for this file + */ + public static final int PT_INTERP = 3; + + /** + * A segment describing the location and size of auxiliary information + */ + public static final int PT_NOTE = 4; + + /** + * A reserved segment type with unspecified semantics + */ + public static final int PT_SHLIB = 5; + + /** + * A segment describing the ELF's header, present once before any loadable + * segments + */ + public static final int PT_PHDR = 6; + + /** + * Thread local storage (TLS) segment + */ + public static final int PT_TLS = 7; + + + /** + * Start of OS reserved segment types + */ + + /** + * SUN unwind table segment + */ + public static final int PT_SUNW_UNWIND = 0x6464e550; + + /** + * GCC .eh_frame_hdr segment + */ + public static final int PT_GNU_EH_FRAME = 0x6474e550; + + /** + * Indicates stack executability + */ + public static final int PT_GNU_STACK = 0x6474e551; + + /** + * Read-only after relocation + */ + public static final int PT_GNU_RELRO = 0x6474e552; + + /** + * Start of SUN reserved segments + */ + + /** + * The array element has the same attributes as a PT_LOAD element and is + * used to describe a .SUNW_bss section. + */ + public static final int PT_SUNWBSS = 0x6ffffffa; + + /** + * Describes a process stack. Only one PT_SUNWSTACK element can exist. Only + * access permissions, as defined in the p_flags field, are meaningful. + */ + public static final int PT_SUNWSTACK = 0x6ffffffb; + + /** + * Reserved for internal use by dtrace + */ + public static final int PT_SUNWDTRACE = 0x6ffffffc; + + /** + * Specifies hardware capability requirements + */ + public static final int PT_SUNWCAP = 0x6ffffffd; + + /** + * End of SUN reserved segments + */ + + /** + * End of OS reserved segment types + */ + + + /** + * Offset of first byte of segment data in file + */ + public final int p_offset; + + /** + * Virtual address of first byte in segment + */ + public final int p_vaddr; + + /** + * Corresponding physical addressed used by some systems + */ + public int p_paddr; + + /** + * Size of segment in file + */ + public final int p_filesz; + + /** + * Size of segment in memory + */ + public final int p_memsz; + + /** + * Read/Write/Execute flags for segment in memory + */ + public int p_flags; + + /** + * Executable flag + */ + public static final int PF_X = 0x1; + + /** + * Writable flag + */ + public static final int PF_W = 0x2; + + /** + * Readable flag + */ + public static final int PF_R = 0x4; + + /** + * OS specific reserved bits + */ + private static final int PF_MASKOS = 0x0ff00000; + + /** + * Processor specific reserved bits + */ + private static final int PF_MASKPROC = 0xf0000000; + + /** + * This member gives the value to which the segments are aligned in memory + * and in the file. Values 0 and 1 mean no alignment is required. Otherwise, + * p_align should be a positive, integral power of 2, and p_vaddr should + * equal p_offset, modulo p_align. + */ + private final int p_align; + + /** + * Construct a program segment header reading in from the reader + */ + private SegmentHeader(BinaryReader reader) throws IOException { + p_type = reader.readInt(); + p_offset = reader.readInt(); + p_vaddr = reader.readInt(); + p_paddr = reader.readInt(); + p_filesz = reader.readInt(); + p_memsz = reader.readInt(); + p_flags = reader.readInt(); + p_align = reader.readInt(); + // Move file onto next program segment header offset + reader.rFile.skipBytes(header.getProgramSegmentHeaderSize() - 32); + } + + public DynamicSection asDynamicSection() throws IOException { + return new DynamicSection(this); + } + + void create(ProcessSpace ps) { + create(ps, 0); + } + + /** + * Load/create the program segment + */ + void create(ProcessSpace ps, int offset) { + switch (p_type) { + case PT_NULL: // Null header, contains no data and can be ignored + break; + + case PT_LOAD: // A loadable segment + try { + createSegment(ps.memory, reader.rFile, p_offset, p_vaddr + offset, p_filesz, + p_memsz, (p_flags & PF_R) != 0, (p_flags & PF_W) != 0, + (p_flags & PF_X) != 0); + } catch (MemoryMapException e) { + throw new Error("Error in creating: " + this, e); + } + break; + case PT_PHDR: + case PT_NOTE: // A segment describing the location and size of auxiliary + // information + // ignore + break; + case PT_GNU_STACK: // A segment describing the permissions for the stack + // ignore + break; + case PT_TLS: // A segment describing thread local storage + // ignore for now + break; + case PT_INTERP: // A segment containing a string to invoke as interpreter + // for this file + case PT_DYNAMIC: // Segment containing dynamic linking information + case PT_SHLIB: // A reserved segment type with unspecified semantics + //case PT_PHDR: // A segment describing the ELF's header; present once + // before any loadable segments + default: + return; + //throw new Error("Segment type " + toString() + " not yet supported"); + } + } + + /** + * Create a segment + * @param memory The memory into which the segment is to be mapped. + * @param file file to read segment data from if file size != 0 + * @param offset file offset + * @param address location of segment + * @param filesize size of segment in file + * @param memsize size of segment in memory + * @param read is segment readable + * @param write is segment writable + * @param exec is segment executable + */ + public void createSegment(Memory memory, RandomAccessFile file, + long offset, int address, int filesize, int memsize, boolean read, + boolean write, boolean exec) throws MemoryMapException { + // Sanity check + if (memsize < filesize) { + throw new Error("Segment memory size (" + memsize + + ")less than file size (" + filesize + ")"); + } + // Are we mapping anything from a file? + if (filesize == 0) { + // No: map anonymously + memory.map(address, memsize, read, write, exec); + } else { + // align offset and address + int alignedAddress; + long alignedOffset; + int alignedFilesize; + if (memory.isPageAligned(address)) { + // memory and therefore offset should be aligned + alignedAddress = address; + alignedOffset = offset; + alignedFilesize = filesize; + } else { + // Address not aligned + alignedAddress = memory.truncateToPage(address); + int delta = address - alignedAddress; + // adjust offset and length too + alignedOffset = offset - delta; + alignedFilesize = filesize + delta; + } + 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); + } + } + } + + /** + * Round the give value up so that it is at the beginning of the next + * aligned region + */ + private int truncateToNextAlignment(int x) { + return ((x + p_align - 1) / p_align) * p_align; + } + + /** + * Get the end of the segment + */ + public int getEnd() { + return truncateToNextAlignment(p_vaddr + p_memsz); + } + + /** + * String representation of header + */ + public String toString() { + switch (p_type) { + case PT_NULL: + return "Null segment header (ignored)"; + case PT_LOAD: + return "Loadable segment (offset=0x" + Long.toHexString(p_offset) + + ", address=0x" + Integer.toHexString(p_vaddr) + ", file size=" + + p_filesz + ", memory size=" + p_memsz + ", permissions=" + + (((p_flags & PF_R) != 0) ? 'r' : '-') + + (((p_flags & PF_W) != 0) ? 'w' : '-') + + (((p_flags & PF_X) != 0) ? 'x' : '-') + ")"; + case PT_TLS: + return "TLS segment (offset=0x" + Long.toHexString(p_offset) + + ", address=0x" + Integer.toHexString(p_vaddr) + ", file size=" + + p_filesz + ", memory size=" + p_memsz + ", permissions=" + + (((p_flags & PF_R) != 0) ? 'r' : '-') + + (((p_flags & PF_W) != 0) ? 'w' : '-') + + (((p_flags & PF_X) != 0) ? 'x' : '-') + ")"; + case PT_NOTE: + return "Note: segment containing auxiliary information"; + case PT_INTERP: + return "Interpreter"; + case PT_DYNAMIC: + return "Dynamic link information"; + case PT_SHLIB: + return "SHLIB/Unspecified - semantics unknown"; + case PT_PHDR: + return "Program header"; + case PT_GNU_STACK: + return "GNU stack executability"; + default: + SegmentRange range = SegmentRange.fromInteger(p_type); + return range.toString() + "(0x" + Integer.toHexString(p_type) + ")"; + } + } + } +} Deleted: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java =================================================================== --- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-05-08 16:35:56 UTC (rev 105) +++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-05-08 16:38:23 UTC (rev 106) @@ -1,968 +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.os.loader.elf; - -import java.io.IOException; -import java.io.RandomAccessFile; - -import org.binarytranslator.DBT; -import org.binarytranslator.DBT_Options; -import org.binarytranslator.generic.memory.Memory; -import org.binarytranslator.generic.memory.MemoryMapException; -import org.binarytranslator.generic.os.loader.Loader; -import org.binarytranslator.generic.os.process.ProcessSpace; - -public class ELF_Loader extends Loader { - - /** - * Wrapper class used for reading the ELF file with the required endianness - */ - private ELF_BinaryReader reader; - - /** - * Field holding identity information - */ - private ELF_Identity identity; - - /** - * Header of ELF file - */ - public ELF_Header elfHeader; - - /** - * Program segment headers - */ - private ELF_ProgramSegmentHeader segmentHeaders[]; - - /** - * Debug information - * @param s string of debug information - */ - private static void report(String s) { - if (DBT_Options.debugLoader) { - System.out.print("ELF Loader:"); - System.out.println(s); - } - } - /** - * Reader for byte and multibyte values respecting endianness. - */ - private abstract static class ELF_BinaryReader { - - /** File to read from */ - protected RandomAccessFile rFile; - - /** - * Returns a new ELF_BinaryReader for the specified byte order and file. - * - * @param byteOrder - * The byte order that the file posesses. - * @param file - * The file that is to be read. - * @return - * An ELF_BinaryReader, that hides the details of the byte order. - */ - public static ELF_BinaryReader create(ELF_Identity.ByteOrder byteOrder, RandomAccessFile file) { - - if (byteOrder == ELF_Identity.ByteOrder.BigEndian) - return new NonSwappingReader(file); - else - return new ByteSwappingReader(file); - } - - /** Hide the constructor, because this class shall only be instantiated by using the factory method {@link #create(org.binarytranslator.generic.os.loader.elf.ELF_Loader.ELF_Header.ByteOrder, RandomAccessFile)}. */ - private ELF_BinaryReader(RandomAccessFile rFile) { - this.rFile = rFile; - } - - /** Seek to location from beginning of file */ - void seek(long pos) throws IOException { - rFile.seek(pos); - } - - /** Read an integer from the file. This function is supposed to hide the difference between little and big endian reads. */ - public abstract int readInt() throws IOException; - - /** Read a short from the file. This function is supposed to hide the difference between little and big endian reads. */ - public abstract short readShort() throws IOException; - - /** Reader that performs byte swaps for each int/short read. */ - private static class ByteSwappingReader extends ELF_BinaryReader { - - ByteSwappingReader(RandomAccessFile rFile) { - super(rFile); - } - - /** Byte swap a 32-bit integer */ - private static int b... [truncated message content] |
From: <mic...@us...> - 2007-05-08 16:35:57
|
Revision: 105 http://svn.sourceforge.net/pearcolator/?rev=105&view=rev Author: michael_baer Date: 2007-05-08 09:35:56 -0700 (Tue, 08 May 2007) Log Message: ----------- Fixed bugs in IntMultiply, LongMultiply and Rotate-Right-Extend (RRX) uncovered by sanity tests. 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-05-02 18:27:00 UTC (rev 104) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-05-08 16:35:56 UTC (rev 105) @@ -92,8 +92,7 @@ } /** Base class for multiply operations. */ - protected abstract static class MultiplyTemplate - extends ThreeRegistersTemplate { + protected abstract static class MultiplyTemplate extends Instruction { /** @see #updateConditionCodes() */ protected final boolean updateConditionCodes; @@ -103,13 +102,25 @@ /** @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. */ @@ -126,6 +137,21 @@ 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. */ @@ -172,7 +198,7 @@ LSR, ASR, ROR, - RRE + RRX } /** Creates an operand wrapper around a 12 bit immediate value. */ @@ -229,7 +255,7 @@ if (shift == ShiftType.ROR) { //However, if the shift type was RotateRight, then ARM meant do a RotateRightExtend by 1 - return new RegisterShiftImmediateOperand(shiftedRegister, shift, (byte)1); + return new RegisterShiftImmediateOperand(shiftedRegister, ShiftType.RRX, (byte)1); } //in all other cases, an immediate of zero denotes a shift by 32 @@ -591,7 +617,7 @@ } //this instruction variant yields an undefined result - if (DBT.VerifyAssertions) DBT._assert(Rd != 15 || !writeBack); + if (DBT.VerifyAssertions) DBT._assert(Rd != Rn || !writeBack); } /** Returns true, if this memory access shall be treated as if it had been done in user mode. */ @@ -650,7 +676,6 @@ if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); } @@ -668,7 +693,7 @@ unsigned = Utils.getBit(instr, 22); //check for instruction combinations that show undefined behaviour on ARM - if (DBT.VerifyAssertions) DBT._assert((accumulate || Rn == 0) && Rd != 15); + if (DBT.VerifyAssertions) DBT._assert(Rd != 15); } /** Long multiplication stores its result in two registers. This function gets the register which receives the high int. */ @@ -686,7 +711,6 @@ return unsigned; } - @Override public void visit(ARM_InstructionVisitor visitor) { visitor.visit(this); } Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-02 18:27:00 UTC (rev 104) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-08 16:35:56 UTC (rev 105) @@ -162,7 +162,7 @@ case ROR: return Integer.rotateRight(value, shiftAmount); - case RRE: + case RRX: if (regs.isCarrySet()) return (value >> 1) | 0x80000000; else @@ -315,7 +315,7 @@ return Integer.rotateRight(value, shiftAmount); } - case RRE: + case RRX: shifterCarryOut = (value & 0x1) != 0; if (regs.isCarrySet()) Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-02 18:27:00 UTC (rev 104) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-08 16:35:56 UTC (rev 105) @@ -265,7 +265,7 @@ translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); return resultRegister; - case RRE: + case RRX: /* * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; * else return resultRegister >>> 1; @@ -504,7 +504,7 @@ shiftAmount); return resultRegister; - case RRE: + case RRX: /* * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; * else return resultRegister >>> 1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-02 18:26:59
|
Revision: 104 http://svn.sourceforge.net/pearcolator/?rev=104&view=rev Author: michael_baer Date: 2007-05-02 11:27:00 -0700 (Wed, 02 May 2007) Log Message: ----------- ... and removed double AT_BASE entry. Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-05-02 18:26:12 UTC (rev 103) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-05-02 18:27:00 UTC (rev 104) @@ -58,10 +58,6 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, 0x20, LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0x6, LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x40000000, - /*LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, 0x8034, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, 0x20, - LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0x6,*/ - LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x00000000, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, 0x82b4, LinuxStackInitializer.AuxiliaryVectorType.AT_UID, 0x0, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-02 18:26:11
|
Revision: 103 http://svn.sourceforge.net/pearcolator/?rev=103&view=rev Author: michael_baer Date: 2007-05-02 11:26:12 -0700 (Wed, 02 May 2007) Log Message: ----------- Added AT_NULL delimiter to aux vector Modified Paths: -------------- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java =================================================================== --- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-05-02 18:24:31 UTC (rev 102) +++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-05-02 18:26:12 UTC (rev 103) @@ -58,13 +58,18 @@ LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, 0x20, LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0x6, LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x40000000, + /*LinuxStackInitializer.AuxiliaryVectorType.AT_PHDR, 0x8034, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHENT, 0x20, + LinuxStackInitializer.AuxiliaryVectorType.AT_PHNUM, 0x6,*/ + LinuxStackInitializer.AuxiliaryVectorType.AT_BASE, 0x00000000, LinuxStackInitializer.AuxiliaryVectorType.AT_FLAGS, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_ENTRY, 0x82b4, LinuxStackInitializer.AuxiliaryVectorType.AT_UID, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_EUID, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_GID, 0x0, LinuxStackInitializer.AuxiliaryVectorType.AT_EGID, 0x0, - LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, 0xbffffecd }; + LinuxStackInitializer.AuxiliaryVectorType.AT_PLATFORM, 0xbffffecd, + LinuxStackInitializer.AuxiliaryVectorType.AT_NULL, 0x0 }; registers.set(ARM_Registers.SP, LinuxStackInitializer.stackInit(memory, STACK_TOP, getEnvironmentVariables(), auxVector)); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-02 18:24:32
|
Revision: 102 http://svn.sourceforge.net/pearcolator/?rev=102&view=rev Author: michael_baer Date: 2007-05-02 11:24:31 -0700 (Wed, 02 May 2007) Log Message: ----------- - intermediate commit, still no working translator Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-02 18:23:53 UTC (rev 101) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-05-02 18:24:31 UTC (rev 102) @@ -5,6 +5,8 @@ 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; import org.binarytranslator.generic.decoder.DecoderUtils; import org.binarytranslator.generic.decoder.Laziness; import org.jikesrvm.classloader.VM_Atom; @@ -47,8 +49,8 @@ static { psTref = VM_TypeReference.findOrCreate(ARM_ProcessSpace.class); - - registersFref = VM_MemberReference + + registersFref = VM_FieldReference .findOrCreate( psTref, VM_Atom.findOrCreateAsciiAtom("registers"), @@ -82,10 +84,52 @@ protected Laziness createInitialLaziness() { return new ARM_Laziness(); } + + private VM_TypeReference OperatingMode_TypeRef = null; + + /** + * Returns a register operand for values of type <code>OperatingMode</code>. + * @return + */ + public OPT_RegisterOperand getTempOperatingMode() { + if (OperatingMode_TypeRef == null) { + OperatingMode_TypeRef = VM_TypeReference.findOrCreate(ARM_Registers.OperatingMode.class); + } + + return gc.temps.makeTemp(OperatingMode_TypeRef); + } + + /** + * Returns an register operand that is equivalent to the given operating mode. + */ + public OPT_RegisterOperand getTempOperatingMode(OperatingMode mode) { + //We are going to insert a GETFIELD, which will grab the appropriate OperatingMode static instance from + //the OperatingMode class. + OPT_RegisterOperand result = getTempOperatingMode(); + + //the type reference should have been initialized by the previous call to getTempOperatingMode. + //For the sake of defensive programming, we are doing it again here... + if (OperatingMode_TypeRef == null) { + OperatingMode_TypeRef = VM_TypeReference.findOrCreate(ARM_Registers.OperatingMode.class); + } - @Override - protected void fillAllRegisters() { + //grab the field reference to the corresponding field + VM_FieldReference requestedMode_FieldReference = VM_FieldReference.findOrCreate(OperatingMode_TypeRef, VM_Atom.findOrCreateAsciiAtom(mode.name()), VM_Atom.findOrCreateAsciiAtom("Lorg/binarytranslator/arch/arm/os/process/ARM_Registers/OperatingMode;")).asFieldReference(); + //Finally, use a getfield to grab the (static) member field + appendInstructionToCurrentBlock(GetField.create(GETFIELD, result, + null, new OPT_AddressConstantOperand(requestedMode_FieldReference + .peekResolvedField().getOffset()), new OPT_LocationOperand( + requestedMode_FieldReference), new OPT_TrueGuardOperand())); + + return result; + } + + /** + * Returns a RegisterOperand that contains a reference to the currently used ARM_Registers instance. + * Use this reference when calling functions on ARM_Registers. + */ + public OPT_RegisterOperand getArmRegistersReference() { OPT_RegisterOperand ps_registersOp; if (ps_registers != null) { @@ -99,7 +143,33 @@ else { ps_registersOp = new OPT_RegisterOperand(ps_registers, registersTref); } + + return ps_registersOp; + } + + /** + * Writes all current flag values back to their respective registers + */ + public void spillAllFlags(Laziness lazyState) { + + //first resolve the current lazy state (i.e. calculate the values of registers that are not yet resolved) + resolveLaziness(lazyState); + + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + + public void fillAllFlags() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + @Override + protected void fillAllRegisters() { + + //get an operand that contains a reference to the current ps.registers field. + OPT_RegisterOperand ps_registersOp = getArmRegistersReference(); + // Get the array of general purpose registers OPT_RegisterOperand ps_registers_regsOp; if (ps_registers_regs == null) { Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-02 18:23:53 UTC (rev 101) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-05-02 18:24:31 UTC (rev 102) @@ -35,15 +35,41 @@ this.ps = ps; this.arm2ir = arm2ir; } + + private OPT_Instruction createCallToRegisters(String methodName, String signature, int numParameters) { + VM_TypeReference RegistersType = VM_TypeReference + .findOrCreate(ARM_Registers.class); + VM_MethodReference methodRef = VM_MemberReference + .findOrCreate(RegistersType, + VM_Atom.findOrCreateAsciiAtom(methodName), + VM_Atom.findOrCreateAsciiAtom(signature)).asMethodReference(); + + VM_Method method = methodRef.resolve(); + + OPT_Instruction call = Call.create(CALL, null, null, null, null, numParameters + 1); + OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(methodRef, method); + + OPT_RegisterOperand thisOperand = arm2ir.getArmRegistersReference(); + + Call.setParam(call, 0, thisOperand); + Call.setGuard(call, new OPT_TrueGuardOperand()); + Call.setMethod(call, methOp); + Call.setAddress(call, new OPT_AddressConstantOperand(method + .getOffset())); + + return call; + } + + private abstract static class ResolvedOperand { protected OPT_Operand value; protected ARM_Translator translator; - public static ResolvedOperand resolveWithShifterCarryOut( + public static ResolvedOperand resolveAndStoreShifterCarryOutToCarry( ARM_Translator translator, OperandWrapper operand) { throw new RuntimeException("Not yet implemented"); } @@ -59,8 +85,6 @@ return value; } - public abstract OPT_Operand getShifterCarryOut(); - protected OPT_RegisterOperand getTempInt() { return translator.arm2ir.getTempInt(0); } @@ -79,11 +103,6 @@ _resolve(operand); } - public OPT_Operand getShifterCarryOut() { - throw new RuntimeException( - "This class does not provide a shifter carry out value."); - } - private void _resolve(OperandWrapper operand) { switch (operand.getType()) { @@ -159,8 +178,9 @@ switch (operand.getShiftType()) { case ASR: /* - * if (shiftAmout >= 32) { value = shiftedOperand >> 31; else value = - * shiftedOperand >> shiftAmount; + * if (shiftAmout >= 32) { value = shiftedOperand >> 31; shiftedOperand >> 1; } + * else + * value = shiftedOperand >> shiftAmount; */ ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); elseBlock = translator.arm2ir.createBlockAfterCurrent(); @@ -172,16 +192,20 @@ OPT_BranchProfileOperand.unlikely())); currentBlock.insertOut(ifBlock); + //shift translator.arm2ir.setCurrentBlock(ifBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_SHR, resultRegister, shiftedOperand, new OPT_IntConstantOperand(31))); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, + new OPT_IntConstantOperand(1))); translator.arm2ir.setCurrentBlock(elseBlock); translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_SHR, resultRegister, shiftedOperand, shiftAmount)); - return resultRegister; + break; case LSL: /* @@ -206,7 +230,7 @@ translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_SHL, resultRegister, shiftedOperand, shiftAmount)); - return resultRegister; + break; case LSR: @@ -232,7 +256,7 @@ translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( INT_USHR, resultRegister, shiftedOperand, shiftAmount)); - return resultRegister; + break; case ROR: /* @@ -244,35 +268,293 @@ case RRE: /* * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; - * else return resultRegister >> 1; + * else return resultRegister >>> 1; */ - // resultRegister = resultRegister >> 1 + // resultRegister = resultRegister >>> 1 translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + //conditionally, set resultRegister = resultRegister | 0x80000000; ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); ifBlock.insertOut(nextBlock); translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), translator.arm2ir.getCarryFlag(), + new OPT_IntConstantOperand(1), OPT_ConditionOperand + .EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_OR_ACC, resultRegister, new OPT_IntConstantOperand(0x80000000))); + + break; + + default: + throw new RuntimeException("Unexpected shift type: " + + operand.getShiftType()); + } + + translator.arm2ir.setCurrentBlock(nextBlock); + return resultRegister; + } + } + + + + + + + private static class ResolvedOperand_WithShifterCarryOut extends + ResolvedOperand { + + private ResolvedOperand_WithShifterCarryOut(ARM_Translator translator, + OperandWrapper operand) { + this.translator = translator; + _resolve(operand); + } + private void _resolve(OperandWrapper operand) { + + switch (operand.getType()) { + case Immediate: + value = new OPT_IntConstantOperand(operand.getImmediate()); + + if (operand.getShiftAmount() != 0) { + OPT_RegisterOperand carryFlag = translator.arm2ir.getCarryFlag(); + OPT_Operand shifterCarryOut = new OPT_IntConstantOperand(((operand.getImmediate() & 0x80000000) != 0) ? 1 : 0); + + //otherwise there is no shifter carry out + translator.arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, carryFlag, shifterCarryOut)); + } + return; + + case Register: + //in this case, there is no special shifter carry out (i.e. it equals the carry flag). + int reg = operand.getRegister(); + + if (reg == 15) { + // mind the ARM pc offset + value = new OPT_IntConstantOperand(translator.pc + 8); + return; + } + + value = translator.arm2ir.getRegister(reg); + return; + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + value = resolveShift(operand); + return; + + case PcRelative: + throw new RuntimeException("This operand type does not produce a shifter carry out."); + + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand.getType()); + } + } + + /** + * Translates a bit test, where bit <code>shifterResultBit</code> is tested within <code>value</code> and the result + * is put into the carry flag If <code>shifterResultBit</code> is less than 0, the carry is not changed. + * + */ + private void translateShifterCarryOut(OPT_Operand value, OPT_Operand shifterResultBit) { + + OPT_RegisterOperand carryFlag = translator.arm2ir.getCarryFlag(); + + + OPT_RegisterOperand tmp = getTempInt(); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, + tmp, shifterResultBit, new OPT_IntConstantOperand(1))); + translator.arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, carryFlag, value, tmp.copyRO(), OPT_ConditionOperand.BIT_TEST(), new OPT_BranchProfileOperand())); + } + + /** + * If the given OperandWrapper involves shifting a register, then this + * function will decoder the shift and set the result of the barrel shifter + * accordingly. + */ + private final OPT_Operand resolveShift(OperandWrapper operand) { + if (DBT.VerifyAssertions) + DBT + ._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister + || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); + + // consider the "usual" ARM program counter offset + OPT_Operand shiftedOperand; + if (operand.getRegister() == 15) + shiftedOperand = new OPT_IntConstantOperand(translator.pc + 8); + else + shiftedOperand = translator.arm2ir.getRegister(operand.getRegister()); + + OPT_Operand shiftAmount; + + if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) { + // the amount of shift is a constant + shiftAmount = new OPT_IntConstantOperand(operand.getShiftAmount()); + } else { + // the amount of shifting is determined by a register + shiftAmount = translator.arm2ir.getRegister(operand + .getShiftingRegister()); + } + + OPT_BasicBlock currentBlock = translator.arm2ir.getCurrentBlock(); + OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); + + OPT_BasicBlock ifBlock; + OPT_BasicBlock elseBlock; + + OPT_RegisterOperand resultRegister = getTempInt(); + + switch (operand.getShiftType()) { + case ASR: + /* + * if (shiftAmout >= 32) { value = shiftedOperand >> 31; shiftedOperand >> 1; } + * else + * value = shiftedOperand >> shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + ifBlock.insertOut(nextBlock); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( INT_IFCMP, getTempValidation(), shiftAmount, new OPT_IntConstantOperand(32), OPT_ConditionOperand .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + new OPT_BranchProfileOperand())); + currentBlock.insertOut(ifBlock); + + //shift twice to simulate arithmetic shift-right by 32 + //circumvents java doing (shiftAmount MOD 32). + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, + new OPT_IntConstantOperand(31))); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, + new OPT_IntConstantOperand(1))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, shiftAmount)); + translateShifterCarryOut(resultRegister, shiftAmount); + + break; + + case LSL: + /* + * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand << + * shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), OPT_BranchProfileOperand.unlikely())); currentBlock.insertOut(ifBlock); translator.arm2ir.setCurrentBlock(ifBlock); translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + + break; + + case LSR: + + /* + * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand >>> + * shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + + break; + + case ROR: + /* + * return Integer.rotateRight(value, shiftAmount); + */ + translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, + shiftAmount); + return resultRegister; + + case RRE: + /* + * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; + * else return resultRegister >>> 1; + */ + + // resultRegister = resultRegister >>> 1 + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), translator.arm2ir.getCarryFlag(), + new OPT_IntConstantOperand(1), OPT_ConditionOperand + .EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( INT_AND_ACC, resultRegister, new OPT_IntConstantOperand( 0x80000000))); - return resultRegister; + break; default: throw new RuntimeException("Unexpected shift type: " + operand.getShiftType()); } + + translator.arm2ir.setCurrentBlock(nextBlock); + return resultRegister; } } + + + + + + + + + + + + + + + + } /** All ARM interpreter instructions implement this interface. */ @@ -298,69 +580,160 @@ } public void translate() { - throw new RuntimeException("Not yet implemented"); - } - - public Condition getCondition() { - return conditionalInstruction.getCondition(); - } - - /** Return true if the condition required by the conditional instruction is fulfilled, false otherwise.*/ - private boolean isConditionTrue() { + //conditionals are implemented easily: if the condition does not hold, then just + //jump to the block following the conditional instruction + OPT_BasicBlock nextInstruction = arm2ir.getNextBlock(); + arm2ir.getCurrentBlock().insertOut(nextInstruction); + + OPT_BasicBlock currentInstruction = arm2ir.createBlockAfterCurrent(); + switch (conditionalInstruction.getCondition()) { case AL: throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator."); case CC: - return !regs.isCarrySet(); + //return !regs.isCarrySet(); + translateCondition(nextInstruction, arm2ir.getCarryFlag(), OPT_ConditionOperand.NOT_EQUAL()); + break; case CS: - return regs.isCarrySet(); + //return regs.isCarrySet(); + translateCondition(nextInstruction, arm2ir.getCarryFlag(), OPT_ConditionOperand.EQUAL()); + break; case EQ: - return regs.isZeroSet(); + //return regs.isZeroSet(); + translateCondition(nextInstruction, arm2ir.getZeroFlag(), OPT_ConditionOperand.EQUAL()); + break; case GE: - return regs.isNegativeSet() == regs.isOverflowSet(); + //return regs.isNegativeSet() == regs.isOverflowSet(); + translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL(), arm2ir.getOverflowFlag()); + break; case GT: - return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); + translateCondition_GT(nextInstruction); + break; case HI: - return regs.isCarrySet() && !regs.isZeroSet(); + translateCondition_HI(nextInstruction); + break; case LE: - return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); + translateCondition_LE(nextInstruction); + break; case LS: - return !regs.isCarrySet() || regs.isZeroSet(); + translateCondition_LS(nextInstruction); + break; case LT: - return regs.isNegativeSet() != regs.isOverflowSet(); + //return regs.isNegativeSet() != regs.isOverflowSet(); + translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.getOverflowFlag()); + break; case MI: - return regs.isNegativeSet(); + //return regs.isNegativeSet(); + translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL()); + break; case NE: - return !regs.isZeroSet(); + //return !regs.isZeroSet(); + translateCondition(nextInstruction, arm2ir.getZeroFlag(), OPT_ConditionOperand.NOT_EQUAL()); + break; case NV: - return false; + //never execute this instruction + translateCondition(nextInstruction, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL()); + break; case PL: - return !regs.isNegativeSet(); + //return !regs.isNegativeSet(); + translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL()); + break; case VC: - return !regs.isOverflowSet(); + //return !regs.isOverflowSet(); + translateCondition(nextInstruction, arm2ir.getOverflowFlag(), OPT_ConditionOperand.NOT_EQUAL()); + break; case VS: - return regs.isOverflowSet(); + //return regs.isOverflowSet(); + translateCondition(nextInstruction, arm2ir.getOverflowFlag(), OPT_ConditionOperand.EQUAL()); + break; default: throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); } + + arm2ir.setCurrentBlock(currentInstruction); } + private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand operand, OPT_ConditionOperand condition) { + translateCondition(nextInstruction, operand, condition, new OPT_IntConstantOperand(1)); + } + + private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand lhs, OPT_ConditionOperand condition, OPT_Operand rhs) { + + condition = condition.flipCode(); + arm2ir.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(9), lhs, rhs, condition, nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + } + + private void translateCondition_HI(OPT_BasicBlock nextInstruction) { + //return regs.isCarrySet() && !regs.isZeroSet(); + OPT_Operand carry = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_RegisterOperand result = arm2ir.getTempValidation(9); + + arm2ir.appendInstructionToCurrentBlock(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.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + } + + private void translateCondition_LS(OPT_BasicBlock nextInstruction) { + //return !regs.isCarrySet() || regs.isZeroSet(); + OPT_Operand carry = arm2ir.getCarryFlag(); + OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_RegisterOperand result = arm2ir.getTempValidation(9); + + arm2ir.appendInstructionToCurrentBlock(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.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + } + + private void translateCondition_GT(OPT_BasicBlock nextInstruction) { + //return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); + OPT_Operand negative = arm2ir.getNegativeFlag(); + OPT_Operand overflow = arm2ir.getOverflowFlag(); + OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_RegisterOperand result = arm2ir.getTempValidation(9); + + arm2ir.appendInstructionToCurrentBlock(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.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + } + + private void translateCondition_LE(OPT_BasicBlock nextInstruction) { + //return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); + OPT_Operand negative = arm2ir.getNegativeFlag(); + OPT_Operand overflow = arm2ir.getOverflowFlag(); + OPT_Operand zero = arm2ir.getCarryFlag(); + OPT_RegisterOperand result = arm2ir.getTempValidation(9); + + arm2ir.appendInstructionToCurrentBlock(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.appendInstructionToCurrentBlock(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(8), result, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand())); + } + + + public Condition getCondition() { + return conditionalInstruction.getCondition(); + } + @Override public String toString() { return conditionalInstruction.toString(); @@ -390,81 +763,102 @@ return ResolvedOperand.resolve(ARM_Translator.this, operand2); } - /** Returns teh register into which the result of a data processing operation shall be stored. */ + /** Returns the register into which the result of a data processing operation shall be stored. */ protected OPT_RegisterOperand getResultRegister() { return arm2ir.getRegister(Rd); - } - - /** Sets the result of an operation. */ - protected void setResult(OPT_RegisterOperand result) { - if (Rd == 15) { - //TODO: This is a jump, handle it accordingly - throw new RuntimeException("Not yet implemented"); - } - } + } public abstract void translate(); /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ - protected final void setFlagsForAdd(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setAddResult(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { if (updateConditionCodes) { if (Rd != 15) { - - //set the carry flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.CARRY_FROM_ADD(), new OPT_BranchProfileOperand())); - - //set the overflow flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); - - //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); - - //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + setAddFlags(result, lhs, rhs); } else { - //TODO: Implement this - regs.restoreSPSR2CPSR(); - throw new RuntimeException("Not yet implemented"); + OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); + arm2ir.appendInstructionToCurrentBlock(s); } } + + if (Rd == 15) + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } + + /** + * Sets the flags according to the result of an add operation. + * @param result + * The result of the add operation. + * @param lhs + * The left-hand-side operator. + * @param rhs + * The add's right-hand-side operator. + */ + protected void setAddFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + //set the carry flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.CARRY_FROM_ADD(), new OPT_BranchProfileOperand())); + + //set the overflow flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, 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>.*/ - protected final void setFlagsForSub(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + protected final void setSubResult(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { if (updateConditionCodes) { if (Rd != 15) { - //set the carry flag to not(Borrow) - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); - arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); - - //set the overflow flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); - - //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); - - //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + setSubFlags(result, lhs, rhs); } else { - //TODO: Implement this - regs.restoreSPSR2CPSR(); - throw new RuntimeException("Not yet implemented"); + OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); + arm2ir.appendInstructionToCurrentBlock(s); } } + + if (Rd == 15) + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } + /** + * Sets the processor flags according to the result of a sub operation. + * @param result + * The result of the sub operation. + * @param lhs + * The sub's left-hand-side operator. + * @param rhs + * The sub's right-hand-side operator. + */ + protected void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + //set the carry flag to not(Borrow) + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); + + //set the overflow flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } + public int getSuccessor(int pc) { if (Rd != 15) return pc + 4; @@ -475,48 +869,57 @@ private abstract class DataProcessing_Logical extends DataProcessing { - /** Most data processing instructions may set the carry flag according to the barrel shifter's carry - * out value. The (supposed) value of the barrel shifter is stored within this variable. */ - protected OPT_Operand shifterCarryOut; protected DataProcessing_Logical(int instr) { super(instr); } - /** - * Returns the value of the rhs-operand of the data processing instruction. - * This function also retrieves a value for the shifter carry out, which may be set when resolving - * the 2nd operand.*/ + /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift + * and set the result of the barrel shifter accordingly. However, the shifter carry out is only calculated, when + * the condition codes are to be modified by this function (because otherwise it won't be used anyway).*/ protected OPT_Operand resolveOperand2() { - ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveWithShifterCarryOut(ARM_Translator.this, operand2); - shifterCarryOut = resolvedOperand2.getShifterCarryOut(); - return resolvedOperand2.getValue(); + + if (updateConditionCodes) { + ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveAndStoreShifterCarryOutToCarry(ARM_Translator.this, operand2); + return resolvedOperand2.getValue(); + } + else { + return super.resolveOperand2(); + } } /** Sets the condition field for logical operations. */ - protected final void setFlagsForLogicalOperator(OPT_Operand result) { + protected final void setLogicalResult(OPT_Operand result) { if (updateConditionCodes) { if (Rd != 15) { - //TODO: Find an equivalent for BOOLEAN_MOVE - arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), shifterCarryOut)); - arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); - - //set the negative flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); - - //set the zero flag - arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( - BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); - + setLogicalFlags(result); } else { - //TODO: Implement this - regs.restoreSPSR2CPSR(); - throw new RuntimeException("Not yet implemented"); + OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0); + arm2ir.appendInstructionToCurrentBlock(s); } } + + if (Rd == 15) + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, result); } + + /** + * Sets the flags according to the result of a logical operation. + * @param result + * The result of the logical operation + */ + protected void setLogicalFlags(OPT_Operand result) { + //the shifter carry out has already been set during the resolve-phase + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } } /** Binary and. <code>Rd = op1 & op2 </code>.*/ @@ -532,8 +935,7 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, resolveOperand1(), resolveOperand2())); - setFlagsForLogicalOperator(result); - setResult(result); + setLogicalResult(result); } } @@ -550,8 +952,7 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_XOR, result, resolveOperand1(), resolveOperand2())); - setFlagsForLogicalOperator(result); - setResult(result); + setLogicalResult(result); } } @@ -570,8 +971,7 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); - setFlagsForAdd(result, operand1, operand2); - setResult(result); + setAddResult(result, operand1, operand2); } } @@ -590,8 +990,7 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); - setFlagsForSub(result, operand1, operand2); - setResult(result); + setSubResult(result, operand1, operand2); } } @@ -610,8 +1009,7 @@ arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand2, operand1)); - setFlagsForSub(result, operand2, operand1); - setResult(result); + setSubResult(result, operand2, operand1); } } @@ -732,7 +1130,7 @@ public void translate() { OPT_RegisterOperand result = arm2ir.getTempInt(0); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, resolveOperand1(), resolveOperand2())); - setFlagsForLogicalOperator(result); + setLogicalFlags(result); } } @@ -748,7 +1146,7 @@ public void translate() { OPT_RegisterOperand result = arm2ir.getTempInt(0); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_XOR, result, resolveOperand1(), resolveOperand2())); - setFlagsForLogicalOperator(result); + setLogicalFlags(result); } } @@ -766,7 +1164,7 @@ OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = arm2ir.getTempInt(0); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); - setFlagsForSub(result, operand1, operand2); + setSubFlags(result, operand1, operand2); } } @@ -784,7 +1182,7 @@ OPT_Operand operand2 = resolveOperand2(); OPT_RegisterOperand result = arm2ir.getTempInt(0); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); - setFlagsForAdd(result, operand1, operand2); + setAddFlags(result, operand1, operand2); } } @@ -802,8 +1200,7 @@ OPT_RegisterOperand result = getResultRegister(); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_OR, result, operand1, operand2)); - setFlagsForLogicalOperator(result); - setResult(result); + setLogicalResult(result); } } @@ -820,9 +1217,7 @@ OPT_RegisterOperand result = getResultRegister(); arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand)); - - setResult(result); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -844,13 +1239,12 @@ OPT_RegisterOperand tmp = arm2ir.getTempInt(0); arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_NOT, tmp, operand2)); arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, operand1, tmp)); - setFlagsForLogicalOperator(result); - setResult(result); + setLogicalResult(result); } } /** Move and negate. Moves an integer between two registers, negating it on the way. - * <code>Rd = -op2</code>.*/ + * <code>Rd = ~op2</code>.*/ private final class DataProcessing_Mvn extends DataProcessing_Logical { protected DataProcessing_Mvn(int instr) { @@ -861,7 +1255,7 @@ public void translate() { OPT_RegisterOperand result = getResultRegister(); arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_NOT, result, resolveOperand2())); - setFlagsForLogicalOperator(result); + setLogicalResult(result); } } @@ -875,7 +1269,7 @@ @Override public void translate() { - + //Call Integer.numberOfLeadingZeros() to obtain the result of this operation OPT_RegisterOperand result = getResultRegister(); VM_TypeReference IntegerType = VM_TypeReference @@ -899,7 +1293,6 @@ .getOffset())); arm2ir.appendInstructionToCurrentBlock(s); - setResult(result); } } @@ -1144,7 +1537,7 @@ arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); } - arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc+8 + getOffset())); + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc + 8 + getOffset())); } public int getSuccessor(int pc) { @@ -1161,43 +1554,51 @@ } public void translate() { - //TODO: Implement - throw new RuntimeException("Not yet implemented"); - /* //remember the previous address - int previousAddress = regs.get(ARM_Registers.PC) + 8; + int previousAddress = pc + 8; - //are we supposed to jump to thumb (thumb=true) or ARM32 (thumb=false)? - boolean thumb; + //the address of the instruction we're jumping to + OPT_Operand targetAddress; - //the address of the instruction we're jumping to - int targetAddress; + //1 if we're supposed to switch to thumb mode after this call, 0 otherwise + OPT_Operand enableThumb; switch (target.getType()) { case PcRelative: - targetAddress = previousAddress + target.getOffset(); - thumb = true; + targetAddress = new OPT_IntConstantOperand(previousAddress + target.getOffset()); + + //Call regs.setThumbMode(true) to enable thumb execution + enableThumb = new OPT_IntConstantOperand(1); break; case Register: - targetAddress = regs.get(target.getRegister()); - thumb = (targetAddress & 0x1) != 0; - targetAddress = targetAddress & 0xFFFFFFFE; + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, tmp, arm2ir.getRegister(target.getRegister()), new OPT_IntConstantOperand(0xFFFFFFFE) )); + targetAddress = tmp; + + OPT_RegisterOperand tmp2 = arm2ir.getTempInt(1); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, tmp2, arm2ir.getRegister(target.getRegister()), new OPT_IntConstantOperand(0x1) )); + enableThumb = tmp2; break; default: throw new RuntimeException("Unexpected Operand type: " + target.getType()); } - - //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);*/ + + //write the next address into the link register, if requested so. + if (link) { + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(previousAddress - 4))); + } + + //set the correct processor mode (thumb or not) + OPT_Instruction s = createCallToRegisters("setThumbMode", "(Z)V", 1); + Call.setParam(s, 1, enableThumb); + arm2ir.appendInstructionToCurrentBlock(s); + + //jump to the target address + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, targetAddress); } public int getSuccessor(int pc) { @@ -1322,15 +1723,22 @@ public void translate() { - throw new RuntimeException("Not yet implemented"); - /* + //write the current flags back to the registers class + arm2ir.spillAllFlags(lazy); + + OPT_RegisterOperand psrValue = arm2ir.getRegister(Rd); + OPT_Instruction call; + //do we have to transfer the saved or the current PSR? if (transferSavedPSR) { - regs.set(Rd, regs.getSPSR()); - } + call = createCallToRegisters("getSPSR", "()V", 0); + } else { - regs.set(Rd, regs.getCPSR()); - }*/ + call = createCallToRegisters("getCPSR", "()V", 0); + } + + Call.setResult(call, psrValue); + arm2ir.appendInstructionToCurrentBlock(call); } public int getSuccessor(int pc) { @@ -1350,8 +1758,13 @@ public void translate() { //TODO: implement - throw new RuntimeException("Not yet implemented"); + //throw new RuntimeException("Not yet implemented"); + //this variable is going to receive the new psr, which we will set + OPT_Operand new_psr = ResolvedOperand.resolve(ARM_Translator.this, sourceOperand); + + + /* //this variable is going to receive the new psr, which we will set int new_psr = ResolvedOperand.resolve(regs, sourceOperand); @@ -1472,13 +1885,21 @@ public void translate() { //should we simulate a user-mode memory access? If yes, store the current mode and fake a switch //to user mode. - OperatingMode previousMode = null; + + //stores the current operating mode + OPT_RegisterOperand currentOperatingMode = null; + if (forceUserMode) { - //TODO: implement - previousMode = ps.registers.getOperatingMode(); - ps.registers.setOperatingModeWithoutRegisterLayout(ARM_Registers.OperatingMode.USR); + OPT_Instruction call_getOperatingMode = createCallToRegisters("getOperatingMode", "()A", 0); + currentOperatingMode = arm2ir.getTempOperatingMode(); - throw new RuntimeException("Not yet implemented"); + Call.setResult(call_getOperatingMode, currentOperatingMode); + arm2ir.appendInstructionToCurrentBlock(call_getOperatingMode); + + OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1); + Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, arm2ir.getTempOperatingMode(OperatingMode.USR)); + + arm2ir.appendInstructionToCurrentBlock(call_setOperatingModeWithoutRegisterLayout); } //get the address of the memory, that we're supposed access @@ -1546,9 +1967,9 @@ //if we were writing in user mode, then switch back to our previous operating mode if (forceUserMode) { - //TODO: implement - ps.registers.setOperatingModeWithoutRegisterLayout(previousMode); - throw new RuntimeException("Not yet implemented"); + OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1); + Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, currentOperatingMode); + arm2ir.appendInstructionToCurrentBlock(call_setOperatingModeWithoutRegisterLayout); } //should the memory address, which we accessed, be written back into a register? @@ -1562,7 +1983,6 @@ else { //add the offset to the base address and write the result back into Rn OPT_Operand resolvedOffset = resolveOffset(); - arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, writeBackTarget, address, resolvedOffset)); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-05-02 18:23:53
|
Revision: 101 http://svn.sourceforge.net/pearcolator/?rev=101&view=rev Author: michael_baer Date: 2007-05-02 11:23:53 -0700 (Wed, 02 May 2007) Log Message: ----------- - Fixed bug in RRE - Reduced evaluation of barrel-shifter even further - Small javadoc correction Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-04-30 18:00:12 UTC (rev 100) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-05-02 18:23:53 UTC (rev 101) @@ -166,7 +166,7 @@ if (regs.isCarrySet()) return (value >> 1) | 0x80000000; else - return value >> 1; + return value >>> 1; default: throw new RuntimeException("Unexpected shift type: " @@ -321,7 +321,7 @@ if (regs.isCarrySet()) return (value >> 1) | 0x80000000; else - return value >> 1; + return value >>> 1; default: throw new RuntimeException("Unexpected shift type: " @@ -509,11 +509,18 @@ } /** If the given OperandWrapper involves shifting a register, then this function will decoder the shift - * and set the result of the barrel shifter accordingly. */ + * and set the result of the barrel shifter accordingly. However, the shifter carry out is only calculated, when + * the condition codes are to be modified by this function (because otherwise it won't be used anyway).*/ protected int resolveOperand2() { - ResolvedOperand operand = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); - shifterCarryOut = operand.getShifterCarryOut(); - return operand.getValue(); + + if (updateConditionCodes) { + ResolvedOperand operand = ResolvedOperand.resolveWithShifterCarryOut(regs, operand2); + shifterCarryOut = operand.getShifterCarryOut(); + return operand.getValue(); + } + else { + return super.resolveOperand2(); + } } /** Sets the condition field for logical operations. */ @@ -801,7 +808,7 @@ } /** Move and negate. Moves an integer between two registers, negating it on the way. - * <code>Rd = -op2</code>.*/ + * <code>Rd = ~op2</code>.*/ private final class DataProcessing_Mvn extends DataProcessing_Logical { protected DataProcessing_Mvn(int instr) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mic...@us...> - 2007-04-30 18:00:11
|
Revision: 100 http://svn.sourceforge.net/pearcolator/?rev=100&view=rev Author: michael_baer Date: 2007-04-30 11:00:12 -0700 (Mon, 30 Apr 2007) Log Message: ----------- - Initial version of an ARM translator Modified Paths: -------------- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java src/org/binarytranslator/arch/arm/os/process/ARM_Registers.java Added Paths: ----------- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-04-30 17:59:37 UTC (rev 99) +++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-04-30 18:00:12 UTC (rev 100) @@ -10,6 +10,8 @@ import org.jikesrvm.classloader.VM_Atom; import org.jikesrvm.classloader.VM_FieldReference; 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.ir.*; @@ -133,6 +135,27 @@ regUsed[r] = true; return new OPT_RegisterOperand(regMap[r], VM_TypeReference.Int); } + + public OPT_RegisterOperand getCarryFlag() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + + public OPT_RegisterOperand getZeroFlag() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + + public OPT_RegisterOperand getNegativeFlag() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + + public OPT_RegisterOperand getOverflowFlag() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + } + @Override protected OPT_Register[] getUnusedRegisters() { @@ -183,4 +206,41 @@ //ARM_InstructionDecoder.translateInstruction(this, // (ARM_ProcessSpace) ps, (ARM_Laziness) lazy, pc); } + + /** + * Adds code to the current block that will rotate <code>rotatedOperand</code> by + * <code>rotation</code> and stores the rotated integer into <code>result</code>. + * @param result + * The register into which the rotated value is stored. + * @param rotatedOperand + * The operand which is to be rotated. + * @param rotation + * The amount of rotation that is to be applied to the operand. + */ + public void appendRotateRight(OPT_RegisterOperand result, OPT_Operand rotatedOperand, OPT_Operand rotation) { + VM_TypeReference IntegerType = VM_TypeReference + .findOrCreate(Integer.class); + + VM_MethodReference rotateRightMethodRef = VM_MemberReference + .findOrCreate(IntegerType, + VM_Atom.findOrCreateAsciiAtom("rotateRight"), + VM_Atom.findOrCreateAsciiAtom("(II)I")).asMethodReference(); + + VM_Method rotateRightMethod = rotateRightMethodRef.resolve(); + + OPT_Instruction s = Call.create(CALL, null, null, null, null, 2); + OPT_MethodOperand methOp = OPT_MethodOperand + .STATIC(rotateRightMethod); + + Call.setParam(s, 1, rotatedOperand); + Call.setParam(s, 2, rotation); + Call.setResult(s, result); + Call.setGuard(s, new OPT_TrueGuardOperand()); + Call.setMethod(s, methOp); + Call.setAddress(s, new OPT_AddressConstantOperand(rotateRightMethod + .getOffset())); + + appendInstructionToCurrentBlock(s); + } + } Added: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java =================================================================== --- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java (rev 0) +++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-04-30 18:00:12 UTC (rev 100) @@ -0,0 +1,1730 @@ +package org.binarytranslator.arch.arm.decoder; + +import org.binarytranslator.DBT; +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; +import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition; +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.jikesrvm.classloader.VM_Atom; +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.ir.*; + +/** + */ +public class ARM_Translator implements OPT_Operators { + + /** The process space that we're interpreting.*/ + protected final ARM_ProcessSpace ps; + + protected final ARM2IR arm2ir; + + protected ARM_Laziness lazy; + + protected int pc; + + /** A "quick" pointer to the ARM registers within the process space*/ + protected final ARM_Registers regs = null; + + public ARM_Translator(ARM_ProcessSpace ps, ARM2IR arm2ir) { + this.ps = ps; + this.arm2ir = arm2ir; + } + + + private abstract static class ResolvedOperand { + + protected OPT_Operand value; + + protected ARM_Translator translator; + + public static ResolvedOperand resolveWithShifterCarryOut( + ARM_Translator translator, OperandWrapper operand) { + throw new RuntimeException("Not yet implemented"); + } + + public static OPT_Operand resolve(ARM_Translator translator, + OperandWrapper operand) { + ResolvedOperand result = new ResolvedOperand_WithoutShifterCarryOut( + translator, operand); + return result.getValue(); + } + + public final OPT_Operand getValue() { + return value; + } + + public abstract OPT_Operand getShifterCarryOut(); + + protected OPT_RegisterOperand getTempInt() { + return translator.arm2ir.getTempInt(0); + } + + protected OPT_RegisterOperand getTempValidation() { + return translator.arm2ir.getGenerationContext().temps + .makeTempValidation(); + } + + private static class ResolvedOperand_WithoutShifterCarryOut extends + ResolvedOperand { + + private ResolvedOperand_WithoutShifterCarryOut(ARM_Translator translator, + OperandWrapper operand) { + this.translator = translator; + _resolve(operand); + } + + public OPT_Operand getShifterCarryOut() { + throw new RuntimeException( + "This class does not provide a shifter carry out value."); + } + + private void _resolve(OperandWrapper operand) { + + switch (operand.getType()) { + case Immediate: + value = new OPT_IntConstantOperand(operand.getImmediate()); + return; + + case Register: + int reg = operand.getRegister(); + + if (reg == 15) { + // mind the ARM pc offset + value = new OPT_IntConstantOperand(translator.pc + 8); + return; + } + + value = translator.arm2ir.getRegister(reg); + return; + + case RegisterShiftedRegister: + case ImmediateShiftedRegister: + value = resolveShift(operand); + return; + + case PcRelative: + value = new OPT_IntConstantOperand(translator.pc + 8 + + operand.getOffset()); + return; + + default: + throw new RuntimeException("Unexpected wrapped operand type: " + + operand.getType()); + } + } + + /** + * If the given OperandWrapper involves shifting a register, then this + * function will decoder the shift and set the result of the barrel + * shifter accordingly. + */ + private final OPT_Operand resolveShift(OperandWrapper operand) { + if (DBT.VerifyAssertions) + DBT + ._assert(operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister + || operand.getType() == OperandWrapper.Type.RegisterShiftedRegister); + + // consider the "usual" ARM program counter offset + OPT_Operand shiftedOperand; + if (operand.getRegister() == 15) + shiftedOperand = new OPT_IntConstantOperand(translator.pc + 8); + else + shiftedOperand = translator.arm2ir.getRegister(operand.getRegister()); + + OPT_Operand shiftAmount; + + if (operand.getType() == OperandWrapper.Type.ImmediateShiftedRegister) { + // the amount of shift is a constant + shiftAmount = new OPT_IntConstantOperand(operand.getShiftAmount()); + } else { + // the amount of shifting is determined by a register + shiftAmount = translator.arm2ir.getRegister(operand + .getShiftingRegister()); + } + + OPT_BasicBlock currentBlock = translator.arm2ir.getCurrentBlock(); + OPT_BasicBlock nextBlock = translator.arm2ir.getNextBlock(); + + OPT_BasicBlock ifBlock; + OPT_BasicBlock elseBlock; + + OPT_RegisterOperand resultRegister = getTempInt(); + + switch (operand.getShiftType()) { + case ASR: + /* + * if (shiftAmout >= 32) { value = shiftedOperand >> 31; else value = + * shiftedOperand >> shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, + new OPT_IntConstantOperand(31))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHR, resultRegister, shiftedOperand, shiftAmount)); + + return resultRegister; + + case LSL: + /* + * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand << + * shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_SHL, resultRegister, shiftedOperand, shiftAmount)); + + return resultRegister; + + case LSR: + + /* + * if (shiftAmout >= 32) { value = 0; else value = shiftedOperand >>> + * shiftAmount; + */ + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + elseBlock = translator.arm2ir.createBlockAfterCurrent(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_MOVE, resultRegister, new OPT_IntConstantOperand(0))); + + translator.arm2ir.setCurrentBlock(elseBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Binary.create( + INT_USHR, resultRegister, shiftedOperand, shiftAmount)); + + return resultRegister; + + case ROR: + /* + * return Integer.rotateRight(value, shiftAmount); + */ + translator.arm2ir.appendRotateRight(resultRegister, shiftedOperand, shiftAmount); + return resultRegister; + + case RRE: + /* + * if (regs.isCarrySet()) return (resultRegister >> 1) | 0x80000000; + * else return resultRegister >> 1; + */ + + // resultRegister = resultRegister >> 1 + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_USHR_ACC, resultRegister, new OPT_IntConstantOperand(1))); + + ifBlock = translator.arm2ir.createBlockAfterCurrentNotInCFG(); + ifBlock.insertOut(nextBlock); + translator.arm2ir.appendInstructionToCurrentBlock(IfCmp.create( + INT_IFCMP, getTempValidation(), shiftAmount, + new OPT_IntConstantOperand(32), OPT_ConditionOperand + .GREATER_EQUAL(), ifBlock.makeJumpTarget(), + OPT_BranchProfileOperand.unlikely())); + currentBlock.insertOut(ifBlock); + + translator.arm2ir.setCurrentBlock(ifBlock); + translator.arm2ir.appendInstructionToCurrentBlock(Unary.create( + INT_AND_ACC, resultRegister, new OPT_IntConstantOperand( + 0x80000000))); + + return resultRegister; + + default: + throw new RuntimeException("Unexpected shift type: " + + operand.getShiftType()); + } + } + } + } + + /** All ARM interpreter instructions implement this interface. */ + private interface ARM_Instruction { + /** Returns the condition, under which the given instruction will be executed. */ + Condition getCondition(); + + /** performs the actual translation.*/ + void translate(); + } + + /** All ARM instructions that are supposed to be executed conditionally + * are decorated with this decorator. + * The decorator takes care of checking the individual condition and depending on it, executing the + * instruction (or not). The instruction classes itself do not check any conditions. */ + private final class ConditionalDecorator implements ARM_Instruction { + + protected final ARM_Instruction conditionalInstruction; + + /** Decorates an ARM interpreter instruction, by making it execute conditionally. */ + protected ConditionalDecorator(ARM_Instruction i) { + conditionalInstruction = i; + } + + public void translate() { + throw new RuntimeException("Not yet implemented"); + } + + public Condition getCondition() { + return conditionalInstruction.getCondition(); + } + + /** Return true if the condition required by the conditional instruction is fulfilled, false otherwise.*/ + private boolean isConditionTrue() { + switch (conditionalInstruction.getCondition()) { + case AL: + throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator."); + + case CC: + return !regs.isCarrySet(); + + case CS: + return regs.isCarrySet(); + + case EQ: + return regs.isZeroSet(); + + case GE: + return regs.isNegativeSet() == regs.isOverflowSet(); + + case GT: + return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet(); + + case HI: + return regs.isCarrySet() && !regs.isZeroSet(); + + case LE: + return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet()); + + case LS: + return !regs.isCarrySet() || regs.isZeroSet(); + + case LT: + return regs.isNegativeSet() != regs.isOverflowSet(); + + case MI: + return regs.isNegativeSet(); + + case NE: + return !regs.isZeroSet(); + + case NV: + return false; + + case PL: + return !regs.isNegativeSet(); + + case VC: + return !regs.isOverflowSet(); + + case VS: + return regs.isOverflowSet(); + + default: + throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition()); + } + } + + @Override + public String toString() { + return conditionalInstruction.toString(); + } + } + + /** A base class for all data processing interpreter instructions, including CLZ.*/ + private abstract class DataProcessing extends ARM_Instructions.DataProcessing + implements ARM_Instruction { + + protected DataProcessing(int instr) { + super(instr); + } + + /** Returns the value of operand 1 of the data processing instruction. This is always a register value. */ + protected OPT_Operand resolveOperand1() { + + if (Rn == ARM_Registers.PC) { + return new OPT_IntConstantOperand(pc + 8); + } + + return arm2ir.getRegister(Rn); + } + + /** Returns the value of the rhs-operand of the data processing instruction. */ + protected OPT_Operand resolveOperand2() { + return ResolvedOperand.resolve(ARM_Translator.this, operand2); + } + + /** Returns teh register into which the result of a data processing operation shall be stored. */ + protected OPT_RegisterOperand getResultRegister() { + return arm2ir.getRegister(Rd); + } + + /** Sets the result of an operation. */ + protected void setResult(OPT_RegisterOperand result) { + if (Rd == 15) { + //TODO: This is a jump, handle it accordingly + throw new RuntimeException("Not yet implemented"); + } + } + + public abstract void translate(); + + /** Sets the processor flags according to the result of adding <code>lhs</code> and <code>rhs</code>.*/ + protected final void setFlagsForAdd(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + + if (updateConditionCodes) { + if (Rd != 15) { + + //set the carry flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.CARRY_FROM_ADD(), new OPT_BranchProfileOperand())); + + //set the overflow flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } + else { + //TODO: Implement this + regs.restoreSPSR2CPSR(); + throw new RuntimeException("Not yet implemented"); + } + } + } + + /** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/ + protected final void setFlagsForSub(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) { + + if (updateConditionCodes) { + if (Rd != 15) { + //set the carry flag to not(Borrow) + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs, rhs, OPT_ConditionOperand.BORROW_FROM_SUB(), new OPT_BranchProfileOperand())); + arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); + + //set the overflow flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs, rhs, OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } + else { + //TODO: Implement this + regs.restoreSPSR2CPSR(); + throw new RuntimeException("Not yet implemented"); + } + } + } + + public int getSuccessor(int pc) { + if (Rd != 15) + return pc + 4; + else + return -1; + } + } + + private abstract class DataProcessing_Logical extends DataProcessing { + + /** Most data processing instructions may set the carry flag according to the barrel shifter's carry + * out value. The (supposed) value of the barrel shifter is stored within this variable. */ + protected OPT_Operand shifterCarryOut; + + protected DataProcessing_Logical(int instr) { + super(instr); + } + + /** + * Returns the value of the rhs-operand of the data processing instruction. + * This function also retrieves a value for the shifter carry out, which may be set when resolving + * the 2nd operand.*/ + protected OPT_Operand resolveOperand2() { + ResolvedOperand resolvedOperand2 = ResolvedOperand.resolveWithShifterCarryOut(ARM_Translator.this, operand2); + shifterCarryOut = resolvedOperand2.getShifterCarryOut(); + return resolvedOperand2.getValue(); + } + + /** Sets the condition field for logical operations. */ + protected final void setFlagsForLogicalOperator(OPT_Operand result) { + + if (updateConditionCodes) { + if (Rd != 15) { + //TODO: Find an equivalent for BOOLEAN_MOVE + arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), shifterCarryOut)); + arm2ir.appendInstructionToCurrentBlock(Unary.create(BOOLEAN_NOT, arm2ir.getCarryFlag(), arm2ir.getCarryFlag())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + + } else { + //TODO: Implement this + regs.restoreSPSR2CPSR(); + throw new RuntimeException("Not yet implemented"); + } + } + } + } + + /** Binary and. <code>Rd = op1 & op2 </code>.*/ + private final class DataProcessing_And extends DataProcessing_Logical { + + protected DataProcessing_And(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, resolveOperand1(), resolveOperand2())); + + setFlagsForLogicalOperator(result); + setResult(result); + } + } + + /** Exclusive or. <code>Rd = op1 ^ op2 </code>.*/ + private final class DataProcessing_Eor extends DataProcessing_Logical { + + protected DataProcessing_Eor(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_XOR, result, resolveOperand1(), resolveOperand2())); + + setFlagsForLogicalOperator(result); + setResult(result); + } + } + + /** Add. <code>Rd = op1 + op2 </code>.*/ + private final class DataProcessing_Add extends DataProcessing { + + public DataProcessing_Add(int instr) { + super(instr); + } + + public void translate() { + + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); + + setFlagsForAdd(result, operand1, operand2); + setResult(result); + } + } + + /** Subtract. <code>Rd = op1 - op2 </code>.*/ + private final class DataProcessing_Sub extends DataProcessing { + + public DataProcessing_Sub(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); + + setFlagsForSub(result, operand1, operand2); + setResult(result); + } + } + + /** Reverse subtract. <code>Rd = op2 - op1</code>.*/ + private final class DataProcessing_Rsb extends DataProcessing { + + protected DataProcessing_Rsb(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand2, operand1)); + + setFlagsForSub(result, operand2, operand1); + setResult(result); + } + } + + /** Add with carry. <code>Rd = op1 + op2 + CARRY</code>. + * If the carry flag is set, the instruction will add 1 to one of the operands (whichever operands would + * not cause an overflow). Then, the normal add-routine is being invoked. */ + private final class DataProcessing_Adc extends DataProcessing { + + protected DataProcessing_Adc(int instr) { + super(instr); + } + + @Override + public void translate() { + + throw new RuntimeException("Not yet implemented"); + + /* + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + OPT_RegisterOperand long_op1 = arm2ir.getTempLong(0); + OPT_RegisterOperand long_op2 = arm2ir.getTempLong(1); + OPT_RegisterOperand long_result = arm2ir.getTempLong(2); + OPT_RegisterOperand long_tmp = arm2ir.getTempLong(3); + + //convert the operands to longs. Be careful to treat them as unsigned ints during the conversion + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, long_op1, operand1)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_op1, long_op1, new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, long_op2, operand2)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_op2, long_op2, new OPT_LongConstantOperand(0xFFFFFFFF))); + + //perform the actual addition + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_ADD, long_result, long_op1, long_op2)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_ADD, long_result, long_result, new OPT_LongConstantOperand(1))); + arm2ir.appendInstructionToCurrentBlock(Unary.create(LONG_2INT, result, long_result)); + + //set the carry flag if the upper 32 bit of the result are != 0 + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, long_tmp, long_result, new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create(BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), long_tmp, new OPT_LongConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), OPT_BranchProfileOperand.unlikely())); + + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + + //commit the result + setResult(result);*/ + } + } + + /** Subtract with carry. <code>Rd = op1 - op2 + CARRY</code>.*/ + private class DataProcessing_Sbc extends DataProcessing { + + protected DataProcessing_Sbc(int instr) { + super(instr); + } + + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + + /* + if (!regs.isCarrySet()) { + if (operand1 != Integer.MIN_VALUE) { + operand1--; + } else if (operand2 != Integer.MIN_VALUE) { + operand2--; + } else { + //TODO: Remove this exception, when the correct behavior has been verified. + throw new RuntimeException("I'm interested in finding a case where this occurs, so this exception is sooner or later going to 'notify' me.."); + //regs.setFlags(operand1 > 0, operand1 != 0, true, true); + //return; + } + } + + int result = operand1 - operand2; + + regs.set(Rd, result); + setFlagsForSub(operand1, operand2);*/ + } + } + + /** Reserve subtract with carry. <code>Rd = -op1 + op2 + CARRY</code>.*/ + private final class DataProcessing_Rsc extends DataProcessing_Sbc { + + protected DataProcessing_Rsc(int instr) { + super(instr); + } + + @Override + protected OPT_Operand resolveOperand1() { + return super.resolveOperand2(); + } + + @Override + protected OPT_Operand resolveOperand2() { + return super.resolveOperand1(); + } + } + + /** Set the flags according to the logical-and of two values. + * <code>Flags = op1 & op2</code>*/ + private final class DataProcessing_Tst extends DataProcessing_Logical { + + protected DataProcessing_Tst(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, resolveOperand1(), resolveOperand2())); + setFlagsForLogicalOperator(result); + } + } + + /** Sets the flags according to the exclusive-or of two values. + * <code>Flags = op1 ^ op2</code> */ + private final class DataProcessing_Teq extends DataProcessing_Logical { + + protected DataProcessing_Teq(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_XOR, result, resolveOperand1(), resolveOperand2())); + setFlagsForLogicalOperator(result); + } + } + + /** Set the flags according to the comparison of two values. + * <code>Flags = op1 - op2</code> */ + private final class DataProcessing_Cmp extends DataProcessing { + + protected DataProcessing_Cmp(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, result, operand1, operand2)); + setFlagsForSub(result, operand1, operand2); + } + } + + /** Set the flags according to the comparison of two values, negating the 2nd value on the way. + * <code>Flags = op1 + op2</code>. */ + private final class DataProcessing_Cmn extends DataProcessing { + + protected DataProcessing_Cmn(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, operand1, operand2)); + setFlagsForAdd(result, operand1, operand2); + } + } + + /** Binary or. <code>Rd = op1 | op2</code>. */ + private final class DataProcessing_Orr extends DataProcessing_Logical { + + protected DataProcessing_Orr(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_OR, result, operand1, operand2)); + setFlagsForLogicalOperator(result); + setResult(result); + } + } + + private final class DataProcessing_Mov extends DataProcessing_Logical { + + protected DataProcessing_Mov(int instr) { + super(instr); + } + + @Override + /** Moves a value into a register .*/ + public void translate() { + OPT_Operand operand = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, operand)); + + setResult(result); + setFlagsForLogicalOperator(result); + } + } + + /** Bit clear. Clear bits in a register by a mask given by a second operand. + * <code>Rd = op1 & (~op2)</code>.*/ + private final class DataProcessing_Bic extends DataProcessing_Logical { + + protected DataProcessing_Bic(int instr) { + super(instr); + } + + @Override + /** Clear bits in a register by a mask given by a second operand. */ + public void translate() { + OPT_Operand operand1 = resolveOperand1(); + OPT_Operand operand2 = resolveOperand2(); + OPT_RegisterOperand result = getResultRegister(); + + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_NOT, tmp, operand2)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, result, operand1, tmp)); + setFlagsForLogicalOperator(result); + setResult(result); + } + } + + /** Move and negate. Moves an integer between two registers, negating it on the way. + * <code>Rd = -op2</code>.*/ + private final class DataProcessing_Mvn extends DataProcessing_Logical { + + protected DataProcessing_Mvn(int instr) { + super(instr); + } + + @Override + public void translate() { + OPT_RegisterOperand result = getResultRegister(); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_NOT, result, resolveOperand2())); + setFlagsForLogicalOperator(result); + } + } + + /** Count the number of leading zeros in an integer. + * <code>Rd = Number_Of_Leading_Zeroes(op2) </code> */ + private final class DataProcessing_Clz extends DataProcessing { + + protected DataProcessing_Clz(int instr) { + super(instr); + } + + @Override + public void translate() { + + OPT_RegisterOperand result = getResultRegister(); + + VM_TypeReference IntegerType = VM_TypeReference + .findOrCreate(Integer.class); + + VM_MethodReference clzMethodRef = VM_MemberReference + .findOrCreate(IntegerType, + VM_Atom.findOrCreateAsciiAtom("numberOfLeadingZeros"), + VM_Atom.findOrCreateAsciiAtom("(I)I")).asMethodReference(); + + VM_Method clzMethod = clzMethodRef.resolve(); + + OPT_Instruction s = Call.create(CALL, null, null, null, null, 1); + OPT_MethodOperand methOp = OPT_MethodOperand.STATIC(clzMethod); + + Call.setParam(s, 1, resolveOperand2()); + Call.setResult(s, result); + Call.setGuard(s, new OPT_TrueGuardOperand()); + Call.setMethod(s, methOp); + Call.setAddress(s, new OPT_AddressConstantOperand(clzMethod + .getOffset())); + + arm2ir.appendInstructionToCurrentBlock(s); + setResult(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 { + + public Swap(int instr) { + super(instr); + } + + public void translate() { + OPT_Operand memAddr = arm2ir.getRegister(Rn); + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + OPT_RegisterOperand result = arm2ir.getRegister(Rd); + + //swap exchanges the value of a memory address with the value in a register + if (!swapByte) { + ps.memory.translateLoad32(memAddr, tmp); + ps.memory.translateStore32(memAddr, arm2ir.getRegister(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 + OPT_RegisterOperand rotation = arm2ir.getTempInt(1); + + //rotation = (memAddr & 0x3) * 8 + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, rotation, memAddr, new OPT_IntConstantOperand(0x3))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHL, rotation, rotation, new OPT_IntConstantOperand(3))); + arm2ir.appendRotateRight(result, tmp, rotation); + } + else { + ps.memory.translateLoadUnsigned8(memAddr, tmp); + ps.memory.translateStore8(memAddr, arm2ir.getRegister(Rm)); + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, result, tmp)); + } + } + + 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; + } + } + + /** Transfer multiple registers at once between the register bank and the memory. */ + private final class BlockDataTransfer extends ARM_Instructions.MultipleDataTransfer + implements ARM_Instruction { + + /** 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. */ + private final int[] registersToTransfer = new int[16]; + + /** True if the PC should be transferred to, false otherwise. */ + private final boolean transferPC; + + public BlockDataTransfer(int instr) { + super(instr); + + transferPC = transferRegister(15); + int regCount = 0; + + for (int i = 0; i <= 14; i++) + if (transferRegister(i)) { + registersToTransfer[regCount++] = i; + } + + registersToTransfer[regCount] = -1; + registerCount = regCount; + } + + public void translate() { + //build the address, which generally ignores the last two bits + OPT_RegisterOperand startAddress = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, startAddress, arm2ir.getRegister(baseRegister), new OPT_IntConstantOperand(0xFFFFFFFC))); + + if (!incrementBase) { + if (postIndexing) { + //post-indexing, backward reading + //startAddress -= (registerCount + (transferPC ? 1 : 0)) * 4; + OPT_Operand offset = new OPT_IntConstantOperand((registerCount + (transferPC ? 1 : 0)) * 4); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, startAddress, startAddress, offset)); + } else { + //pre-indexing, backward-reading + //startAddress -= (registerCount + (transferPC ? 2 : 1)) * 4 + OPT_Operand offset = new OPT_IntConstantOperand((registerCount + (transferPC ? 2 : 1)) * 4); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, startAddress, startAddress, offset)); + } + } else { + if (postIndexing) { + //post-indexing, forward reading + //startAddress -= 4; + OPT_Operand offset = new OPT_IntConstantOperand(4); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SUB, startAddress, startAddress, offset)); + } else { + //pre-indexing, forward reading + //no need to adjust the start address + } + } + + OPT_RegisterOperand nextAddress = arm2ir.getTempInt(1); + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, nextAddress, startAddress)); + + //TODO: implement + OperatingMode previousMode = ps.registers.getOperatingMode(); + + //if we should transfer the user mode registers... + if (forceUser) { + //... then change the current register map, but do NOT change the current processor mode + ps.registers.switchOperatingMode(OperatingMode.USR); + ps.registers.setOperatingModeWithoutRegisterLayout(previousMode); + + //TODO: implement + throw new RuntimeException("Not yet implemented"); + } + + //are we supposed to load or store multiple registers? + if (isLoad) { + int nextReg = 0; + + while (registersToTransfer[nextReg] != -1) { + //nextAddress += 4; + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); + + OPT_RegisterOperand target = arm2ir.getRegister(registersToTransfer[nextReg++]); + ps.memory.translateLoad32(nextAddress, target); + } + + //if we also transferred the program counter + if (transferPC) { + //nextAddress += 4; + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); + + OPT_RegisterOperand target = arm2ir.getRegister(ARM_Registers.PC); + ps.memory.translateLoad32(nextAddress, target); + + //TODO: Use the first bit of (target) before the following instruction to determine if we should be in thumb mode... + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, target, target, new OPT_IntConstantOperand(0xFFFFFFFE))); + + throw new RuntimeException("Not yet implemented"); + /* + if (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. + //Therefore, sync both first by switching the operating mode to user (which is what our register layout + //is anyway). + regs.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); + regs.restoreSPSR2CPSR(); + + if (regs.getThumbMode()) + newpc = newpc & 0xFFFFFFFE; + else + newpc = newpc & 0xFFFFFFFC; + + regs.set(ARM_Registers.PC, newpc); + //there is no write-back for this instruction. + return; + } + else { + //shall we switch to thumb mode + regs.set(ARM_Registers.PC, newpc & 0xFFFFFFFE); + regs.setThumbMode((newpc & 0x1) != 0); + }*/ + } + } else { + int nextReg = 0; + + while (registersToTransfer[nextReg] != -1) { + //nextAddress += 4; + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); + ps.memory.translateStore32(nextAddress, arm2ir.getRegister(registersToTransfer[nextReg++])); + } + + //also transfer the program counter, if requested so + if (transferPC) { + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, nextAddress, nextAddress, new OPT_IntConstantOperand(4))); + ps.memory.translateStore32(nextAddress, new OPT_IntConstantOperand(pc + 8)); + } + } + + //restore the register layout, if we were transferring the user mode registers + if (forceUser) { + //TODO: Implement.... + ps.registers.setOperatingModeWithoutRegisterLayout(OperatingMode.USR); + ps.registers.switchOperatingMode(previousMode); + } + + if (writeBack) { + OPT_RegisterOperand writeBackTarget = arm2ir.getRegister(baseRegister); + + //write the last address we read from back to a register + if (!incrementBase) { + //backward reading + if (postIndexing) { + //backward reading, post-indexing + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, writeBackTarget, startAddress)); + } + else { + //backward reading, pre-indexing + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, writeBackTarget, startAddress, new OPT_IntConstantOperand(4))); + } + } + else { + //forward reading + if (postIndexing) { + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, writeBackTarget, nextAddress, new OPT_IntConstantOperand(4))); + } + else { + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, writeBackTarget, nextAddress)); + } + } + } + } + + 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) + return -1; + else + return pc + 4; + } + } + + /** Branch to another instruction address. */ + private final class Branch extends ARM_Instructions.Branch implements + ARM_Instruction { + + public Branch(int instr) { + super(instr); + } + + public void translate() { + + //if we're supposed to link, then write the previous address into the link register + if (link) { + arm2ir.appendInstructionToCurrentBlock(Move.create(INT_MOVE, arm2ir.getRegister(ARM_Registers.LR), new OPT_IntConstantOperand(pc + 4))); + } + + arm2ir.setReturnValueResolveLazinessAndBranchToFinish(lazy, new OPT_IntConstantOperand(pc+8 + getOffset())); + } + + public int getSuccessor(int pc) { + return pc + 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 + implements ARM_Instruction { + + public BranchExchange(int instr) { + super(instr); + } + + public void translate() { + //TODO: Implement + throw new RuntimeException("Not yet implemented"); + + /* + //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; + + //the address of the instruction we're jumping to + int targetAddress; + + switch (target.getType()) { + case PcRelative: + targetAddress = previousAddress + target.getOffset(); + thumb = true; + break; + + case Register: + targetAddress = regs.get(target.getRegister()); + thumb = (targetAddress & 0x1) != 0; + targetAddress = targetAddress & 0xFFFFFFFE; + break; + + default: + throw new RuntimeException("Unexpected Operand type: " + + target.getType()); + } + + //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) { + //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(); + } else { + //otherwise we can't predict it + return -1; + } + } + } + + /** 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 + ARM_Instruction { + + protected IntMultiply(int instr) { + super(instr); + } + + public void translate() { + //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 + OPT_Operand operand1 = arm2ir.getRegister(Rm); + OPT_Operand operand2 = arm2ir.getRegister(Rs); + OPT_RegisterOperand result = arm2ir.getRegister(Rd); + + //calculate the result + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_MUL, result, operand1, operand2)); + + if (accumulate) { + OPT_Operand operand3 = arm2ir.getRegister(Rn); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, result, operand3)); + } + + if (updateConditionCodes) { + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } + } + + public int getSuccessor(int pc) { + return pc + 4; + } + } + + /** Multiply two longs into a register, possibly adding the value of a third register on the way. */ + private final class LongMultiply extends ARM_Instructions.LongMultiply implements + ARM_Instruction { + + protected LongMultiply(int instr) { + super(instr); + } + + public void translate() { + //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 + + OPT_RegisterOperand operand1 = arm2ir.getTempLong(0); + OPT_RegisterOperand operand2 = arm2ir.getTempLong(1); + OPT_RegisterOperand result = arm2ir.getTempLong(2); + + //fill the two operands + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, operand1, arm2ir.getRegister(Rm))); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, operand2, arm2ir.getRegister(Rs))); + + if (unsigned) { + //treat the original ints as unsigned, so get rid of the signs for the longs + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, operand1, operand1, new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, operand2, operand2, new OPT_LongConstantOperand(0xFFFFFFFF))); + } + + //multiply the two operands + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_MUL, result, operand1, operand2)); + + if (accumulate) { + //treat the accum. value as an unsigned value + OPT_Operand operand3 = arm2ir.getRegister(getRdLow()); + OPT_RegisterOperand tmp = arm2ir.getTempLong(0); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, tmp, operand3)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_AND, tmp, tmp, new OPT_LongConstantOperand(0xFFFFFFFF))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_ADD, result, result, tmp)); + + operand3 = arm2ir.getRegister(getRdHigh()); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_2LONG, tmp, operand3)); + arm2ir.appendInstructionToCurrentBlock(Binary.create(LONG_SHL, tmp, tmp, new OPT_IntConstantOperand(32))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, result, result, operand3)); + } + + if (updateConditionCodes) { + //set the negative flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_LONG, arm2ir.getNegativeFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand())); + + //set the zero flag + arm2ir.appendInstructionToCurrentBlock(BooleanCmp.create( + BOOLEAN_CMP_LONG, arm2ir.getZeroFlag(), result, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand())); + } + } + + public int getSuccessor(int pc) { + return pc + 4; + } + } + + /** Move the value of the program status register into a register. */ + private final class MoveFromStatusRegister extends + ARM_Instructions.MoveFromStatusRegister implements + ARM_Instruction { + + public MoveFromStatusRegister(int instr) { + super(instr); + } + + public void translate() { + + throw new RuntimeException("Not yet implemented"); + /* + //do we have to transfer the saved or the current PSR? + if (transferSavedPSR) { + regs.set(Rd, regs.getSPSR()); + } + else { + regs.set(Rd, regs.getCPSR()); + }*/ + } + + public int getSuccessor(int pc) { + //Rd should never be the PC, so we can safely predict the next instruction + return pc + 4; + } + } + + private final class MoveToStatusRegister extends + ARM_Instructions.MoveToStatusRegister implements + ARM_Instruction { + + public MoveToStatusRegister(int instr) { + super(instr); + } + + public void translate() { + + //TODO: implement + throw new RuntimeException("Not yet implemented"); + + /* + //this variable is going to receive the new psr, which we will set + int new_psr = ResolvedOperand.resolve(regs, sourceOperand); + + //are we currently in a privileged mode? + boolean inPrivilegedMode = (regs.getOperatingMode() != ARM_Registers.OperatingMode.USR); + + //this variable receives the psr that we're replacing + int old_psr; + + //get the currect value for old_psr + if (transferSavedPSR) { + //if the current mode does not have a SPSR, then do nothing + if (inPrivilegedMode && regs.getOperatingMode() != ARM_Registers.OperatingMode.SYS) + return; + + old_psr = regs.getSPSR(); + } + else { + old_psr = regs.getCPSR(); + } + */ + + //create a new CPSR value according to what pieces of the CPSR we are actually required to set + /*if (!transferControl || !inPrivilegedMode) { + new_psr &= 0xFFFFFF00; + new_psr |= (old_psr & 0xFF); + } + + if (!transferExtension || !inPrivilegedMode) { + new_psr &= 0xFFFF00FF; + new_psr |= (old_psr & 0xFF00); + } + + if (!transferStatus || !inPrivilegedMode) { + new_psr &= 0xFF00FFFF; + new_psr |= (old_psr & 0xFF0000); + } + + if (!transferFlags) { + new_psr &= 0x00FFFFFF; + new_psr |= (old_psr & 0xFF000000); + } + + if (transferSavedPSR) + regs.setSPSR(new_psr); + else + regs.setCPSR(new_psr);*/ + } + + public int getSuccessor(int pc) { + return pc+4; + } + } + + /** Invoke a software interrupt. */ + private final class SoftwareInterrupt extends ARM_Instructions.SoftwareInterrupt + implements ARM_Instruction { + + public SoftwareInterrupt(int instr) { + super(instr); + } + + public void translate() { + arm2ir.plantSystemCall(lazy, pc); + } + + 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 { + + public SingleDataTransfer(int instr) { + super(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 OPT_Operand resolveOffset() { + OPT_Operand positiveOffset = ResolvedOperand.resolve(ARM_Translator.this, offset); + + if (this.positiveOffset) { + return positiveOffset; + } + else { + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Unary.create(INT_NEG, tmp, positiveOffset)); + return tmp; + } + } + + /** Resolves the address of the memory slot, that is involved in the transfer. */ + private OPT_Operand resolveAddress() { + + OPT_Operand base; + + //acquire the base address + if (Rn == 15) + base = new OPT_IntConstantOperand(pc + 8); + else + base = arm2ir.getRegister(Rn); + + //if we are not pre-indexing, then just use the base register for the memory access + if (!preIndexing) + return base; + + //add the offset to the base register + OPT_RegisterOperand tmp = arm2ir.getTempInt(0); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_ADD, tmp, base, resolveOffset())); + return tmp; + } + + public void translate() { + //should we simulate a user-mode memory access? If yes, store the current mode and fake a switch + //to user mode. + OperatingMode previousMode = null; + if (forceUserMode) { + //TODO: implement + previousMode = ps.registers.getOperatingMode(); + ps.registers.setOperatingModeWithoutRegisterLayout(ARM_Registers.OperatingMode.USR); + + throw new RuntimeException("Not yet implemented"); + } + + //get the address of the memory, that we're supposed access + OPT_Operand address = resolveAddress(); + + if (isLoad) { + //we are loading a value from memory. Load it into this variable. + OPT_RegisterOperand value = arm2ir.getRegister(Rd); + + switch (size) { + + case Word: + ps.memory.translateLoad32(address, value); + + //according to the ARM reference, the last two bits cause the value to be right-rotated + OPT_RegisterOperand rotation = arm2ir.getTempInt(0); + + //rotation = (address & 0x3) * 8 + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_AND, rotation, address, new OPT_IntConstantOperand(0x3))); + arm2ir.appendInstructionToCurrentBlock(Binary.create(INT_SHL, rotation, rotation, new OPT_... [truncated message content] |