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-08-27 15:14:37
|
Revision: 174
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=174&view=rev
Author: michael_baer
Date: 2007-08-27 08:14:38 -0700 (Mon, 27 Aug 2007)
Log Message:
-----------
- Added support for Big and Little Endian Applications on ARM
- Added memory implementations for big endian
Modified Paths:
--------------
rvmroot.patch
src/org/binarytranslator/arch/arm/decoder/ARM_Options.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/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java
src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java
src/org/binarytranslator/generic/os/loader/elf/ELF_File.java
src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java
Added Paths:
-----------
src/org/binarytranslator/generic/memory/ByteAddressedBigEndianMemory.java
src/org/binarytranslator/generic/memory/IntAddressedBigEndianMemory.java
Modified: rvmroot.patch
===================================================================
--- rvmroot.patch 2007-08-24 17:51:46 UTC (rev 173)
+++ rvmroot.patch 2007-08-27 15:14:38 UTC (rev 174)
@@ -146,7 +146,7 @@
[Lorg/jikesrvm/compilers/opt/OPT_Simplifier$DefUseEffect;
[Lorg/jikesrvm/compilers/opt/ir/OPT_Operator;
+[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$ELF_Identity$AddressSize;
-+[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$ELF_Identity$ByteOrder;
++[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$ByteOrder;
+[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$Header$ObjectFileType;
+[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$SegmentRange;
+[Lorg/binarytranslator/vmInterface/DummyDynamicCodeRunner;
@@ -157,4 +157,6 @@
+[Lorg/binarytranslator/arch/arm/decoder/ARM_Instructions$Instruction$Condition;
+[Lorg/binarytranslator/arch/arm/decoder/ARM_Instructions$DataProcessing$Opcode;
+[Lorg/binarytranslator/arch/arm/decoder/ARM_Instructions$OperandWrapper$ShiftType;
++[Lorg/binarytranslator/arch/arm/decoder/ARM_Laziness$Operation;
++[Lorg/binarytranslator/arch/arm/decoder/ARM_Laziness$Flag;
\ No newline at end of file
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-24 17:51:46 UTC (rev 173)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-27 15:14:38 UTC (rev 174)
@@ -1,5 +1,7 @@
package org.binarytranslator.arch.arm.decoder;
+import org.binarytranslator.generic.os.loader.elf.ELF_File.ByteOrder;
+
public class ARM_Options {
public enum FlagBehaviour {
@@ -39,6 +41,9 @@
/** Sets the memory model that ARM shall use. */
public static MemoryModel memoryModel = MemoryModel.IntAddressed;
+ /** Override the byte order read from the ELF file. */
+ public static ByteOrder enforcedByteOrder = null;
+
public static void parseOption(String key, String value) {
if (key.equalsIgnoreCase("optimizeByProfiling")) {
optimizeTranslationByProfiling = Boolean.parseBoolean(value);
@@ -50,7 +55,9 @@
memoryModel = ARM_Options.MemoryModel.valueOf(value);
} else if (key.equalsIgnoreCase("optimizedFlags")) {
useOptimizedFlags = Boolean.parseBoolean(value);
- }
+ } else if (key.equalsIgnoreCase("byteOrder")) {
+ enforcedByteOrder = ByteOrder.valueOf(value);
+ }
else {
throw new Error("Unknown ARM option: " + key);
}
Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-24 17:51:46 UTC (rev 173)
+++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-27 15:14:38 UTC (rev 174)
@@ -10,9 +10,13 @@
import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace;
import org.binarytranslator.generic.decoder.CodeTranslator;
import org.binarytranslator.generic.decoder.Interpreter;
+import org.binarytranslator.generic.memory.ByteAddressedBigEndianMemory;
import org.binarytranslator.generic.memory.ByteAddressedLittleEndianMemory;
+import org.binarytranslator.generic.memory.IntAddressedBigEndianMemory;
import org.binarytranslator.generic.memory.IntAddressedLittleEndianMemory;
import org.binarytranslator.generic.os.loader.Loader;
+import org.binarytranslator.generic.os.loader.elf.ELF_Loader;
+import org.binarytranslator.generic.os.loader.elf.ELF_File.ByteOrder;
import org.binarytranslator.generic.os.process.ProcessSpace;
import org.binarytranslator.vmInterface.DBT_Trace;
import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext;
@@ -20,11 +24,9 @@
public abstract class ARM_ProcessSpace extends ProcessSpace {
-
/** Registers used by this process */
public ARM_Registers registers;
-
/**
* Debug information
*
@@ -38,16 +40,44 @@
}
}
- protected ARM_ProcessSpace() {
+ protected ARM_ProcessSpace(ByteOrder byteOrder) {
registers = new ARM_Registers();
switch (ARM_Options.memoryModel) {
case ByteAddressed:
- memory = new ByteAddressedLittleEndianMemory();
+
+ switch (byteOrder)
+ {
+ case LittleEndian:
+ memory = new ByteAddressedLittleEndianMemory();
+ break;
+
+ case BigEndian:
+ memory = new ByteAddressedBigEndianMemory();
+ break;
+
+ default:
+ throw new RuntimeException("Unexpected byte order: " + byteOrder);
+ }
+
break;
case IntAddressed:
- memory = new IntAddressedLittleEndianMemory();
+
+ switch (byteOrder)
+ {
+ case LittleEndian:
+ memory = new IntAddressedLittleEndianMemory();
+ break;
+
+ case BigEndian:
+ memory = new IntAddressedBigEndianMemory();
+ break;
+
+ default:
+ throw new RuntimeException("Unexpected byte order: " + byteOrder);
+ }
+
break;
default:
@@ -79,12 +109,30 @@
public static ProcessSpace createProcessSpaceFromBinary(Loader loader)
throws IOException {
Loader.ABI abi = loader.getABI();
+
+ //determine the byte order for the memory implementation
+ ByteOrder byteOrder = ARM_Options.enforcedByteOrder;
+
+ if (byteOrder == null) {
+ if (loader instanceof ELF_Loader) {
+ //read the byte order from the elf file
+ byteOrder = ((ELF_Loader)loader).getFile().getByteOrder();
+ }
+ else {
+ byteOrder = ByteOrder.LittleEndian;
+ System.err.println("WARNING: Unable to deduce byte order from binary file. Defaulting to " + byteOrder);
+ }
+ }
+ else {
+ System.err.println("WARNING: Overriding byte order set by ELF file to " + byteOrder);
+ }
+
if (abi == Loader.ABI.ARM) {
report("Creating ARM Linux ABI Process space");
- return new ARM_LinuxProcessSpace();
+ return new ARM_LinuxProcessSpace(byteOrder);
} else {
report("Creating ARM image process space.");
- return new ARM_ImageProcessSpace();
+ return new ARM_ImageProcessSpace(byteOrder);
}
}
Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-24 17:51:46 UTC (rev 173)
+++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-27 15:14:38 UTC (rev 174)
@@ -10,6 +10,7 @@
import org.binarytranslator.generic.execution.GdbController.GdbTarget;
import org.binarytranslator.generic.fault.InsufficientMemoryException;
import org.binarytranslator.generic.os.loader.Loader;
+import org.binarytranslator.generic.os.loader.elf.ELF_File.ByteOrder;
public class ARM_ImageProcessSpace extends ARM_ProcessSpace {
@@ -17,11 +18,8 @@
private final int STACK_SIZE = 4096 * 1000;
private final int HEAP_SIZE = 4096 * 1000;
- public ARM_ImageProcessSpace() {
- super();
-
- //make sure that pages of memory are automatically mapped in as they are requested.
- //memory = new AutoMappingMemory(memory);
+ public ARM_ImageProcessSpace(ByteOrder byteOrder) {
+ super(byteOrder);
}
private int allocateFreeMemoryArea(int stackSize) throws InsufficientMemoryException
Modified: src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-08-24 17:51:46 UTC (rev 173)
+++ src/org/binarytranslator/arch/arm/os/process/linux/ARM_LinuxProcessSpace.java 2007-08-27 15:14:38 UTC (rev 174)
@@ -10,6 +10,7 @@
import org.binarytranslator.generic.os.abi.linux.LinuxSystemCalls;
import org.binarytranslator.generic.os.loader.Loader;
import org.binarytranslator.generic.os.loader.elf.ELF_Loader;
+import org.binarytranslator.generic.os.loader.elf.ELF_File.ByteOrder;
public class ARM_LinuxProcessSpace extends ARM_ProcessSpace {
@@ -31,7 +32,9 @@
*/
private int[] auxVector;
- public ARM_LinuxProcessSpace() {
+ public ARM_LinuxProcessSpace(ByteOrder byteOrder) {
+ super(byteOrder);
+
sysCallGenerator = new Legacy(this);
sysCalls = new ARM_LinuxSystemCalls(this, sysCallGenerator);
}
Added: src/org/binarytranslator/generic/memory/ByteAddressedBigEndianMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/ByteAddressedBigEndianMemory.java (rev 0)
+++ src/org/binarytranslator/generic/memory/ByteAddressedBigEndianMemory.java 2007-08-27 15:14:38 UTC (rev 174)
@@ -0,0 +1,550 @@
+/*
+ * This file is part of binarytranslator.org. The binarytranslator.org
+ * project is distributed under the Common Public License (CPL).
+ * A copy of the license is included in the distribution, and is also
+ * available at http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * (C) Copyright Ian Rogers, The University of Manchester 2003-2006
+ */
+package org.binarytranslator.generic.memory;
+
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import org.binarytranslator.DBT_Options;
+import org.binarytranslator.generic.fault.SegmentationFault;
+
+/**
+ * ByteAddressedMemory:
+ *
+ * Memory is arrays of bytes, no endian conversion is performed.
+ *
+ * The string helo followed by the int of 0xcafebabe appear as:
+ *
+ * <pre>
+ * Byte Address|
+ * -----------------
+ * .........07 | ca|
+ * .........06 | fe|
+ * .........05 | ba|
+ * .........04 | be|
+ * .........03 |'o'|
+ * .........02 |'l'|
+ * .........01 |'e'|
+ * .........00 |'H'|
+ * </pre>
+ */
+public class ByteAddressedBigEndianMemory extends CallBasedMemory {
+
+ /** The size of a single page in bytes. */
+ private static final int PAGE_SIZE = 4096;
+
+ /** Bits in offset */
+ private static final int OFFSET_BITS = 12;
+
+ /** The number of pages */
+ private static final int NUM_PAGES = 0x100000;
+
+ /** The maximum amount of RAM available */
+ protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES;
+
+ /** The memory backing store */
+ private byte readableMemory[][];
+ private byte writableMemory[][];
+ private byte executableMemory[][];
+
+ /** Do we have more optimal nio mmap operation? */
+ private boolean HAVE_java_nio_FileChannelImpl_nio_mmap_file = false;
+
+ /**
+ * Constructor - used when this is the instatiated class
+ */
+ public ByteAddressedBigEndianMemory() {
+ this(null);
+ }
+
+ /**
+ * Constructor - used when deriving a class
+ *
+ * @param classType
+ * the name of the over-riding class
+ */
+ protected ByteAddressedBigEndianMemory(Class classType) {
+ super(classType != null ? classType : ByteAddressedBigEndianMemory.class);
+ readableMemory = new byte[NUM_PAGES][];
+ writableMemory = new byte[NUM_PAGES][];
+ executableMemory = new byte[NUM_PAGES][];
+ }
+
+ /**
+ * Return the offset part of the address
+ */
+ private static final int getOffset(int address) {
+ return address & (PAGE_SIZE - 1);
+ }
+
+ /**
+ * Return the page table entry part of the address
+ */
+ private static final int getPTE(int address) {
+ return address >>> OFFSET_BITS;
+ }
+
+ /**
+ * Find free consecutive pages
+ *
+ * @param pages
+ * the number of pages required
+ * @return the address found
+ */
+ private final int findFreePages(int pages) {
+ starting_page_search: for (int i = 0; i < NUM_PAGES; i++) {
+ if (getPage(i) == null) {
+ int start = i;
+ int end = i + pages;
+ for (; i <= end; i++) {
+ if (getPage(i) != null) {
+ continue starting_page_search;
+ }
+ }
+ return start << OFFSET_BITS;
+ }
+ }
+ throw new Error(
+ "No mappable consecutive pages found for an anonymous map of size"
+ + (pages * PAGE_SIZE));
+ }
+
+ /**
+ * Map an anonymous page of memory
+ *
+ * @param addr
+ * the address to map or NULL if don't care
+ * @param len
+ * the amount of memory to map
+ * @param read
+ * is the page readable
+ * @param write
+ * is the page writable
+ * @param exec
+ * is the page executable
+ */
+ public int map(int addr, int len, boolean read, boolean write, boolean exec)
+ throws MemoryMapException {
+ // Check address is page aligned
+ if ((addr % PAGE_SIZE) != 0) {
+ MemoryMapException.unalignedAddress(addr);
+ }
+
+ // Create memory
+ int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE;
+ byte pages[][] = new byte[num_pages][PAGE_SIZE];
+
+ // Find address if not specified
+ if (addr == 0) {
+ addr = findFreePages(num_pages);
+ }
+
+ if (DBT_Options.debugMemory) {
+ System.out.println("Anonymous mapping: addr=0x"
+ + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -")
+ + (write ? "w" : "-") + (exec ? "x" : "-"));
+ }
+
+ // Get page table entry
+ int pte = getPTE(addr);
+ for (int i = 0; i < num_pages; i++) {
+
+ // Check pages aren't already allocated
+ if (getPage(pte + i) != null) {
+ throw new Error("Memory map of already mapped location addr=0x"
+ + Integer.toHexString(addr) + " len=" + len);
+ }
+
+ // Allocate pages
+ readableMemory[pte + i] = read ? pages[i] : null;
+ writableMemory[pte + i] = write ? pages[i] : null;
+ executableMemory[pte + i] = exec ? pages[i] : null;
+ }
+
+ return addr;
+ }
+
+ /**
+ * Map a page of memory from file
+ *
+ * @param file
+ * the file map in from
+ * @param addr
+ * the address to map or NULL if don't care
+ * @param len
+ * the amount of memory to map
+ * @param read
+ * is the page readable
+ * @param write
+ * is the page writable
+ * @param exec
+ * is the page executable
+ */
+ public int map(RandomAccessFile file, long offset, int addr, int len,
+ boolean read, boolean write, boolean exec) throws MemoryMapException {
+ // Check address is page aligned
+ if ((addr % PAGE_SIZE) != 0) {
+ MemoryMapException.unalignedAddress(addr);
+ }
+
+ // Check file offset is page aligned
+ /*if ((offset % PAGE_SIZE) != 0) {
+ MemoryMapException.unalignedFileOffset(offset);
+ }*/
+
+ // Calculate number of pages
+ int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE;
+ // Find address if not specified
+ if (addr == 0) {
+ addr = findFreePages(num_pages);
+ }
+ if (DBT_Options.debugMemory) {
+ System.out.println("Mapping file " + file + " offset=" + offset
+ + " addr=0x" + Integer.toHexString(addr) + " len=" + len
+ + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-"));
+ }
+ try {
+ // Get page table entry
+ int pte = getPTE(addr);
+ // Can we optimise the reads to use mmap?
+ if (!HAVE_java_nio_FileChannelImpl_nio_mmap_file) {
+ // Sub-optimal
+ file.seek(offset);
+ for (int i = 0; i < num_pages; i++) {
+ // Check pages aren't already allocated
+ if (getPage(pte + i) != 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];
+ if (i == 0) { // first read, start from offset upto a page length
+ file.read(page, getOffset(addr), PAGE_SIZE - getOffset(addr));
+ } else if (i == (num_pages - 1)) { // last read
+ file.read(page, 0, ((len - getOffset(addr)) % PAGE_SIZE));
+ } else {
+ file.read(page);
+ }
+
+ readableMemory[pte + i] = read ? page : null;
+ writableMemory[pte + i] = write ? page : null;
+ executableMemory[pte + i] = exec ? page : null;
+ }
+ } else {
+ for (int i = 0; i < num_pages; i++) {
+ // Check pages aren't already allocated
+ if (getPage(pte + i) != null) {
+ throw new Error("Memory map of already mapped location addr=0x"
+ + Integer.toHexString(addr) + " len=" + len);
+ }
+
+ // Allocate page
+ if (read && write) {
+ readableMemory[pte + i] = file.getChannel().map(
+ FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE),
+ PAGE_SIZE).array();
+ writableMemory[pte + i] = readableMemory[pte + i];
+ if (exec) {
+ executableMemory[pte + i] = readableMemory[pte + i];
+ }
+ } else if (read) {
+ readableMemory[pte + i] = file.getChannel().map(
+ FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE),
+ PAGE_SIZE).array();
+ if (exec) {
+ executableMemory[pte + i] = readableMemory[pte + i];
+ }
+ } else if (exec) {
+ executableMemory[pte + i] = file.getChannel().map(
+ FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE),
+ PAGE_SIZE).array();
+ } else {
+ throw new Error("Unable to map address 0x"
+ + Integer.toHexString(addr) + " with permissions "
+ + (read ? "r" : "-") + (write ? "w" : "-") + (exec ? "x" : "-"));
+ }
+ }
+ }
+ return addr;
+ } catch (java.io.IOException e) {
+ throw new Error(e);
+ }
+ }
+
+ /**
+ * Returns the page currently mapped at the given page table entry.
+ *
+ * @param pte
+ * The page table entry, for which a page is to be retrieved.
+ * @return
+ * The page mapped at the given page table entry or null, if no page is currently mapped
+ * to that entry.
+ */
+ private byte[] getPage(int pte) {
+
+ if (readableMemory[pte] != null)
+ return readableMemory[pte];
+
+ if (writableMemory[pte] != null)
+ return writableMemory[pte];
+
+ if (executableMemory[pte] != null)
+ return executableMemory[pte];
+
+ return null;
+ }
+
+ /**
+ * Unmap a page of memory
+ *
+ * @param addr
+ * the address to unmap
+ * @param len
+ * the amount of memory to unmap
+ */
+ public void unmap(int addr, int len) {
+ for (int i = 0; i < len; i += PAGE_SIZE) {
+
+ int pte = getPTE(addr + i);
+ if (getPage(pte) != null) {
+ readableMemory[pte] = null;
+ writableMemory[pte] = null;
+ executableMemory[pte] = null;
+ }
+ else {
+ throw new Error("Unmapping memory that's not mapped addr=0x"
+ + Integer.toHexString(addr) + " len=" + len);
+ }
+ }
+ }
+
+ /**
+ * Is the given address mapped into memory?
+ * @param addr to check
+ * @return true => memory is mapped
+ */
+ public boolean isMapped(int addr) {
+ return getPage(getPTE(addr)) != null;
+ }
+
+ /**
+ * @return the size of a page
+ */
+ public int getPageSize() {
+ return PAGE_SIZE;
+ }
+
+ /**
+ * Is the given address aligned on a page boundary?
+ *
+ * @param addr
+ * the address to check
+ * @return whether the address is aligned
+ */
+ public boolean isPageAligned(int addr) {
+ return (addr % PAGE_SIZE) == 0;
+ }
+
+ /**
+ * Make the given address page aligned to the page beneath it
+ *
+ * @param addr
+ * the address to truncate
+ * @return the truncated address
+ */
+ public int truncateToPage(int addr) {
+ return (addr >> OFFSET_BITS) << OFFSET_BITS;
+ }
+
+ /**
+ * Make the given address page aligned to the page above it
+ *
+ * @param addr
+ * the address to truncate
+ * @return the truncated address
+ */
+ public int truncateToNextPage(int addr) {
+ return ((addr + PAGE_SIZE - 1) >> OFFSET_BITS) << OFFSET_BITS;
+ }
+
+ /**
+ * Perform a byte load where the sign extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the sign extended result
+ */
+ final public int loadSigned8(int addr) {
+ try {
+ if (DBT_Options.debugMemory)
+ System.err.println("LoadS8 address: 0x" + Integer.toHexString(addr)
+ + " val: " + readableMemory[getPTE(addr)][getOffset(addr)]);
+ return readableMemory[getPTE(addr)][getOffset(addr)];
+ } catch (NullPointerException e) {
+ System.err.println("Null pointer exception at address: 0x"
+ + Integer.toHexString(addr));
+ throw e;
+ }
+ }
+
+ /**
+ * Perform a byte load where the zero extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the zero extended result
+ */
+ final public int loadUnsigned8(int addr) {
+ try {
+ if (DBT_Options.debugMemory)
+ System.err.println("LoadU8 address: 0x" + Integer.toHexString(addr)
+ + " val: " + readableMemory[getPTE(addr)][getOffset(addr)]);
+ return readableMemory[getPTE(addr)][getOffset(addr)] & 0xFF;
+ } catch (NullPointerException e) {
+ System.err.println("Null pointer exception at address: 0x"
+ + Integer.toHexString(addr));
+ throw e;
+ }
+ }
+
+ /**
+ * Perform a 16bit load where the sign extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the sign extended result
+ */
+ public int loadSigned16(int addr) {
+ return (loadSigned8(addr) << 8) | loadUnsigned8(addr + 1);
+ }
+
+ /**
+ * Perform a 16bit load where the zero extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the zero extended result
+ */
+ public int loadUnsigned16(int addr) {
+ return (loadUnsigned8(addr) << 8) | loadUnsigned8(addr + 1);
+ }
+
+ /**
+ * Perform a 32bit load
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int load32(int addr) {
+ try {
+ return (loadSigned8(addr) << 24) | (loadUnsigned8(addr + 1) << 16)
+ | (loadUnsigned8(addr + 2) << 8) | loadUnsigned8(addr + 3);
+ } catch (Exception e) {
+ throw new SegmentationFault(addr);
+ }
+ }
+
+ /**
+ * Perform a 8bit load from memory that must be executable
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int loadInstruction8(int addr) {
+ if (DBT_Options.debugMemory)
+ System.err.println("LoadI8 address: 0x" + Integer.toHexString(addr)
+ + " val: " + executableMemory[getPTE(addr)][getOffset(addr)]);
+ return executableMemory[getPTE(addr)][getOffset(addr)] & 0xFF;
+ }
+
+ /**
+ * Perform a 32bit load from memory that must be executable
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int loadInstruction32(int addr) {
+ return (loadInstruction8(addr) << 24)
+ | (loadInstruction8(addr + 1) << 16)
+ | (loadInstruction8(addr + 2) << 8) | loadInstruction8(addr + 3);
+ }
+
+ /**
+ * Perform a byte store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public final void store8(int addr, int value) {
+ if (DBT_Options.debugMemory)
+ System.err.println("Store8 address: 0x" + Integer.toHexString(addr)
+ + " val: 0x" + Integer.toHexString(value & 0xFF));
+ writableMemory[getPTE(addr)][getOffset(addr)] = (byte) value;
+ }
+
+ /**
+ * Perform a 16bit store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public void store16(int addr, int value) {
+ store8(addr, value >> 8);
+ store8(addr + 1, value);
+ }
+
+ /**
+ * Perform a 32bit store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public void store32(int addr, int value) {
+ try {
+ store8(addr, value >> 24);
+ store8(addr + 1, value >> 16);
+ store8(addr + 2, value >> 8);
+ store8(addr + 3, value);
+ } catch (Exception e) {
+ throw new SegmentationFault(addr);
+ }
+ }
+
+ @Override
+ public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) {
+
+ while (len > 0) {
+ int pte = getPTE(address);
+ byte[] page = getPage(pte);
+
+ if (page == null)
+ throw new SegmentationFault(address);
+
+ readableMemory[pte] = newRead ? page : null;
+ writableMemory[pte] = newWrite ? page : null;
+ executableMemory[pte] = newExec ? page : null;
+
+ address += PAGE_SIZE;
+ len -= PAGE_SIZE;
+ }
+ }
+
+ @Override
+ public int loadInstruction16(int addr) {
+ return (loadInstruction8(addr) << 8) | loadInstruction8(addr + 1);
+ }
+}
Added: src/org/binarytranslator/generic/memory/IntAddressedBigEndianMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/IntAddressedBigEndianMemory.java (rev 0)
+++ src/org/binarytranslator/generic/memory/IntAddressedBigEndianMemory.java 2007-08-27 15:14:38 UTC (rev 174)
@@ -0,0 +1,669 @@
+/*
+ * This file is part of binarytranslator.org. The binarytranslator.org
+ * project is distributed under the Common Public License (CPL).
+ * A copy of the license is included in the distribution, and is also
+ * available at http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * (C) Copyright Ian Rogers, The University of Manchester 2003-2006
+ */
+package org.binarytranslator.generic.memory;
+
+import java.io.RandomAccessFile;
+
+import org.binarytranslator.DBT;
+import org.binarytranslator.DBT_Options;
+import org.binarytranslator.generic.fault.SegmentationFault;
+import org.vmmagic.pragma.Inline;
+
+/**
+ * IntAddressedMemory:
+ *
+ * Memory is arrays of ints, no endian conversion is performed.
+ *
+ * The string helloworld following by the int of 0xcafebabe appear as:
+ *
+ * <pre>
+ * Byte Address
+ * Int Address | 0 | 1 | 2 | 3 |
+ * -----------------------------
+ * .........0c | ca| fe| ba| be|
+ * .........08 |'l'|'d'| \n| \0|
+ * .........04 |'o'|'W'|'o'|'r'|
+ * .........00 |'H'|'e'|'l'|'l'|
+ * </pre>
+ */
+public class IntAddressedBigEndianMemory extends CallBasedMemory {
+ /**
+ * The size of pages
+ */
+ protected static final int PAGE_SIZE = 4096;
+
+ /**
+ * Bits in offset
+ */
+ protected static final int OFFSET_BITS = 12;
+
+ /**
+ * The number of pages
+ */
+ protected static final int NUM_PAGES = 0x100000;
+
+ /**
+ * The maximum amount of RAM available
+ */
+ protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES;
+
+ /**
+ * The memory backing store
+ */
+ private int readableMemory[][];
+
+ private int writableMemory[][];
+
+ private int executableMemory[][];
+
+ /**
+ * Constructor - used when this is the instatiated class
+ */
+ public IntAddressedBigEndianMemory() {
+ this(null);
+ }
+
+ /**
+ * Constructor - used when deriving a class
+ *
+ * @param classType
+ * the type of the over-riding class
+ */
+ protected IntAddressedBigEndianMemory(Class classType) {
+ super(classType != null ? classType : IntAddressedBigEndianMemory.class);
+ readableMemory = new int[NUM_PAGES][];
+ writableMemory = new int[NUM_PAGES][];
+ executableMemory = new int[NUM_PAGES][];
+ }
+
+ /**
+ * Return the offset part of the address
+ */
+ @Inline
+ private static final int getOffset(int address) {
+ return (address & (PAGE_SIZE - 1)) >>> 2;
+ }
+
+ /**
+ * Return the page table entry part of the address
+ */
+ @Inline
+ private static final int getPTE(int address) {
+ return address >>> OFFSET_BITS;
+ }
+
+ /**
+ * Is the given address mapped into memory?
+ * @param addr to check
+ * @return true => memory is mapped
+ */
+ public boolean isMapped(int addr) {
+ return getPage(getPTE(addr)) != null;
+ }
+
+ /**
+ * @return the size of a page
+ */
+ public int getPageSize() {
+ return PAGE_SIZE;
+ }
+
+ /**
+ * Is the given address aligned on a page boundary?
+ *
+ * @param addr
+ * the address to check
+ * @return whether the address is aligned
+ */
+ public boolean isPageAligned(int addr) {
+ return (addr % PAGE_SIZE) == 0;
+ }
+
+ /**
+ * Make the given address page aligned to the page beneath it
+ *
+ * @param addr
+ * the address to truncate
+ * @return the truncated address
+ */
+ public int truncateToPage(int addr) {
+ return (addr >> OFFSET_BITS) << OFFSET_BITS;
+ }
+
+ /**
+ * Make the given address page aligned to the page above it
+ *
+ * @param addr
+ * the address to truncate
+ * @return the truncated address
+ */
+ public int truncateToNextPage(int addr) {
+ return ((addr + PAGE_SIZE - 1) >> OFFSET_BITS) << OFFSET_BITS;
+ }
+
+ /**
+ * Find free consecutive pages
+ *
+ * @param pages
+ * the number of pages required
+ * @return the address found
+ */
+ private final int findFreePages(int pages) {
+ starting_page_search: for (int i = 0; i < NUM_PAGES; i++) {
+ if (getPage(i) == null) {
+ int start = i;
+ int end = i + pages;
+ for (; i <= end; i++) {
+ if (getPage(i) != null) {
+ continue starting_page_search;
+ }
+ }
+ return start << OFFSET_BITS;
+ }
+ }
+ throw new Error(
+ "No mappable consecutive pages found for an anonymous map of size"
+ + (pages * PAGE_SIZE));
+ }
+
+ /**
+ * Map an anonymous page of memory
+ *
+ * @param addr
+ * the address to map or NULL if don't care
+ * @param len
+ * the amount of memory to map
+ * @param read
+ * is the page readable
+ * @param write
+ * is the page writable
+ * @param exec
+ * is the page executable
+ */
+ public int map(int addr, int len, boolean read, boolean write, boolean exec)
+ throws MemoryMapException {
+ // Check that the address is page aligned
+ if ((addr % PAGE_SIZE) != 0) {
+ // if it is not, truncate the address down to the next page boundary and
+ // start mapping from there
+ int validPageCount = addr / PAGE_SIZE;
+ int oldStartAddress = addr;
+ addr = validPageCount * PAGE_SIZE;
+
+ if (DBT.VerifyAssertions)
+ DBT._assert(oldStartAddress > addr);
+
+ // we have to map more more memory now to reach the same end address
+ len += (oldStartAddress - addr);
+ }
+
+ // Calculate number of pages
+ int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE;
+ // Create memory
+ int pages[][] = new int[num_pages][PAGE_SIZE / 4];
+ // Find address if not specified
+ if (addr == 0) {
+ addr = findFreePages(num_pages);
+ }
+ if (DBT_Options.debugRuntime) {
+ System.out.println("Anonymous mapping: addr=0x"
+ + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -")
+ + (write ? "w" : "-") + (exec ? "x" : "-"));
+ }
+ // Get page table entry
+ int pte = getPTE(addr);
+ for (int i = 0; i < num_pages; i++) {
+ // Check pages aren't already allocated
+ if (getPage(pte + i) != null) {
+ throw new Error("Memory map of already mapped location addr=0x"
+ + Integer.toHexString(addr) + " len=" + len);
+ }
+
+ readableMemory[pte+i] = read ? pages[i] : null;
+ writableMemory[pte+i] = write ? pages[i] : null;
+ executableMemory[pte+i] = exec ? pages[i] : null;
+ }
+ return addr;
+ }
+
+ /**
+ * Returns the page currently mapped at the given page table entry.
+ *
+ * @param pte
+ * The page table entry, for which a page is to be retrieved.
+ * @return
+ * The page mapped at the given page table entry or null, if no page is currently mapped
+ * to that entry.
+ */
+ private int[] getPage(int pte) {
+
+ if (readableMemory[pte] != null)
+ return readableMemory[pte];
+
+ if (writableMemory[pte] != null)
+ return writableMemory[pte];
+
+ if (executableMemory[pte] != null)
+ return executableMemory[pte];
+
+ return null;
+ }
+
+ @Override
+ public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) {
+
+ while (len > 0) {
+ int pte = getPTE(address);
+ int[] page = getPage(pte);
+
+ if (page == null)
+ throw new SegmentationFault(address);
+
+ readableMemory[pte] = newRead ? page : null;
+ writableMemory[pte] = newWrite ? page : null;
+ executableMemory[pte] = newExec ? page : null;
+
+ address += PAGE_SIZE;
+ len -= PAGE_SIZE;
+ }
+ }
+
+ /**
+ * Read an int from RandomAccessFile ensuring that a byte swap isn't performed
+ *
+ * @param file
+ * file to read from
+ * @return native endian read int
+ */
+ protected int readInt(RandomAccessFile file) throws java.io.IOException {
+
+ return file.readByte() << 24 | (file.readUnsignedByte() << 16)
+ | (file.readUnsignedByte() << 8) | (file.readUnsignedByte());
+ }
+
+ /**
+ * Map a page of memory from file
+ *
+ * @param file
+ * the file map in from
+ * @param addr
+ * the address to map or NULL if don't care
+ * @param len
+ * the amount of memory to map
+ * @param read
+ * is the page readable
+ * @param write
+ * is the page writable
+ * @param exec
+ * is the page executable
+ */
+ public final int map(RandomAccessFile file, long offset, int addr, int len,
+ boolean read, boolean write, boolean exec) throws MemoryMapException {
+ // Check address is page aligned
+ if ((addr % PAGE_SIZE) != 0) {
+ MemoryMapException.unalignedAddress(addr);
+ }
+ // Check file offset is page aligned
+ /*if ((offset % PAGE_SIZE) != 0) {
+ MemoryMapException.unalignedFileOffset(offset);
+ }*/
+
+ if (DBT_Options.debugRuntime) {
+ System.out.println("Mapping file " + file + " offset=" + offset
+ + " addr=0x" + Integer.toHexString(addr) + " len=" + len
+ + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-"));
+ }
+ addr = map(addr, len, read, write, exec);
+
+ try {
+ file.seek(offset);
+ for (int i = 0; i < len; i += 4) {
+
+ int[] page = getPage(getPTE(addr + i));
+ page[getOffset(addr + i)] = readInt(file);
+ }
+
+ return addr;
+
+ }
+ catch (java.io.IOException e) {
+ throw new Error(e);
+ }
+ }
+
+ /**
+ * Unmap a page of memory
+ *
+ * @param addr
+ * the address to unmap
+ * @param len
+ * the amount of memory to unmap
+ */
+ public final void unmap(int addr, int len) {
+ for (int i = 0; i < len; i += PAGE_SIZE) {
+
+ int pte = getPTE(addr + i);
+
+ if (getPage(pte) != null) {
+ readableMemory[pte] = null;
+ writableMemory[pte] = null;
+ executableMemory[pte] = null;
+ }
+ else {
+ throw new Error("Unmapping memory that's not mapped addr=0x"
+ + Integer.toHexString(addr) + " len=" + len);
+ }
+ }
+ }
+
+ /**
+ * Perform a 32bit load where addr is word aligned
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ protected final int loadWordAligned32(int addr) {
+ return readableMemory[getPTE(addr)][getOffset(addr)];
+ }
+
+ /**
+ * Perform a 32bit load where addr is word aligned and executable
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ protected final int loadWordAlignedInstruction32(int addr) {
+ return executableMemory[getPTE(addr)][getOffset(addr)];
+ }
+
+ /**
+ * Perform a byte load where the sign extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the sign extended result
+ */
+ public int loadSigned8(int addr) {
+ return (loadWordAligned32(addr) << ((addr & 0x3) << 3)) >> 24;
+ // switch(addr & 3) {
+ // default:
+ // return (loadWordAligned32(addr) << 24) >> 24;
+ // case 1:
+ // return (loadWordAligned32(addr) << 16) >> 24;
+ // case 2:
+ // return (loadWordAligned32(addr) << 8) >> 24;
+ // case 3:
+ // return loadWordAligned32(addr) >> 24;
+ // }
+ }
+
+ /**
+ * Perform a byte load where the zero extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the zero extended result
+ */
+ public int loadUnsigned8(int addr) {
+ return (loadWordAligned32(addr) >> ((3 - (addr & 3)) << 3)) & 0xFF;
+ // switch(addr & 3) {
+ // default:
+ // return loadWordAligned32(addr) & 0xFF;
+ // case 1:
+ // return (loadWordAligned32(addr) >> 8) & 0xFF;
+ // case 2:
+ // return (loadWordAligned32(addr) >> 16) & 0xFF;
+ // case 3:
+ // return loadWordAligned32(addr) >>> 24;
+ // }
+ }
+
+ /**
+ * Perform a 16bit load where the sign extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the sign extended result
+ */
+ public int loadSigned16(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAligned32(addr) >> 16;
+ case 1:
+ return (loadWordAligned32(addr) << 8) >> 16;
+ case 2:
+ return (loadWordAligned32(addr) << 16) >> 16;
+ case 3: // 2 loads to deal with spanning int problem
+ return ((loadWordAligned32(addr) << 24) >> 16)
+ | (loadWordAligned32(addr + 1) >>> 24);
+ }
+ }
+
+ /**
+ * Perform a 16bit load where the zero extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the zero extended result
+ */
+ public int loadUnsigned16(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAligned32(addr) >>> 16;
+ case 1:
+ return (loadWordAligned32(addr) >> 8) & 0xFFFF;
+ case 2:
+ return loadWordAligned32(addr) & 0xFFFF;
+ case 3: // 2 loads to deal with spanning int problem
+ return ((loadWordAligned32(addr) << 8) & 0xFF00)
+ | loadWordAligned32(addr + 1) >>> 24;
+ }
+ }
+
+ /**
+ * Perform a 32bit load
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int load32(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAligned32(addr);
+ case 1: // 2 loads to deal with spanning int problem
+ return (loadWordAligned32(addr + 3) >>> 24)
+ | (loadWordAligned32(addr) << 8);
+ case 2: // 2 loads to deal with spanning int problem
+ return (loadWordAligned32(addr + 2) >>> 16)
+ | (loadWordAligned32(addr) << 16);
+ case 3: // 2 loads to deal with spanning int problem
+ return (loadWordAligned32(addr + 1) >>> 8)
+ | (loadWordAligned32(addr) << 24);
+ }
+ }
+
+ /**
+ * Perform a 8bit load from memory that must be executable
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int loadInstruction8(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAlignedInstruction32(addr) >>> 24;
+ case 1:
+ return (loadWordAlignedInstruction32(addr) >> 16) & 0xFF;
+ case 2:
+ return (loadWordAlignedInstruction32(addr) >> 8) & 0xFF;
+ case 3:
+ return loadWordAlignedInstruction32(addr) & 0xFF;
+ }
+ }
+
+ @Override
+ public int loadInstruction16(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAlignedInstruction32(addr) >>> 16;
+ case 1:
+ return (loadWordAlignedInstruction32(addr) >> 8) & 0xFFFF;
+ case 2:
+ return loadWordAlignedInstruction32(addr) & 0xFFFF;
+ case 3: // 2 loads to deal with spanning int problem
+ return ((loadWordAlignedInstruction32(addr) << 8) & 0xFF00)
+ | (loadWordAlignedInstruction32(addr + 1) >>> 25);
+ }
+ }
+
+ /**
+ * Perform a 32bit load from memory that must be executable
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int loadInstruction32(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAlignedInstruction32(addr);
+ case 1: // 2 loads to deal with spanning int problem
+ return (loadWordAlignedInstruction32(addr + 3) >>> 24)
+ | (loadWordAlignedInstruction32(addr) << 8);
+ case 2: // 2 loads to deal with spanning int problem
+ return (loadWordAlignedInstruction32(addr + 2) >>> 16)
+ | (loadWordAlignedInstruction32(addr) << 16);
+ case 3: // 2 loads to deal with spanning int problem
+ return (loadWordAlignedInstruction32(addr + 1) >>> 8)
+ | (loadWordAlignedInstruction32(addr) << 24);
+ }
+ }
+
+ /**
+ * Perform a 32bit aligned store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ final protected void storeWordAligned32(int addr, int value) {
+ writableMemory[getPTE(addr)][getOffset(addr)] = value;
+ }
+
+ /**
+ * Perform a 32bit load, from writable memory, where addr is word aligned
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ final protected int loadWordAligned32forWrite(int addr) {
+ return writableMemory[getPTE(addr)][getOffset(addr)];
+ }
+
+ /**
+ * Perform a byte store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public void store8(int addr, int value) {
+ switch (addr & 3) {
+ default:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0x00FFFFFF)
+ | (value << 24));
+ break;
+ case 1:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFF00FFFF)
+ | ((value & 0xFF) << 16));
+ break;
+ case 2:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFFFF00FF)
+ | ((value & 0xFF) << 8));
+ break;
+ case 3:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFFFFFF00)
+ | (value & 0xFF));
+ break;
+ }
+ }
+
+ /**
+ * Perform a 16bit store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public void store16(int addr, int value) {
+ switch (addr & 3) {
+ default:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0x0000FFFF)
+ | (value << 16));
+ break;
+ case 1:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFF0000FF)
+ | ((value & 0xFFFF) << 8));
+ break;
+ case 2:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFFFF0000)
+ | (value & 0xFFFF));
+ break;
+ case 3:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFFFFFF00)
+ | ((value >> 8) & 0xFF));
+ storeWordAligned32(addr + 1,
+ (loadWordAligned32forWrite(addr + 1) & 0x00FFFFFF)
+ | (value << 24));
+ break;
+ }
+ }
+
+ /**
+ * Perform a 32bit store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public void store32(int addr, int value) {
+ switch (addr & 3) {
+ default:
+ storeWordAligned32(addr, value);
+ break;
+ case 1:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFF000000)
+ | (value >>> 8));
+ storeWordAligned32(addr + 3,
+ (loadWordAligned32forWrite(addr + 3) & 0x00FFFFFF) | (value << 24));
+ break;
+ case 2:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFFFF0000)
+ | (value >>> 16));
+ storeWordAligned32(addr + 2,
+ (loadWordAligned32forWrite(addr + 2) & 0x0000FFFF) | (value << 16));
+ break;
+ case 3:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFFFFFF00)
+ | (value >>> 24));
+ storeWordAligned32(addr + 1,
+ (loadWordAligned32forWrite(addr + 1) & 0x000000FF) | (value << 8));
+ break;
+ }
+ }
+}
Modified: src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java 2007-08-24 17:51:46 UTC (rev 173)
+++ src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java 2007-08-27 15:14:38 UTC (rev 174)
@@ -13,7 +13,6 @@
import org.binarytranslator.DBT;
import org.binarytranslator.DBT_Options;
import org.binarytranslator.generic.fault.SegmentationFault;
-import org.jikesrvm.VM_Configuration;
import org.vmmagic.pragma.Inline;
/**
@@ -283,12 +282,8 @@
* @return native endian read int
*/
protected int readInt(RandomAccessFile file) throws java.io.IOException {
- if (VM_Configuration.BuildForPowerPC) {
- return file.readInt(); // NB this will always read in big-endian format
- } else {
- return file.readUnsignedByte() | (file.readUnsignedByte() << 8)
- | (file.readUnsignedByte() << 16) | (file.readByte() << 24);
- }
+ return file.readUnsignedByte() | (file.readUnsignedByte() << 8)
+ | (file.readUnsignedByte() << 16) | (file.readByte() << 24);
}
/**
Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_File.java
===================================================================
--- src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-08-24 17:51:46 UTC (rev 173)
+++ src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-08-27 15:14:38 UTC (rev 174)
@@ -22,7 +22,23 @@
import org.binarytranslator.generic.os.process.ProcessSpace;
public class ELF_File {
+
+ /** Represents accepted ELF byte orders. */
+ public enum ByteOrder implements IdentifiedEnum {
+ LittleEndian(1),
+ BigEndian(2);
+
+ private int identifier;
+
+ private ByteOrder(int identifier) {
+ this.identifier = identifier;
+ }
+ public int getIdentifier() {
+ return identifier;
+ }
+ }
+
/** Wrapper class used for reading the ELF file with the required endianness */
private BinaryReader reader;
@@ -31,6 +47,10 @@
/** Program segment headers */
private SegmentHeader segmentHeaders[];
+
+ public ByteOrder getByteOrder() {
+ return header.byteOrder;
+ }
/**
* Debug information
@@ -60,9 +80,9 @@
* @return
* An ELF_BinaryReader, that hides the details of the byte order.
*/
- public static BinaryReader create(ELF_Identity.ByteOrder byteOrder, RandomAccessFile file) {
+ public static BinaryReader create(ByteOrder byteOrder, RandomAccessFile file) {
- if (byteOrder == ELF_Identity.ByteOrder.BigEndian)
+ if (byteOrder == ByteOrder.BigEndian)
return new NonSwappingReader(file);
else
return new ByteSwappingReader(file);
@@ -296,22 +316,6 @@
}
}
- /** 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;
@@ -334,13 +338,13 @@
private static final byte ELF_MAGIC_VALUE[] = { 0x7f, 'E', 'L','F' };
/** Specifies the size of an address within this elf.*/
- private AddressSize addressSize;
+ AddressSize addressSize;
/** The byte order used by this elf.*/
- private ByteOrder byteOrder;
+ ByteOrder byteOrder;
/** The ABI that is used by this ELF.*/
- private byte abi;
+ byte abi;
/**
* Construct/read ELF identity
Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java
===================================================================
--- src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-08-24 17:51:46 UTC (rev 173)
+++ src/org/binarytranslator/generic/os/loader/elf/ELF_Loader.java 2007-08-27 15:14:38 UTC (rev 174)
@@ -1,7 +1,6 @@
package org.binarytranslator.generic.os.loader.elf;
import java.io.IOException;
-
import org.binarytranslator.DBT_Options;
import org.binarytranslator.generic.os.loader.Loader;
import org.binarytranslator.generic.os.process.ProcessSpace;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-24 17:51:44
|
Revision: 173
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=173&view=rev
Author: michael_baer
Date: 2007-08-24 10:51:46 -0700 (Fri, 24 Aug 2007)
Log Message:
-----------
- Missing from last commit
Modified Paths:
--------------
src/org/binarytranslator/DBT_Options.java
src/org/binarytranslator/Main.java
src/org/binarytranslator/generic/decoder/CodeTranslator.java
src/org/binarytranslator/generic/memory/CallBasedMemory.java
src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-24 17:08:31 UTC (rev 172)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-24 17:51:46 UTC (rev 173)
@@ -310,7 +310,7 @@
input = input.substring(pos + 1);
}
- if (input.length() > 1) {
+ if (input.length() >= 1) {
state.onText(input);
}
}
Modified: src/org/binarytranslator/Main.java
===================================================================
--- src/org/binarytranslator/Main.java 2007-08-24 17:08:31 UTC (rev 172)
+++ src/org/binarytranslator/Main.java 2007-08-24 17:51:46 UTC (rev 173)
@@ -86,6 +86,10 @@
return;
}
+ if (DBT_Options.buildForSunVM) {
+ System.err.println("WARNING: This build was done for the SUN JVM and does only support interpretation, but not binary translation. Set DBT_Options.buildForSunVM to false to build for the Jikes RVM.");
+ }
+
if (DBT.VerifyAssertions) {
System.err.println("WARNING: Assertions are enabled.");
}
Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java
===================================================================
--- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-24 17:08:31 UTC (rev 172)
+++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-24 17:51:46 UTC (rev 173)
@@ -765,7 +765,7 @@
* supposedly a CALL or RETURN
*/
- boolean decision = DBT_Options.singleInstrTranslation == false && jump.type == BranchType.DIRECT_BRANCH && !shallTraceStop();
+ boolean decision = DBT_Options.singleInstrTranslation == false && !shallTraceStop();
if (!decision) {
@@ -778,10 +778,14 @@
return false;
}
- //only query the code cache if we have to
- DBT_Trace compiledTrace = ps.codeCache.tryGet(targetPc);
- decision = (compiledTrace == null || compiledTrace.getNumberOfInstructions() < 20) ;
+ decision = jump.type == BranchType.DIRECT_BRANCH;
+ if (!decision) {
+ //only query the code cache if we have to
+ DBT_Trace compiledTrace = ps.codeCache.tryGet(targetPc);
+ decision = (compiledTrace != null && compiledTrace.getNumberOfInstructions() < 30);
+ }
+
if (DBT_Options.debugBranchResolution) {
String text = (!decision ? "Not inlining " : "Inlining ");
text += jump.type + " to 0x" + Integer.toHexString(targetPc);
Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-08-24 17:08:31 UTC (rev 172)
+++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-08-24 17:51:46 UTC (rev 173)
@@ -104,12 +104,12 @@
/**
* The generation context we're translating within
*/
- private OPT_GenerationContext gc;
+ protected OPT_GenerationContext gc;
/**
* Register that references the memory object
*/
- OPT_Register memory;
+ protected OPT_Register memory;
/**
* Constructor
@@ -158,7 +158,7 @@
}
/**
- * Generate memory prologue,... for the beignning of a trace. e.g. Loading the
+ * Generate memory prologue,... for the beginning of a trace. e.g. Loading the
* page table into a register
*/
public void initTranslate(CodeTranslator helper) {
@@ -202,8 +202,7 @@
if (DBT_Options.inlineCallbasedMemory) {
translator.appendInlinedCall(s);
}
- else
- {
+ else {
s.position = gc.inlineSequence;
s.bcIndex = bcIndex;
translator.appendInstruction(s);
@@ -395,45 +394,6 @@
}
/**
- * Generate the IR code for a byte store
- *
- * @param src
- * the register that holds the value to store
- * @param addr
- * the address of the value to store
- */
- public void translateCallBasedStore8(OPT_Operand addr,
- OPT_RegisterOperand src) {
- translateStore(store8, DBT_Trace.MEMORY_STORE8, addr, src);
- }
-
- /**
- * Generate the IR code for a 16bit store
- *
- * @param src
- * the register that holds the value to store
- * @param addr
- * the address of the value to store
- */
- public void translateCallBasedStore16(OPT_Operand addr,
- OPT_RegisterOperand src) {
- translateStore(store16, DBT_Trace.MEMORY_STORE16, addr, src);
- }
-
- /**
- * Generate the IR code for a 32bit store
- *
- * @param src
- * the register that holds the value to store
- * @param addr
- * the address of the value to store
- */
- public void translateCallBasedStore32(OPT_Operand addr,
- OPT_RegisterOperand src) {
- translateStore(store32, DBT_Trace.MEMORY_STORE32, addr, src);
- }
-
- /**
* Get method reference if linking a call
*
* @param callAddress
Modified: src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java 2007-08-24 17:08:31 UTC (rev 172)
+++ src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java 2007-08-24 17:51:46 UTC (rev 173)
@@ -87,7 +87,7 @@
* Return the offset part of the address
*/
@Inline
- protected int getOffset(int address) {
+ private static final int getOffset(int address) {
return (address & (PAGE_SIZE - 1)) >>> 2;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-24 17:08:32
|
Revision: 172
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=172&view=rev
Author: michael_baer
Date: 2007-08-24 10:08:31 -0700 (Fri, 24 Aug 2007)
Log Message:
-----------
- Fixed a bug where a parameter that is only one char would not be parsed correctly
- Fixed a bug that I recently introduced on loads with negative offset and writeback
- various smaller fixes
Modified Paths:
--------------
src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java
src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java
src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java
Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-21 16:12:27 UTC (rev 171)
+++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-24 17:08:31 UTC (rev 172)
@@ -556,28 +556,13 @@
return super.inlineBranchInstruction(targetPc, jump);
case DynamicJumps:
- if (jump.type == BranchType.INDIRECT_BRANCH)
- return true;
- else
- return super.inlineBranchInstruction(targetPc, jump);
+ return jump.type == BranchType.INDIRECT_BRANCH;
- case FunctionCalls:
- if (jump.type == BranchType.CALL)
- return true;
- else
- return super.inlineBranchInstruction(targetPc, jump);
+ case DirectBranches:
+ return jump.type == BranchType.DIRECT_BRANCH;
- case FunctionReturns:
- if (jump.type == BranchType.CALL)
- return true;
- else
- return super.inlineBranchInstruction(targetPc, jump);
-
case Functions:
- if (jump.type == BranchType.CALL || jump.type == BranchType.RETURN)
- return true;
- else
- return super.inlineBranchInstruction(targetPc, jump);
+ return jump.type == BranchType.CALL || jump.type == BranchType.RETURN;
case All:
return true;
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-08-21 16:12:27 UTC (rev 171)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-08-24 17:08:31 UTC (rev 172)
@@ -248,7 +248,8 @@
if (instr.writeBack())
address += '!';
- } else {
+ }
+ else {
address += "], ";
if (!instr.positiveOffset())
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-08-21 16:12:27 UTC (rev 171)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_InstructionDecoder.java 2007-08-24 17:08:31 UTC (rev 172)
@@ -368,10 +368,12 @@
<T> T decode(short instr, ARM_InstructionFactory<T> factory) {
//bit9==bit10==bit11==1?
if ((instr & 0x0E00) == 0x0E00) {
- if (Utils.getBit(instr, 8))
+ if (Utils.getBit(instr, 8)) {
return factory.createSoftwareInterrupt(instr);
- else
+ }
+ else {
return factory.createUndefinedInstruction(instr);
+ }
}
return factory.createBranch(instr);
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-21 16:12:27 UTC (rev 171)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-24 17:08:31 UTC (rev 172)
@@ -11,8 +11,7 @@
NoInlining,
Default,
Functions,
- FunctionCalls,
- FunctionReturns,
+ DirectBranches,
DynamicJumps,
All,
}
@@ -40,7 +39,6 @@
/** Sets the memory model that ARM shall use. */
public static MemoryModel memoryModel = MemoryModel.IntAddressed;
-
public static void parseOption(String key, String value) {
if (key.equalsIgnoreCase("optimizeByProfiling")) {
optimizeTranslationByProfiling = Boolean.parseBoolean(value);
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-21 16:12:27 UTC (rev 171)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-24 17:08:31 UTC (rev 172)
@@ -8,7 +8,6 @@
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.binarytranslator.generic.branchprofile.BranchProfile.BranchType;
import org.jikesrvm.classloader.VM_Atom;
import org.jikesrvm.classloader.VM_MemberReference;
@@ -2205,7 +2204,7 @@
return positiveOffset;
}
else {
- OPT_RegisterOperand tmp = arm2ir.getTempInt(0);
+ OPT_RegisterOperand tmp = arm2ir.getTempInt(1);
arm2ir.appendInstruction(Unary.create(INT_NEG, tmp, positiveOffset));
return tmp.copy();
}
@@ -2241,26 +2240,14 @@
}
public void translate() {
- //should we simulate a user-mode memory access? If yes, store the current mode and fake a switch
- //to user mode.
-
- //stores the current operating mode
- OPT_RegisterOperand currentOperatingMode = null;
-
+ //should we simulate a user-mode memory access? If yes, handle this using the interpreter
if (i.forceUserMode) {
- OPT_Instruction call_getOperatingMode = createCallToRegisters("getOperatingMode", "()A", 0);
- currentOperatingMode = arm2ir.getTempOperatingMode();
-
- Call.setResult(call_getOperatingMode, currentOperatingMode);
- arm2ir.appendCustomCall(call_getOperatingMode);
-
- OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1);
- Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, arm2ir.getTempOperatingMode(OperatingMode.USR));
-
- arm2ir.appendCustomCall(call_setOperatingModeWithoutRegisterLayout);
+ arm2ir.appendInterpretedInstruction(pc, lazy);
+ arm2ir.appendTraceExit(lazy, arm2ir.getRegister(ARM_Registers.PC));
+ return;
}
- //get the address of the memory, that we're supposed access
+ //get the address of the memory, that we're supposed to access
OPT_Operand address = resolveAddress();
if (i.isLoad) {
@@ -2275,10 +2262,6 @@
//according to the ARM reference, the last two bits cause the value to be right-rotated
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.appendInstruction(Move.create(INT_MOVE, adrCopy, address.copy()));
//rotation = (address & 0x3) * 8
arm2ir.appendInstruction(Binary.create(INT_AND, rotation, address.copy(), new OPT_IntConstantOperand(0x3)));
@@ -2299,9 +2282,6 @@
//continue with the remainder of the instruction
arm2ir.setCurrentBlock(remainderBlock);
-
- //allow further usage of the memory address
- address = adrCopy;
break;
case HalfWord:
@@ -2345,13 +2325,6 @@
throw new RuntimeException("Unexpected memory size: " + i.size);
}
}
-
- //if we were writing in user mode, then switch back to our previous operating mode
- if (i.forceUserMode) {
- OPT_Instruction call_setOperatingModeWithoutRegisterLayout = createCallToRegisters("setOperatingModeWithoutRegisterLayout", "(A)", 1);
- Call.setParam(call_setOperatingModeWithoutRegisterLayout, 1, currentOperatingMode);
- arm2ir.appendCustomCall(call_setOperatingModeWithoutRegisterLayout);
- }
//should the memory address, which we accessed, be written back into a register?
//This is used for continuous memory accesses
Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-21 16:12:27 UTC (rev 171)
+++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-24 17:08:31 UTC (rev 172)
@@ -58,7 +58,6 @@
if (registers.getThumbMode()) {
int instrAddr = getCurrentInstructionAddress() & 0xFFFFFFFE;
- System.out.println("Thumb syscall at: " + instrAddr);
short instruction = (short)memory.loadInstruction16(instrAddr);
instr = ARM_InstructionDecoder.Thumb.decode(instruction);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-21 16:12:25
|
Revision: 171
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=171&view=rev
Author: michael_baer
Date: 2007-08-21 09:12:27 -0700 (Tue, 21 Aug 2007)
Log Message:
-----------
- Fix bug in loadInstruction16 that was also present in loadUnsigned16
Modified Paths:
--------------
src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java
Modified: src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java 2007-08-21 15:29:38 UTC (rev 170)
+++ src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java 2007-08-21 16:12:27 UTC (rev 171)
@@ -519,11 +519,11 @@
public int loadInstruction16(int addr) {
switch (addr & 3) {
default:
- return loadWordAlignedInstruction32(addr) >>> 16;
+ return loadWordAlignedInstruction32(addr) & 0xFFFF;
case 1:
return (loadWordAlignedInstruction32(addr) >> 8) & 0xFFFF;
case 2:
- return loadWordAlignedInstruction32(addr) & 0xFFFF;
+ return (loadWordAlignedInstruction32(addr) >> 16) & 0xFFFF;
case 3: // 2 loads to deal with spanning int problem
return (loadWordAlignedInstruction32(addr) >>> 24)
| ((loadWordAlignedInstruction32(addr + 1) << 8) & 0xFF00);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-21 15:35:45
|
Revision: 170
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=170&view=rev
Author: michael_baer
Date: 2007-08-21 08:29:38 -0700 (Tue, 21 Aug 2007)
Log Message:
-----------
- Increase ARM heap & stack size to 4MB when loading embedded system images
- Move some OPT_Operand.copy() calls around
Modified Paths:
--------------
src/org/binarytranslator/DBT_Options.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/image/ARM_ImageProcessSpace.java
src/org/binarytranslator/generic/decoder/CodeTranslator.java
src/org/binarytranslator/generic/execution/InterpreterController.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-20 21:08:34 UTC (rev 169)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-21 15:29:38 UTC (rev 170)
@@ -25,7 +25,7 @@
public final static boolean buildForSunVM = false;
/** Enable the profiling of application during interpretation? */
- public final static boolean profileDuringInterpretation = true;
+ public final static boolean profileDuringInterpretation = false;
/** Are unimplemented system calls fatal? */
public final static boolean unimplementedSystemCallsFatal = false;
Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-20 21:08:34 UTC (rev 169)
+++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-21 15:29:38 UTC (rev 170)
@@ -413,7 +413,7 @@
appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand()));
}
else {
- appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.LOWER().flipCode(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.LOWER().flipCode(), new OPT_BranchProfileOperand()));
}
break;
@@ -431,7 +431,7 @@
case Add:
case LogicalOpAfterAdd:
if (ARM_Options.useOptimizedFlags) {
- appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
}
else {
OPT_RegisterOperand tmp1 = getTempInt(5);
@@ -442,7 +442,7 @@
appendInstruction(Binary.create(INT_SUB, tmp2.copyRO(), new OPT_IntConstantOperand(Integer.MIN_VALUE), op2.copy()));
appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, tmp_bool.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.GREATER_EQUAL(), new OPT_BranchProfileOperand(), op1.copy(), tmp1.copy(), OPT_ConditionOperand.GREATER(), OPT_BranchProfileOperand.unlikely()));
appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, getFlag(Flag.Overflow), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS() , new OPT_BranchProfileOperand(), op1.copy(), tmp2.copy(), OPT_ConditionOperand.LESS(), OPT_BranchProfileOperand.unlikely()));
- appendInstruction(Binary.create(INT_OR, getFlag(Flag.Overflow), getFlag(Flag.Overflow), tmp_bool.copy()));
+ appendInstruction(Binary.create(INT_OR, flagRegister, getFlag(Flag.Overflow), tmp_bool.copy()));
}
break;
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-20 21:08:34 UTC (rev 169)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-21 15:29:38 UTC (rev 170)
@@ -186,10 +186,10 @@
ARM_Translator translator, OperandWrapper operand) {
ResolvedOperand result = new ResolvedOperand_WithShifterCarryOut(translator, operand);
- return result.getValue();
+ return result.getValue().copy();
}
- public final OPT_Operand getValue() {
+ private final OPT_Operand getValue() {
return value;
}
@@ -235,7 +235,7 @@
else {
OPT_RegisterOperand tmp = translator.arm2ir.getTempInt(9);
translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, translator.arm2ir.getRegister(operand.getRegister()), new OPT_IntConstantOperand(operand.getOffset())));
- value = tmp.copy();
+ value = tmp;
}
return;
@@ -382,7 +382,7 @@
curBlock.insertOut(block1);
OPT_Operand carryFlag = translator.arm2ir.readCarryFlag(translator.lazy);
translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand.copy(), new OPT_IntConstantOperand(1)));
- translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, translator.arm2ir.getTempValidation(0), carryFlag, new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, carryFlag, new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand()));
//Block 1
translator.arm2ir.setCurrentBlock(block1);
@@ -519,15 +519,15 @@
//block 2 - shift < 32 && shift != 0
translator.arm2ir.setCurrentBlock(block2);
block2.insertOut(nextBlock);
- translator.arm2ir.appendInstruction(Binary.create(INT_SHR, resultRegister, shiftedOperand, shiftAmount.copy()) );
+ translator.arm2ir.appendInstruction(Binary.create(INT_SHR, resultRegister, shiftedOperand.copy(), shiftAmount.copy()) );
translator.arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, shiftAmount.copy(), new OPT_IntConstantOperand(-1)) );
- translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, tmp.copy());
+ translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand.copy(), tmp.copy());
translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget()));
//block 3 - shift >= 32
translator.arm2ir.setCurrentBlock(block3);
block3.insertOut(nextBlock);
- translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand, 31);
+ translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand.copy(), 31);
translator.arm2ir.appendInstruction(Binary.create(INT_MUL, resultRegister.copyRO(), getShifterCarryOutTarget(), new OPT_IntConstantOperand(-1)) ); //creates either 0xFFFFFFFF if the bit is set, or 0 otherwise
translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget()));
@@ -563,7 +563,7 @@
//block 2 - Shift != 0 && Shift < 32
translator.arm2ir.setCurrentBlock(block2);
block2.insertOut(nextBlock);
- translator.arm2ir.appendInstruction(Binary.create(INT_SUB, tmp, new OPT_IntConstantOperand(32), shiftAmount) );
+ translator.arm2ir.appendInstruction(Binary.create(INT_SUB, tmp, new OPT_IntConstantOperand(32), shiftAmount.copy() ) );
translator.arm2ir.appendBitTest(getShifterCarryOutTarget(), shiftedOperand.copy(), tmp.copy());
translator.arm2ir.appendInstruction(Binary.create(INT_SHL, resultRegister, shiftedOperand.copy(), shiftAmount.copy()));
translator.arm2ir.appendInstruction(Goto.create(GOTO, nextBlock.makeJumpTarget()));
@@ -1600,7 +1600,7 @@
@Override
public void translate() {
- //Call Integer.numberOfLeadingZeros() to obtain the result of this operation
+ //Call Integer.numberOfLeadingZeros() to obtain the result of this operation
OPT_RegisterOperand result = getResultRegister();
VM_TypeReference IntegerType = VM_TypeReference
@@ -1647,7 +1647,7 @@
//swap exchanges the value of a memory address with the value in a register
if (!i.swapByte) {
ps.memory.translateLoad32(memAddr, tmp);
- ps.memory.translateStore32(memAddr, arm2ir.getRegister(i.Rm));
+ ps.memory.translateStore32(memAddr.copy(), arm2ir.getRegister(i.Rm));
//according to the ARM architecture reference, the value loaded from a memory address is rotated
//by the number of ones in the first two bits of the address
@@ -1659,8 +1659,8 @@
arm2ir.appendRotateRight(result, tmp.copy(), rotation.copy());
}
else {
- ps.memory.translateLoadUnsigned8(memAddr.copy(), tmp);
- ps.memory.translateStore8(memAddr, arm2ir.getRegister(i.Rm));
+ ps.memory.translateLoadUnsigned8(memAddr, tmp);
+ ps.memory.translateStore8(memAddr.copy(), arm2ir.getRegister(i.Rm));
arm2ir.appendInstruction(Move.create(INT_MOVE, result, tmp.copy()));
}
}
@@ -1959,7 +1959,7 @@
//set the correct processor mode (thumb or not)
OPT_Instruction s = createCallToRegisters("setThumbMode", "(Z)V", 1);
- Call.setParam(s, 1, enableThumb);
+ Call.setParam(s, 1, enableThumb.copy());
arm2ir.appendCustomCall(s);
//jump to the target address. Because we might have switched to thumb mode, we are
@@ -1999,7 +1999,7 @@
arm2ir.appendInstruction(Binary.create(INT_MUL, tmp, operand1, operand2));
OPT_Operand operand3 = arm2ir.getRegister(i.Rn);
- arm2ir.appendInstruction(Binary.create(INT_ADD, result.copyRO(), tmp.copy(), operand3));
+ arm2ir.appendInstruction(Binary.create(INT_ADD, result, tmp.copy(), operand3));
}
else {
arm2ir.appendInstruction(Binary.create(INT_MUL, result, operand1, operand2));
@@ -2050,7 +2050,7 @@
}
//multiply the two operands
- arm2ir.appendInstruction(Binary.create(LONG_MUL, result.copyRO(), operand1.copy(), operand2.copy()));
+ arm2ir.appendInstruction(Binary.create(LONG_MUL, result, operand1.copy(), operand2.copy()));
if (i.accumulate) {
//treat the accum. value as an unsigned value
@@ -2247,7 +2247,7 @@
//stores the current operating mode
OPT_RegisterOperand currentOperatingMode = null;
- if (i.forceUserMode) {
+ if (i.forceUserMode) {
OPT_Instruction call_getOperatingMode = createCallToRegisters("getOperatingMode", "()A", 0);
currentOperatingMode = arm2ir.getTempOperatingMode();
@@ -2364,7 +2364,7 @@
else {
//add the offset to the base address and write the result back into Rn
OPT_Operand resolvedOffset = resolveOffset();
- arm2ir.appendInstruction(Binary.create(INT_ADD, writeBackTarget, address, resolvedOffset));
+ arm2ir.appendInstruction(Binary.create(INT_ADD, writeBackTarget, address.copy(), resolvedOffset));
}
}
Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-20 21:08:34 UTC (rev 169)
+++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-21 15:29:38 UTC (rev 170)
@@ -14,8 +14,8 @@
public class ARM_ImageProcessSpace extends ARM_ProcessSpace {
private AngelSystemCalls sysCalls;
- private final int STACK_SIZE = 4096 * 100;
- private final int HEAP_SIZE = 4096 * 100;
+ private final int STACK_SIZE = 4096 * 1000;
+ private final int HEAP_SIZE = 4096 * 1000;
public ARM_ImageProcessSpace() {
super();
Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java
===================================================================
--- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-20 21:08:34 UTC (rev 169)
+++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-21 15:29:38 UTC (rev 170)
@@ -695,7 +695,7 @@
unresolvedDynamicBranches.add(unresolvedInfo);
setCurrentBlock(fallThrough);
- appendRecordUncaughtBranch(currentPC, targetAddress.copyRO(), branchType, retAddr);
+ appendRecordUncaughtBranch(currentPC, targetAddress, branchType, retAddr);
appendTraceExit((Laziness) lazyStateAtJump.clone(), targetAddress);
}
Modified: src/org/binarytranslator/generic/execution/InterpreterController.java
===================================================================
--- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-08-20 21:08:34 UTC (rev 169)
+++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-08-21 15:29:38 UTC (rev 170)
@@ -20,7 +20,8 @@
while (!ps.finished) {
- Interpreter.Instruction instruction = interpreter.decode(pc);
+ Interpreter.Instruction instruction = interpreter.decode(pc);
+ //System.out.println(String.format("[%x] %s", pc, instruction.toString()));
instruction.execute();
int nextInstruction = instruction.getSuccessor(pc);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-20 21:08:44
|
Revision: 169
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=169&view=rev
Author: michael_baer
Date: 2007-08-20 14:08:34 -0700 (Mon, 20 Aug 2007)
Log Message:
-----------
- Introduce option to use optimized flag handling instructions
- otherwise resorting to traditional flag evaluation
Modified Paths:
--------------
src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
src/org/binarytranslator/arch/arm/decoder/ARM_Options.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-08-20 14:12:59 UTC (rev 168)
+++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-20 21:08:34 UTC (rev 169)
@@ -198,6 +198,7 @@
/** Called when the ARM flags shall be set by a SUB operation. This sets all ARM flags. */
public abstract void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2);
+ public abstract void appendReverseSubFlags(ARM_Laziness lazy, OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs);
}
/** Implements a flag behavior that will immediately evaluate all flag values. */
@@ -209,7 +210,23 @@
appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Zero), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), result.copy(), op1.copy(), OPT_ConditionOperand.LOWER(), new OPT_BranchProfileOperand()));
appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
- appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
+
+ if (ARM_Options.useOptimizedFlags) {
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
+ }
+ else {
+ //resolve overflow
+ OPT_RegisterOperand overflow = getFlag(Flag.Overflow);
+ OPT_RegisterOperand tmp1 = getTempInt(5);
+ OPT_RegisterOperand tmp2 = getTempInt(6);
+ OPT_RegisterOperand tmp_bool = gc.temps.makeTempBoolean();
+
+ appendInstruction(Binary.create(INT_SUB, tmp1.copyRO(), new OPT_IntConstantOperand(Integer.MAX_VALUE), op2.copy()));
+ appendInstruction(Binary.create(INT_SUB, tmp2.copyRO(), new OPT_IntConstantOperand(Integer.MIN_VALUE), op2.copy()));
+ appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, tmp_bool.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.GREATER_EQUAL(), new OPT_BranchProfileOperand(), op1.copy(), tmp1.copy(), OPT_ConditionOperand.GREATER(), OPT_BranchProfileOperand.unlikely()));
+ appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, overflow.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS() , new OPT_BranchProfileOperand(), op1.copy(), tmp2.copy(), OPT_ConditionOperand.LESS(), OPT_BranchProfileOperand.unlikely()));
+ appendInstruction(Binary.create(INT_OR, overflow.copyRO(), overflow.copy(), tmp_bool.copy()));
+ }
}
@Override
@@ -223,9 +240,29 @@
@Override
public void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Zero), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
- appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
- appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand()));
- appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+
+ if (ARM_Options.useOptimizedFlags) {
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely()));
+ }
+ else {
+ //resolve carry
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.LOWER().flipCode(), new OPT_BranchProfileOperand()));
+
+ //resolve overflow
+ OPT_RegisterOperand overflow = getFlag(Flag.Overflow);
+ OPT_RegisterOperand tmp1 = getTempInt(5);
+ OPT_RegisterOperand tmp2 = getTempInt(6);
+ OPT_RegisterOperand tmp_bool = gc.temps.makeTempBoolean();
+
+ appendInstruction(Binary.create(INT_ADD, tmp1.copyRO(), new OPT_IntConstantOperand(Integer.MIN_VALUE), op2.copy()));
+ appendInstruction(Binary.create(INT_ADD, tmp2.copyRO(), new OPT_IntConstantOperand(Integer.MAX_VALUE), op2.copy()));
+
+ appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, tmp_bool.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.GREATER_EQUAL(), new OPT_BranchProfileOperand(), op1.copy(), tmp1.copy(), OPT_ConditionOperand.LESS(), OPT_BranchProfileOperand.unlikely()));
+ appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, overflow.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS() , new OPT_BranchProfileOperand(), op1.copy(), tmp2.copy(), OPT_ConditionOperand.GREATER(), OPT_BranchProfileOperand.unlikely()));
+ appendInstruction(Binary.create(INT_OR, overflow.copyRO(), overflow.copy(), tmp_bool.copy()));
+ }
}
@Override
@@ -237,6 +274,11 @@
public void onFlagWrite(Flag flag, ARM_Laziness lazy) {
//nothing to do here, because the flags are already resolved
}
+
+ @Override
+ public void appendReverseSubFlags(ARM_Laziness lazy, OPT_RegisterOperand result, OPT_Operand op1, OPT_Operand op2) {
+ appendSubFlags(lazy, result, op2, op1);
+ }
}
/** Implements a flag behavior that will use lazy evaluation to only determine a flag value
@@ -366,7 +408,13 @@
case LogicalOpAfterSub:
case Sub:
- appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand()));
+
+ if (ARM_Options.useOptimizedFlags) {
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand()));
+ }
+ else {
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.LOWER().flipCode(), new OPT_BranchProfileOperand()));
+ }
break;
default:
@@ -382,12 +430,40 @@
switch (lazy.getOperation()) {
case Add:
case LogicalOpAfterAdd:
- appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
+ if (ARM_Options.useOptimizedFlags) {
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
+ }
+ else {
+ OPT_RegisterOperand tmp1 = getTempInt(5);
+ OPT_RegisterOperand tmp2 = getTempInt(6);
+ OPT_RegisterOperand tmp_bool = gc.temps.makeTempBoolean();
+
+ appendInstruction(Binary.create(INT_SUB, tmp1.copyRO(), new OPT_IntConstantOperand(Integer.MAX_VALUE), op2.copy()));
+ appendInstruction(Binary.create(INT_SUB, tmp2.copyRO(), new OPT_IntConstantOperand(Integer.MIN_VALUE), op2.copy()));
+ appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, tmp_bool.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.GREATER_EQUAL(), new OPT_BranchProfileOperand(), op1.copy(), tmp1.copy(), OPT_ConditionOperand.GREATER(), OPT_BranchProfileOperand.unlikely()));
+ appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, getFlag(Flag.Overflow), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS() , new OPT_BranchProfileOperand(), op1.copy(), tmp2.copy(), OPT_ConditionOperand.LESS(), OPT_BranchProfileOperand.unlikely()));
+ appendInstruction(Binary.create(INT_OR, getFlag(Flag.Overflow), getFlag(Flag.Overflow), tmp_bool.copy()));
+ }
break;
case Sub:
case LogicalOpAfterSub:
- appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely()));
+ if (ARM_Options.useOptimizedFlags) {
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely()));
+ }
+ else {
+ //resolve overflow
+ OPT_RegisterOperand tmp1 = getTempInt(5);
+ OPT_RegisterOperand tmp2 = getTempInt(6);
+ OPT_RegisterOperand tmp_bool = gc.temps.makeTempBoolean();
+
+ appendInstruction(Binary.create(INT_ADD, tmp1.copyRO(), new OPT_IntConstantOperand(Integer.MIN_VALUE), op2.copy()));
+ appendInstruction(Binary.create(INT_ADD, tmp2.copyRO(), new OPT_IntConstantOperand(Integer.MAX_VALUE), op2.copy()));
+
+ appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, tmp_bool.copyRO(), op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.GREATER_EQUAL(), new OPT_BranchProfileOperand(), op1.copy(), tmp1.copy(), OPT_ConditionOperand.LESS(), OPT_BranchProfileOperand.unlikely()));
+ appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, flagRegister, op2.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS() , new OPT_BranchProfileOperand(), op1.copy(), tmp2.copy(), OPT_ConditionOperand.GREATER(), OPT_BranchProfileOperand.unlikely()));
+ appendInstruction(Binary.create(INT_OR, flagRegister.copyRO(), flagRegister.copy(), tmp_bool.copy()));
+ }
break;
default:
@@ -416,6 +492,11 @@
public void onFlagWrite(Flag flag, ARM_Laziness lazy) {
lazy.setValid(flag, true);
}
+
+ @Override
+ public void appendReverseSubFlags(ARM_Laziness lazy, OPT_RegisterOperand result, OPT_Operand op1, OPT_Operand op2) {
+ appendSubFlags(lazy, result, op2, op1);
+ }
}
@Override
@@ -701,6 +782,12 @@
flagBehavior.appendSubFlags(lazy, result, op1, op2);
}
+
+ public void appendReverseSubFlags(ARM_Laziness lazy, OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) {
+ zeroUsed = negativeUsed = carryUsed = overflowUsed = true;
+ flagBehavior.appendReverseSubFlags(lazy, result, lhs, rhs);
+ }
+
public void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
zeroUsed = negativeUsed = carryUsed = overflowUsed = true;
flagBehavior.appendAddFlags(lazy, result, op1, op2);
@@ -846,4 +933,5 @@
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_Options.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-20 14:12:59 UTC (rev 168)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-20 21:08:34 UTC (rev 169)
@@ -24,12 +24,15 @@
/** Set to true to enable a fastpath for the decoding of data processing instructions.. */
public final static boolean DATAPROCESSING_DECODER_FASTPATH = false;
+
+ /** Shall ARM use the optimized BORROW_FROM_SUB() etc. operations? */
+ public static boolean useOptimizedFlags = false;
/** This variable describes, if the translated program shall be optimized using profiling information. */
public static boolean optimizeTranslationByProfiling = false;
/** This variable describes, if the translated program shall be optimized using lazy evaluation.*/
- public static FlagBehaviour flagEvaluation = FlagBehaviour.Lazy;
+ public static FlagBehaviour flagEvaluation = FlagBehaviour.Immediate;
/** Describes the default behaviour for dealing with ARM function calls and indirect jumps. */
public static InliningBehaviour inlining = InliningBehaviour.Default;
@@ -47,7 +50,9 @@
inlining = ARM_Options.InliningBehaviour.valueOf(value);
} else if (key.equalsIgnoreCase("memory")) {
memoryModel = ARM_Options.MemoryModel.valueOf(value);
- }
+ } else if (key.equalsIgnoreCase("optimizedFlags")) {
+ useOptimizedFlags = Boolean.parseBoolean(value);
+ }
else {
throw new Error("Unknown ARM option: " + key);
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-20 14:12:59 UTC (rev 168)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-20 21:08:34 UTC (rev 169)
@@ -843,22 +843,35 @@
case CC:
//return !regs.isCarrySet();
- translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readCarryFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
+ {
+ OPT_Operand carry = arm2ir.readCarryFlag(lazy);
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, carry, OPT_ConditionOperand.NOT_EQUAL());
+ }
break;
case CS:
//return regs.isCarrySet();
- translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readCarryFlag(lazy), OPT_ConditionOperand.EQUAL());
+ {
+ OPT_Operand carry = arm2ir.readCarryFlag(lazy);
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, carry, OPT_ConditionOperand.EQUAL());
+ }
break;
case EQ:
//return regs.isZeroSet();
- translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readZeroFlag(lazy), OPT_ConditionOperand.EQUAL());
+ {
+ OPT_Operand zero = arm2ir.readZeroFlag(lazy);
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, zero, OPT_ConditionOperand.EQUAL());
+ }
break;
case GE:
//return regs.isNegativeSet() == regs.isOverflowSet();
- translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.EQUAL(), arm2ir.readOverflowFlag(lazy));
+ {
+ OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
+ OPT_Operand negative = arm2ir.readNegativeFlag(lazy);
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, negative, OPT_ConditionOperand.EQUAL(), overflow);
+ }
break;
case GT:
@@ -879,17 +892,27 @@
case LT:
//return regs.isNegativeSet() != regs.isOverflowSet();
- translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.readOverflowFlag(lazy));
+ {
+ OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
+ OPT_Operand negative = arm2ir.readNegativeFlag(lazy);
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, negative, OPT_ConditionOperand.NOT_EQUAL(), overflow);
+ }
break;
case MI:
//return regs.isNegativeSet();
- translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.EQUAL());
+ {
+ OPT_Operand negative = arm2ir.readNegativeFlag(lazy);
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, negative, OPT_ConditionOperand.EQUAL());
+ }
break;
case NE:
//return !regs.isZeroSet();
- translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readZeroFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
+ {
+ OPT_Operand zero = arm2ir.readZeroFlag(lazy);
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, zero, OPT_ConditionOperand.NOT_EQUAL());
+ }
break;
case NV:
@@ -899,17 +922,26 @@
case PL:
//return !regs.isNegativeSet();
- translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
+ {
+ OPT_Operand negative = arm2ir.readNegativeFlag(lazy);
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, negative, OPT_ConditionOperand.NOT_EQUAL());
+ }
break;
case VC:
//return !regs.isOverflowSet();
- translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readOverflowFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
+ {
+ OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, overflow, OPT_ConditionOperand.NOT_EQUAL());
+ }
break;
case VS:
//return regs.isOverflowSet();
- translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readOverflowFlag(lazy), OPT_ConditionOperand.EQUAL());
+ {
+ OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, overflow, OPT_ConditionOperand.EQUAL());
+ }
break;
default:
@@ -997,8 +1029,8 @@
private void translateCondition_GT(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet();
+ OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
OPT_Operand negative = arm2ir.readNegativeFlag(lazy);
- OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
OPT_Operand zero = arm2ir.readZeroFlag(lazy);
OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean();
@@ -1010,8 +1042,8 @@
private void translateCondition_LE(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet());
+ OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
OPT_Operand negative = arm2ir.readNegativeFlag(lazy);
- OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
OPT_Operand zero = arm2ir.readZeroFlag(lazy);
OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean();
@@ -1109,11 +1141,14 @@
}
/** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/
- protected final void setSubResult(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) {
+ protected final void setSubResult(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs, boolean wasReverseSub) {
if (i.updateConditionCodes) {
if (i.Rd != ARM_Registers.PC) {
- setSubFlags(result, lhs, rhs);
+ if (wasReverseSub)
+ setReverseSubFlags(result, lhs, rhs);
+ else
+ setSubFlags(result, lhs, rhs);
}
else {
OPT_Instruction s = createCallToRegisters("restoreSPSR2CPSR", "()V", 0);
@@ -1136,7 +1171,12 @@
arm2ir.appendInstruction(Move.create(INT_MOVE, arm2ir.getRegister(i.Rd), result.copy()) );
}
}
+
+ private void setReverseSubFlags(OPT_RegisterOperand result, OPT_Operand lhs, OPT_Operand rhs) {
+ arm2ir.appendReverseSubFlags(lazy, result, lhs, rhs);
+ }
+
/**
* Sets the processor flags according to the result of a sub operation.
* @param result
@@ -1147,7 +1187,6 @@
* The sub's right-hand-side operator.
*/
protected final void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) {
-
arm2ir.appendSubFlags(lazy, result, lhs, rhs);
}
@@ -1294,7 +1333,7 @@
arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2));
- setSubResult(result, operand1, operand2);
+ setSubResult(result, operand1, operand2, false);
}
}
@@ -1313,7 +1352,7 @@
arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand2, operand1));
- setSubResult(result, operand2, operand1);
+ setSubResult(result, operand1, operand2, true);
}
}
@@ -1385,7 +1424,7 @@
//Finally, subtract the second operands from the result
arm2ir.setCurrentBlock(subWithoutCarry);
arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2.copy()));
- setSubResult(result, operand1, operand2);
+ setSubResult(result, operand1, operand2, false);
}
}
@@ -2188,8 +2227,9 @@
return base;
//add the offset to the base register
+ OPT_Operand offset = resolveOffset();
OPT_RegisterOperand tmp = arm2ir.getTempInt(0);
- arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, base, resolveOffset()));
+ arm2ir.appendInstruction(Binary.create(INT_ADD, tmp, base, offset));
if (i.isThumb && i.isLoad && i.Rn == ARM_Registers.PC) {
//with thumb, bit 1 of the address is always ignored - address = address & 0xFFFFFFFC;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-20 14:13:04
|
Revision: 168
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=168&view=rev
Author: michael_baer
Date: 2007-08-20 07:12:59 -0700 (Mon, 20 Aug 2007)
Log Message:
-----------
- Fixed bug in IntAddressed Memory for 16bit unsigned loads
- Renamed IntAddressedMemory to IntAddressedLittleEndian Memory
- Renamed ByteAddressedMemory to ByteAddressedLittleEndian Memory
Modified Paths:
--------------
src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java
src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java
src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java
src/org/binarytranslator/generic/memory/ByteAddressedByteSwapMemory.java
src/org/binarytranslator/generic/memory/IntAddressedByteSwapMemory.java
src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java
Added Paths:
-----------
src/org/binarytranslator/generic/memory/ByteAddressedLittleEndianMemory.java
src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java
Removed Paths:
-------------
src/org/binarytranslator/generic/memory/ByteAddressedMemory.java
src/org/binarytranslator/generic/memory/IntAddressedMemory.java
Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-15 16:24:05 UTC (rev 167)
+++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-20 14:12:59 UTC (rev 168)
@@ -10,8 +10,8 @@
import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace;
import org.binarytranslator.generic.decoder.CodeTranslator;
import org.binarytranslator.generic.decoder.Interpreter;
-import org.binarytranslator.generic.memory.ByteAddressedMemory;
-import org.binarytranslator.generic.memory.IntAddressedMemory;
+import org.binarytranslator.generic.memory.ByteAddressedLittleEndianMemory;
+import org.binarytranslator.generic.memory.IntAddressedLittleEndianMemory;
import org.binarytranslator.generic.os.loader.Loader;
import org.binarytranslator.generic.os.process.ProcessSpace;
import org.binarytranslator.vmInterface.DBT_Trace;
@@ -43,11 +43,11 @@
switch (ARM_Options.memoryModel) {
case ByteAddressed:
- memory = new ByteAddressedMemory();
+ memory = new ByteAddressedLittleEndianMemory();
break;
case IntAddressed:
- memory = new IntAddressedMemory();
+ memory = new IntAddressedLittleEndianMemory();
break;
default:
Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-15 16:24:05 UTC (rev 167)
+++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-20 14:12:59 UTC (rev 168)
@@ -14,8 +14,8 @@
public class ARM_ImageProcessSpace extends ARM_ProcessSpace {
private AngelSystemCalls sysCalls;
- private final int STACK_SIZE = 4096 * 10;
- private final int HEAP_SIZE = 4096 * 10;
+ private final int STACK_SIZE = 4096 * 100;
+ private final int HEAP_SIZE = 4096 * 100;
public ARM_ImageProcessSpace() {
super();
Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-08-15 16:24:05 UTC (rev 167)
+++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-08-20 14:12:59 UTC (rev 168)
@@ -14,7 +14,7 @@
import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext;
import org.binarytranslator.DBT_Options;
import org.binarytranslator.generic.os.process.ProcessSpace;
-import org.binarytranslator.generic.memory.ByteAddressedMemory;
+import org.binarytranslator.generic.memory.ByteAddressedLittleEndianMemory;
import org.binarytranslator.generic.decoder.CodeTranslator;
import org.binarytranslator.generic.execution.GdbController.GdbTarget;
import org.binarytranslator.generic.fault.BadInstructionException;
@@ -139,7 +139,7 @@
*/
protected X86_ProcessSpace() {
registers = new X86_Registers();
- memory = new ByteAddressedMemory();
+ memory = new ByteAddressedLittleEndianMemory();
}
/**
Modified: src/org/binarytranslator/generic/memory/ByteAddressedByteSwapMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/ByteAddressedByteSwapMemory.java 2007-08-15 16:24:05 UTC (rev 167)
+++ src/org/binarytranslator/generic/memory/ByteAddressedByteSwapMemory.java 2007-08-20 14:12:59 UTC (rev 168)
@@ -29,7 +29,7 @@
* .........00 |'H'|
* </pre>
*/
-final public class ByteAddressedByteSwapMemory extends ByteAddressedMemory {
+final public class ByteAddressedByteSwapMemory extends ByteAddressedLittleEndianMemory {
/**
* Constructor - used when this is the instatiated class
*/
Copied: src/org/binarytranslator/generic/memory/ByteAddressedLittleEndianMemory.java (from rev 149, src/org/binarytranslator/generic/memory/ByteAddressedMemory.java)
===================================================================
--- src/org/binarytranslator/generic/memory/ByteAddressedLittleEndianMemory.java (rev 0)
+++ src/org/binarytranslator/generic/memory/ByteAddressedLittleEndianMemory.java 2007-08-20 14:12:59 UTC (rev 168)
@@ -0,0 +1,550 @@
+/*
+ * This file is part of binarytranslator.org. The binarytranslator.org
+ * project is distributed under the Common Public License (CPL).
+ * A copy of the license is included in the distribution, and is also
+ * available at http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * (C) Copyright Ian Rogers, The University of Manchester 2003-2006
+ */
+package org.binarytranslator.generic.memory;
+
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import org.binarytranslator.DBT_Options;
+import org.binarytranslator.generic.fault.SegmentationFault;
+
+/**
+ * ByteAddressedMemory:
+ *
+ * Memory is arrays of bytes, no endian conversion is performed.
+ *
+ * The string helo followed by the int of 0xcafebabe appear as:
+ *
+ * <pre>
+ * Byte Address|
+ * -----------------
+ * .........07 | ca|
+ * .........06 | fe|
+ * .........05 | ba|
+ * .........04 | be|
+ * .........03 |'o'|
+ * .........02 |'l'|
+ * .........01 |'e'|
+ * .........00 |'H'|
+ * </pre>
+ */
+public class ByteAddressedLittleEndianMemory extends CallBasedMemory {
+
+ /** The size of a single page in bytes. */
+ private static final int PAGE_SIZE = 4096;
+
+ /** Bits in offset */
+ private static final int OFFSET_BITS = 12;
+
+ /** The number of pages */
+ private static final int NUM_PAGES = 0x100000;
+
+ /** The maximum amount of RAM available */
+ protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES;
+
+ /** The memory backing store */
+ private byte readableMemory[][];
+ private byte writableMemory[][];
+ private byte executableMemory[][];
+
+ /** Do we have more optimal nio mmap operation? */
+ private boolean HAVE_java_nio_FileChannelImpl_nio_mmap_file = false;
+
+ /**
+ * Constructor - used when this is the instatiated class
+ */
+ public ByteAddressedLittleEndianMemory() {
+ this(null);
+ }
+
+ /**
+ * Constructor - used when deriving a class
+ *
+ * @param classType
+ * the name of the over-riding class
+ */
+ protected ByteAddressedLittleEndianMemory(Class classType) {
+ super(classType != null ? classType : ByteAddressedLittleEndianMemory.class);
+ readableMemory = new byte[NUM_PAGES][];
+ writableMemory = new byte[NUM_PAGES][];
+ executableMemory = new byte[NUM_PAGES][];
+ }
+
+ /**
+ * Return the offset part of the address
+ */
+ private static final int getOffset(int address) {
+ return address & (PAGE_SIZE - 1);
+ }
+
+ /**
+ * Return the page table entry part of the address
+ */
+ private static final int getPTE(int address) {
+ return address >>> OFFSET_BITS;
+ }
+
+ /**
+ * Find free consecutive pages
+ *
+ * @param pages
+ * the number of pages required
+ * @return the address found
+ */
+ private final int findFreePages(int pages) {
+ starting_page_search: for (int i = 0; i < NUM_PAGES; i++) {
+ if (getPage(i) == null) {
+ int start = i;
+ int end = i + pages;
+ for (; i <= end; i++) {
+ if (getPage(i) != null) {
+ continue starting_page_search;
+ }
+ }
+ return start << OFFSET_BITS;
+ }
+ }
+ throw new Error(
+ "No mappable consecutive pages found for an anonymous map of size"
+ + (pages * PAGE_SIZE));
+ }
+
+ /**
+ * Map an anonymous page of memory
+ *
+ * @param addr
+ * the address to map or NULL if don't care
+ * @param len
+ * the amount of memory to map
+ * @param read
+ * is the page readable
+ * @param write
+ * is the page writable
+ * @param exec
+ * is the page executable
+ */
+ public int map(int addr, int len, boolean read, boolean write, boolean exec)
+ throws MemoryMapException {
+ // Check address is page aligned
+ if ((addr % PAGE_SIZE) != 0) {
+ MemoryMapException.unalignedAddress(addr);
+ }
+
+ // Create memory
+ int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE;
+ byte pages[][] = new byte[num_pages][PAGE_SIZE];
+
+ // Find address if not specified
+ if (addr == 0) {
+ addr = findFreePages(num_pages);
+ }
+
+ if (DBT_Options.debugMemory) {
+ System.out.println("Anonymous mapping: addr=0x"
+ + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -")
+ + (write ? "w" : "-") + (exec ? "x" : "-"));
+ }
+
+ // Get page table entry
+ int pte = getPTE(addr);
+ for (int i = 0; i < num_pages; i++) {
+
+ // Check pages aren't already allocated
+ if (getPage(pte + i) != null) {
+ throw new Error("Memory map of already mapped location addr=0x"
+ + Integer.toHexString(addr) + " len=" + len);
+ }
+
+ // Allocate pages
+ readableMemory[pte + i] = read ? pages[i] : null;
+ writableMemory[pte + i] = write ? pages[i] : null;
+ executableMemory[pte + i] = exec ? pages[i] : null;
+ }
+
+ return addr;
+ }
+
+ /**
+ * Map a page of memory from file
+ *
+ * @param file
+ * the file map in from
+ * @param addr
+ * the address to map or NULL if don't care
+ * @param len
+ * the amount of memory to map
+ * @param read
+ * is the page readable
+ * @param write
+ * is the page writable
+ * @param exec
+ * is the page executable
+ */
+ public int map(RandomAccessFile file, long offset, int addr, int len,
+ boolean read, boolean write, boolean exec) throws MemoryMapException {
+ // Check address is page aligned
+ if ((addr % PAGE_SIZE) != 0) {
+ MemoryMapException.unalignedAddress(addr);
+ }
+
+ // Check file offset is page aligned
+ /*if ((offset % PAGE_SIZE) != 0) {
+ MemoryMapException.unalignedFileOffset(offset);
+ }*/
+
+ // Calculate number of pages
+ int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE;
+ // Find address if not specified
+ if (addr == 0) {
+ addr = findFreePages(num_pages);
+ }
+ if (DBT_Options.debugMemory) {
+ System.out.println("Mapping file " + file + " offset=" + offset
+ + " addr=0x" + Integer.toHexString(addr) + " len=" + len
+ + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-"));
+ }
+ try {
+ // Get page table entry
+ int pte = getPTE(addr);
+ // Can we optimise the reads to use mmap?
+ if (!HAVE_java_nio_FileChannelImpl_nio_mmap_file) {
+ // Sub-optimal
+ file.seek(offset);
+ for (int i = 0; i < num_pages; i++) {
+ // Check pages aren't already allocated
+ if (getPage(pte + i) != 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];
+ if (i == 0) { // first read, start from offset upto a page length
+ file.read(page, getOffset(addr), PAGE_SIZE - getOffset(addr));
+ } else if (i == (num_pages - 1)) { // last read
+ file.read(page, 0, ((len - getOffset(addr)) % PAGE_SIZE));
+ } else {
+ file.read(page);
+ }
+
+ readableMemory[pte + i] = read ? page : null;
+ writableMemory[pte + i] = write ? page : null;
+ executableMemory[pte + i] = exec ? page : null;
+ }
+ } else {
+ for (int i = 0; i < num_pages; i++) {
+ // Check pages aren't already allocated
+ if (getPage(pte + i) != null) {
+ throw new Error("Memory map of already mapped location addr=0x"
+ + Integer.toHexString(addr) + " len=" + len);
+ }
+
+ // Allocate page
+ if (read && write) {
+ readableMemory[pte + i] = file.getChannel().map(
+ FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE),
+ PAGE_SIZE).array();
+ writableMemory[pte + i] = readableMemory[pte + i];
+ if (exec) {
+ executableMemory[pte + i] = readableMemory[pte + i];
+ }
+ } else if (read) {
+ readableMemory[pte + i] = file.getChannel().map(
+ FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE),
+ PAGE_SIZE).array();
+ if (exec) {
+ executableMemory[pte + i] = readableMemory[pte + i];
+ }
+ } else if (exec) {
+ executableMemory[pte + i] = file.getChannel().map(
+ FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE),
+ PAGE_SIZE).array();
+ } else {
+ throw new Error("Unable to map address 0x"
+ + Integer.toHexString(addr) + " with permissions "
+ + (read ? "r" : "-") + (write ? "w" : "-") + (exec ? "x" : "-"));
+ }
+ }
+ }
+ return addr;
+ } catch (java.io.IOException e) {
+ throw new Error(e);
+ }
+ }
+
+ /**
+ * Returns the page currently mapped at the given page table entry.
+ *
+ * @param pte
+ * The page table entry, for which a page is to be retrieved.
+ * @return
+ * The page mapped at the given page table entry or null, if no page is currently mapped
+ * to that entry.
+ */
+ private byte[] getPage(int pte) {
+
+ if (readableMemory[pte] != null)
+ return readableMemory[pte];
+
+ if (writableMemory[pte] != null)
+ return writableMemory[pte];
+
+ if (executableMemory[pte] != null)
+ return executableMemory[pte];
+
+ return null;
+ }
+
+ /**
+ * Unmap a page of memory
+ *
+ * @param addr
+ * the address to unmap
+ * @param len
+ * the amount of memory to unmap
+ */
+ public void unmap(int addr, int len) {
+ for (int i = 0; i < len; i += PAGE_SIZE) {
+
+ int pte = getPTE(addr + i);
+ if (getPage(pte) != null) {
+ readableMemory[pte] = null;
+ writableMemory[pte] = null;
+ executableMemory[pte] = null;
+ }
+ else {
+ throw new Error("Unmapping memory that's not mapped addr=0x"
+ + Integer.toHexString(addr) + " len=" + len);
+ }
+ }
+ }
+
+ /**
+ * Is the given address mapped into memory?
+ * @param addr to check
+ * @return true => memory is mapped
+ */
+ public boolean isMapped(int addr) {
+ return getPage(getPTE(addr)) != null;
+ }
+
+ /**
+ * @return the size of a page
+ */
+ public int getPageSize() {
+ return PAGE_SIZE;
+ }
+
+ /**
+ * Is the given address aligned on a page boundary?
+ *
+ * @param addr
+ * the address to check
+ * @return whether the address is aligned
+ */
+ public boolean isPageAligned(int addr) {
+ return (addr % PAGE_SIZE) == 0;
+ }
+
+ /**
+ * Make the given address page aligned to the page beneath it
+ *
+ * @param addr
+ * the address to truncate
+ * @return the truncated address
+ */
+ public int truncateToPage(int addr) {
+ return (addr >> OFFSET_BITS) << OFFSET_BITS;
+ }
+
+ /**
+ * Make the given address page aligned to the page above it
+ *
+ * @param addr
+ * the address to truncate
+ * @return the truncated address
+ */
+ public int truncateToNextPage(int addr) {
+ return ((addr + PAGE_SIZE - 1) >> OFFSET_BITS) << OFFSET_BITS;
+ }
+
+ /**
+ * Perform a byte load where the sign extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the sign extended result
+ */
+ final public int loadSigned8(int addr) {
+ try {
+ if (DBT_Options.debugMemory)
+ System.err.println("LoadS8 address: 0x" + Integer.toHexString(addr)
+ + " val: " + readableMemory[getPTE(addr)][getOffset(addr)]);
+ return readableMemory[getPTE(addr)][getOffset(addr)];
+ } catch (NullPointerException e) {
+ System.err.println("Null pointer exception at address: 0x"
+ + Integer.toHexString(addr));
+ throw e;
+ }
+ }
+
+ /**
+ * Perform a byte load where the zero extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the zero extended result
+ */
+ final public int loadUnsigned8(int addr) {
+ try {
+ if (DBT_Options.debugMemory)
+ System.err.println("LoadU8 address: 0x" + Integer.toHexString(addr)
+ + " val: " + readableMemory[getPTE(addr)][getOffset(addr)]);
+ return readableMemory[getPTE(addr)][getOffset(addr)] & 0xFF;
+ } catch (NullPointerException e) {
+ System.err.println("Null pointer exception at address: 0x"
+ + Integer.toHexString(addr));
+ throw e;
+ }
+ }
+
+ /**
+ * Perform a 16bit load where the sign extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the sign extended result
+ */
+ public int loadSigned16(int addr) {
+ return (loadSigned8(addr + 1) << 8) | loadUnsigned8(addr);
+ }
+
+ /**
+ * Perform a 16bit load where the zero extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the zero extended result
+ */
+ public int loadUnsigned16(int addr) {
+ return (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr);
+ }
+
+ /**
+ * Perform a 32bit load
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int load32(int addr) {
+ try {
+ return (loadSigned8(addr + 3) << 24) | (loadUnsigned8(addr + 2) << 16)
+ | (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr);
+ } catch (Exception e) {
+ throw new SegmentationFault(addr);
+ }
+ }
+
+ /**
+ * Perform a 8bit load from memory that must be executable
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int loadInstruction8(int addr) {
+ if (DBT_Options.debugMemory)
+ System.err.println("LoadI8 address: 0x" + Integer.toHexString(addr)
+ + " val: " + executableMemory[getPTE(addr)][getOffset(addr)]);
+ return executableMemory[getPTE(addr)][getOffset(addr)] & 0xFF;
+ }
+
+ /**
+ * Perform a 32bit load from memory that must be executable
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int loadInstruction32(int addr) {
+ return (loadInstruction8(addr + 3) << 24)
+ | (loadInstruction8(addr + 2) << 16)
+ | (loadInstruction8(addr + 1) << 8) | loadInstruction8(addr);
+ }
+
+ /**
+ * Perform a byte store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public final void store8(int addr, int value) {
+ if (DBT_Options.debugMemory)
+ System.err.println("Store8 address: 0x" + Integer.toHexString(addr)
+ + " val: 0x" + Integer.toHexString(value & 0xFF));
+ writableMemory[getPTE(addr)][getOffset(addr)] = (byte) value;
+ }
+
+ /**
+ * Perform a 16bit store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public void store16(int addr, int value) {
+ store8(addr + 1, value >> 8);
+ store8(addr, value);
+ }
+
+ /**
+ * Perform a 32bit store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public void store32(int addr, int value) {
+ try {
+ store8(addr + 3, value >> 24);
+ store8(addr + 2, value >> 16);
+ store8(addr + 1, value >> 8);
+ store8(addr, value);
+ } catch (Exception e) {
+ throw new SegmentationFault(addr);
+ }
+ }
+
+ @Override
+ public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) {
+
+ while (len > 0) {
+ int pte = getPTE(address);
+ byte[] page = getPage(pte);
+
+ if (page == null)
+ throw new SegmentationFault(address);
+
+ readableMemory[pte] = newRead ? page : null;
+ writableMemory[pte] = newWrite ? page : null;
+ executableMemory[pte] = newExec ? page : null;
+
+ address += PAGE_SIZE;
+ len -= PAGE_SIZE;
+ }
+ }
+
+ @Override
+ public int loadInstruction16(int addr) {
+ return (loadInstruction8(addr + 1) << 8) | loadInstruction8(addr);
+ }
+}
Deleted: src/org/binarytranslator/generic/memory/ByteAddressedMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-08-15 16:24:05 UTC (rev 167)
+++ src/org/binarytranslator/generic/memory/ByteAddressedMemory.java 2007-08-20 14:12:59 UTC (rev 168)
@@ -1,550 +0,0 @@
-/*
- * This file is part of binarytranslator.org. The binarytranslator.org
- * project is distributed under the Common Public License (CPL).
- * A copy of the license is included in the distribution, and is also
- * available at http://www.opensource.org/licenses/cpl1.0.php
- *
- * (C) Copyright Ian Rogers, The University of Manchester 2003-2006
- */
-package org.binarytranslator.generic.memory;
-
-import java.io.RandomAccessFile;
-import java.nio.channels.FileChannel;
-import org.binarytranslator.DBT_Options;
-import org.binarytranslator.generic.fault.SegmentationFault;
-
-/**
- * ByteAddressedMemory:
- *
- * Memory is arrays of bytes, no endian conversion is performed.
- *
- * The string helo followed by the int of 0xcafebabe appear as:
- *
- * <pre>
- * Byte Address|
- * -----------------
- * .........07 | be|
- * .........06 | ba|
- * .........05 | fe|
- * .........04 | ca|
- * .........03 |'o'|
- * .........02 |'l'|
- * .........01 |'e'|
- * .........00 |'H'|
- * </pre>
- */
-public class ByteAddressedMemory extends CallBasedMemory {
-
- /** The size of a single page in bytes. */
- private static final int PAGE_SIZE = 4096;
-
- /** Bits in offset */
- private static final int OFFSET_BITS = 12;
-
- /** The number of pages */
- private static final int NUM_PAGES = 0x100000;
-
- /** The maximum amount of RAM available */
- protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES;
-
- /** The memory backing store */
- private byte readableMemory[][];
- private byte writableMemory[][];
- private byte executableMemory[][];
-
- /** Do we have more optimal nio mmap operation? */
- private boolean HAVE_java_nio_FileChannelImpl_nio_mmap_file = false;
-
- /**
- * Constructor - used when this is the instatiated class
- */
- public ByteAddressedMemory() {
- this(null);
- }
-
- /**
- * Constructor - used when deriving a class
- *
- * @param classType
- * the name of the over-riding class
- */
- protected ByteAddressedMemory(Class classType) {
- super(classType != null ? classType : ByteAddressedMemory.class);
- readableMemory = new byte[NUM_PAGES][];
- writableMemory = new byte[NUM_PAGES][];
- executableMemory = new byte[NUM_PAGES][];
- }
-
- /**
- * Return the offset part of the address
- */
- private static final int getOffset(int address) {
- return address & (PAGE_SIZE - 1);
- }
-
- /**
- * Return the page table entry part of the address
- */
- private static final int getPTE(int address) {
- return address >>> OFFSET_BITS;
- }
-
- /**
- * Find free consecutive pages
- *
- * @param pages
- * the number of pages required
- * @return the address found
- */
- private final int findFreePages(int pages) {
- starting_page_search: for (int i = 0; i < NUM_PAGES; i++) {
- if (getPage(i) == null) {
- int start = i;
- int end = i + pages;
- for (; i <= end; i++) {
- if (getPage(i) != null) {
- continue starting_page_search;
- }
- }
- return start << OFFSET_BITS;
- }
- }
- throw new Error(
- "No mappable consecutive pages found for an anonymous map of size"
- + (pages * PAGE_SIZE));
- }
-
- /**
- * Map an anonymous page of memory
- *
- * @param addr
- * the address to map or NULL if don't care
- * @param len
- * the amount of memory to map
- * @param read
- * is the page readable
- * @param write
- * is the page writable
- * @param exec
- * is the page executable
- */
- public int map(int addr, int len, boolean read, boolean write, boolean exec)
- throws MemoryMapException {
- // Check address is page aligned
- if ((addr % PAGE_SIZE) != 0) {
- MemoryMapException.unalignedAddress(addr);
- }
-
- // Create memory
- int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE;
- byte pages[][] = new byte[num_pages][PAGE_SIZE];
-
- // Find address if not specified
- if (addr == 0) {
- addr = findFreePages(num_pages);
- }
-
- if (DBT_Options.debugMemory) {
- System.out.println("Anonymous mapping: addr=0x"
- + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -")
- + (write ? "w" : "-") + (exec ? "x" : "-"));
- }
-
- // Get page table entry
- int pte = getPTE(addr);
- for (int i = 0; i < num_pages; i++) {
-
- // Check pages aren't already allocated
- if (getPage(pte + i) != null) {
- throw new Error("Memory map of already mapped location addr=0x"
- + Integer.toHexString(addr) + " len=" + len);
- }
-
- // Allocate pages
- readableMemory[pte + i] = read ? pages[i] : null;
- writableMemory[pte + i] = write ? pages[i] : null;
- executableMemory[pte + i] = exec ? pages[i] : null;
- }
-
- return addr;
- }
-
- /**
- * Map a page of memory from file
- *
- * @param file
- * the file map in from
- * @param addr
- * the address to map or NULL if don't care
- * @param len
- * the amount of memory to map
- * @param read
- * is the page readable
- * @param write
- * is the page writable
- * @param exec
- * is the page executable
- */
- public int map(RandomAccessFile file, long offset, int addr, int len,
- boolean read, boolean write, boolean exec) throws MemoryMapException {
- // Check address is page aligned
- if ((addr % PAGE_SIZE) != 0) {
- MemoryMapException.unalignedAddress(addr);
- }
-
- // Check file offset is page aligned
- /*if ((offset % PAGE_SIZE) != 0) {
- MemoryMapException.unalignedFileOffset(offset);
- }*/
-
- // Calculate number of pages
- int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE;
- // Find address if not specified
- if (addr == 0) {
- addr = findFreePages(num_pages);
- }
- if (DBT_Options.debugMemory) {
- System.out.println("Mapping file " + file + " offset=" + offset
- + " addr=0x" + Integer.toHexString(addr) + " len=" + len
- + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-"));
- }
- try {
- // Get page table entry
- int pte = getPTE(addr);
- // Can we optimise the reads to use mmap?
- if (!HAVE_java_nio_FileChannelImpl_nio_mmap_file) {
- // Sub-optimal
- file.seek(offset);
- for (int i = 0; i < num_pages; i++) {
- // Check pages aren't already allocated
- if (getPage(pte + i) != 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];
- if (i == 0) { // first read, start from offset upto a page length
- file.read(page, getOffset(addr), PAGE_SIZE - getOffset(addr));
- } else if (i == (num_pages - 1)) { // last read
- file.read(page, 0, ((len - getOffset(addr)) % PAGE_SIZE));
- } else {
- file.read(page);
- }
-
- readableMemory[pte + i] = read ? page : null;
- writableMemory[pte + i] = write ? page : null;
- executableMemory[pte + i] = exec ? page : null;
- }
- } else {
- for (int i = 0; i < num_pages; i++) {
- // Check pages aren't already allocated
- if (getPage(pte + i) != null) {
- throw new Error("Memory map of already mapped location addr=0x"
- + Integer.toHexString(addr) + " len=" + len);
- }
-
- // Allocate page
- if (read && write) {
- readableMemory[pte + i] = file.getChannel().map(
- FileChannel.MapMode.READ_WRITE, offset + (i * PAGE_SIZE),
- PAGE_SIZE).array();
- writableMemory[pte + i] = readableMemory[pte + i];
- if (exec) {
- executableMemory[pte + i] = readableMemory[pte + i];
- }
- } else if (read) {
- readableMemory[pte + i] = file.getChannel().map(
- FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE),
- PAGE_SIZE).array();
- if (exec) {
- executableMemory[pte + i] = readableMemory[pte + i];
- }
- } else if (exec) {
- executableMemory[pte + i] = file.getChannel().map(
- FileChannel.MapMode.READ_ONLY, offset + (i * PAGE_SIZE),
- PAGE_SIZE).array();
- } else {
- throw new Error("Unable to map address 0x"
- + Integer.toHexString(addr) + " with permissions "
- + (read ? "r" : "-") + (write ? "w" : "-") + (exec ? "x" : "-"));
- }
- }
- }
- return addr;
- } catch (java.io.IOException e) {
- throw new Error(e);
- }
- }
-
- /**
- * Returns the page currently mapped at the given page table entry.
- *
- * @param pte
- * The page table entry, for which a page is to be retrieved.
- * @return
- * The page mapped at the given page table entry or null, if no page is currently mapped
- * to that entry.
- */
- private byte[] getPage(int pte) {
-
- if (readableMemory[pte] != null)
- return readableMemory[pte];
-
- if (writableMemory[pte] != null)
- return writableMemory[pte];
-
- if (executableMemory[pte] != null)
- return executableMemory[pte];
-
- return null;
- }
-
- /**
- * Unmap a page of memory
- *
- * @param addr
- * the address to unmap
- * @param len
- * the amount of memory to unmap
- */
- public void unmap(int addr, int len) {
- for (int i = 0; i < len; i += PAGE_SIZE) {
-
- int pte = getPTE(addr + i);
- if (getPage(pte) != null) {
- readableMemory[pte] = null;
- writableMemory[pte] = null;
- executableMemory[pte] = null;
- }
- else {
- throw new Error("Unmapping memory that's not mapped addr=0x"
- + Integer.toHexString(addr) + " len=" + len);
- }
- }
- }
-
- /**
- * Is the given address mapped into memory?
- * @param addr to check
- * @return true => memory is mapped
- */
- public boolean isMapped(int addr) {
- return getPage(getPTE(addr)) != null;
- }
-
- /**
- * @return the size of a page
- */
- public int getPageSize() {
- return PAGE_SIZE;
- }
-
- /**
- * Is the given address aligned on a page boundary?
- *
- * @param addr
- * the address to check
- * @return whether the address is aligned
- */
- public boolean isPageAligned(int addr) {
- return (addr % PAGE_SIZE) == 0;
- }
-
- /**
- * Make the given address page aligned to the page beneath it
- *
- * @param addr
- * the address to truncate
- * @return the truncated address
- */
- public int truncateToPage(int addr) {
- return (addr >> OFFSET_BITS) << OFFSET_BITS;
- }
-
- /**
- * Make the given address page aligned to the page above it
- *
- * @param addr
- * the address to truncate
- * @return the truncated address
- */
- public int truncateToNextPage(int addr) {
- return ((addr + PAGE_SIZE - 1) >> OFFSET_BITS) << OFFSET_BITS;
- }
-
- /**
- * Perform a byte load where the sign extended result fills the return value
- *
- * @param addr
- * the address of the value to load
- * @return the sign extended result
- */
- final public int loadSigned8(int addr) {
- try {
- if (DBT_Options.debugMemory)
- System.err.println("LoadS8 address: 0x" + Integer.toHexString(addr)
- + " val: " + readableMemory[getPTE(addr)][getOffset(addr)]);
- return readableMemory[getPTE(addr)][getOffset(addr)];
- } catch (NullPointerException e) {
- System.err.println("Null pointer exception at address: 0x"
- + Integer.toHexString(addr));
- throw e;
- }
- }
-
- /**
- * Perform a byte load where the zero extended result fills the return value
- *
- * @param addr
- * the address of the value to load
- * @return the zero extended result
- */
- final public int loadUnsigned8(int addr) {
- try {
- if (DBT_Options.debugMemory)
- System.err.println("LoadU8 address: 0x" + Integer.toHexString(addr)
- + " val: " + readableMemory[getPTE(addr)][getOffset(addr)]);
- return readableMemory[getPTE(addr)][getOffset(addr)] & 0xFF;
- } catch (NullPointerException e) {
- System.err.println("Null pointer exception at address: 0x"
- + Integer.toHexString(addr));
- throw e;
- }
- }
-
- /**
- * Perform a 16bit load where the sign extended result fills the return value
- *
- * @param addr
- * the address of the value to load
- * @return the sign extended result
- */
- public int loadSigned16(int addr) {
- return (loadSigned8(addr + 1) << 8) | loadUnsigned8(addr);
- }
-
- /**
- * Perform a 16bit load where the zero extended result fills the return value
- *
- * @param addr
- * the address of the value to load
- * @return the zero extended result
- */
- public int loadUnsigned16(int addr) {
- return (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr);
- }
-
- /**
- * Perform a 32bit load
- *
- * @param addr
- * the address of the value to load
- * @return the result
- */
- public int load32(int addr) {
- try {
- return (loadSigned8(addr + 3) << 24) | (loadUnsigned8(addr + 2) << 16)
- | (loadUnsigned8(addr + 1) << 8) | loadUnsigned8(addr);
- } catch (Exception e) {
- throw new SegmentationFault(addr);
- }
- }
-
- /**
- * Perform a 8bit load from memory that must be executable
- *
- * @param addr
- * the address of the value to load
- * @return the result
- */
- public int loadInstruction8(int addr) {
- if (DBT_Options.debugMemory)
- System.err.println("LoadI8 address: 0x" + Integer.toHexString(addr)
- + " val: " + executableMemory[getPTE(addr)][getOffset(addr)]);
- return executableMemory[getPTE(addr)][getOffset(addr)] & 0xFF;
- }
-
- /**
- * Perform a 32bit load from memory that must be executable
- *
- * @param addr
- * the address of the value to load
- * @return the result
- */
- public int loadInstruction32(int addr) {
- return (loadInstruction8(addr + 3) << 24)
- | (loadInstruction8(addr + 2) << 16)
- | (loadInstruction8(addr + 1) << 8) | loadInstruction8(addr);
- }
-
- /**
- * Perform a byte store
- *
- * @param value
- * the value to store
- * @param addr
- * the address of where to store
- */
- public final void store8(int addr, int value) {
- if (DBT_Options.debugMemory)
- System.err.println("Store8 address: 0x" + Integer.toHexString(addr)
- + " val: 0x" + Integer.toHexString(value & 0xFF));
- writableMemory[getPTE(addr)][getOffset(addr)] = (byte) value;
- }
-
- /**
- * Perform a 16bit store
- *
- * @param value
- * the value to store
- * @param addr
- * the address of where to store
- */
- public void store16(int addr, int value) {
- store8(addr + 1, value >> 8);
- store8(addr, value);
- }
-
- /**
- * Perform a 32bit store
- *
- * @param value
- * the value to store
- * @param addr
- * the address of where to store
- */
- public void store32(int addr, int value) {
- try {
- store8(addr + 3, value >> 24);
- store8(addr + 2, value >> 16);
- store8(addr + 1, value >> 8);
- store8(addr, value);
- } catch (Exception e) {
- throw new SegmentationFault(addr);
- }
- }
-
- @Override
- public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) {
-
- while (len > 0) {
- int pte = getPTE(address);
- byte[] page = getPage(pte);
-
- if (page == null)
- throw new SegmentationFault(address);
-
- readableMemory[pte] = newRead ? page : null;
- writableMemory[pte] = newWrite ? page : null;
- executableMemory[pte] = newExec ? page : null;
-
- address += PAGE_SIZE;
- len -= PAGE_SIZE;
- }
- }
-
- @Override
- public int loadInstruction16(int addr) {
- return (loadInstruction8(addr + 1) << 8) | loadInstruction8(addr);
- }
-}
Modified: src/org/binarytranslator/generic/memory/IntAddressedByteSwapMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/IntAddressedByteSwapMemory.java 2007-08-15 16:24:05 UTC (rev 167)
+++ src/org/binarytranslator/generic/memory/IntAddressedByteSwapMemory.java 2007-08-20 14:12:59 UTC (rev 168)
@@ -26,7 +26,7 @@
* .........00 |'H'|'e'|'l'|'l'|
* </pre>
*/
-final public class IntAddressedByteSwapMemory extends IntAddressedMemory {
+final public class IntAddressedByteSwapMemory extends IntAddressedLittleEndianMemory {
/**
* Constructor - used when this is the instatiated class
*/
Copied: src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java (from rev 164, src/org/binarytranslator/generic/memory/IntAddressedMemory.java)
===================================================================
--- src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java (rev 0)
+++ src/org/binarytranslator/generic/memory/IntAddressedLittleEndianMemory.java 2007-08-20 14:12:59 UTC (rev 168)
@@ -0,0 +1,673 @@
+/*
+ * This file is part of binarytranslator.org. The binarytranslator.org
+ * project is distributed under the Common Public License (CPL).
+ * A copy of the license is included in the distribution, and is also
+ * available at http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * (C) Copyright Ian Rogers, The University of Manchester 2003-2006
+ */
+package org.binarytranslator.generic.memory;
+
+import java.io.RandomAccessFile;
+
+import org.binarytranslator.DBT;
+import org.binarytranslator.DBT_Options;
+import org.binarytranslator.generic.fault.SegmentationFault;
+import org.jikesrvm.VM_Configuration;
+import org.vmmagic.pragma.Inline;
+
+/**
+ * IntAddressedMemory:
+ *
+ * Memory is arrays of ints, no endian conversion is performed.
+ *
+ * The string helloworld following by the int of 0xcafebabe appear as:
+ *
+ * <pre>
+ * Byte Address
+ * Int Address | 0 | 1 | 2 | 3 |
+ * -----------------------------
+ * .........0c | be| ba| fe| ca|
+ * .........08 |'l'|'d'| \n| \0|
+ * .........04 |'o'|'W'|'o'|'r'|
+ * .........00 |'H'|'e'|'l'|'l'|
+ * </pre>
+ */
+public class IntAddressedLittleEndianMemory extends CallBasedMemory {
+ /**
+ * The size of pages
+ */
+ protected static final int PAGE_SIZE = 4096;
+
+ /**
+ * Bits in offset
+ */
+ protected static final int OFFSET_BITS = 12;
+
+ /**
+ * The number of pages
+ */
+ protected static final int NUM_PAGES = 0x100000;
+
+ /**
+ * The maximum amount of RAM available
+ */
+ protected static final long MAX_RAM = (long) PAGE_SIZE * (long) NUM_PAGES;
+
+ /**
+ * The memory backing store
+ */
+ private int readableMemory[][];
+
+ private int writableMemory[][];
+
+ private int executableMemory[][];
+
+ /**
+ * Constructor - used when this is the instatiated class
+ */
+ public IntAddressedLittleEndianMemory() {
+ this(null);
+ }
+
+ /**
+ * Constructor - used when deriving a class
+ *
+ * @param classType
+ * the type of the over-riding class
+ */
+ protected IntAddressedLittleEndianMemory(Class classType) {
+ super(classType != null ? classType : IntAddressedLittleEndianMemory.class);
+ readableMemory = new int[NUM_PAGES][];
+ writableMemory = new int[NUM_PAGES][];
+ executableMemory = new int[NUM_PAGES][];
+ }
+
+ /**
+ * Return the offset part of the address
+ */
+ @Inline
+ protected int getOffset(int address) {
+ return (address & (PAGE_SIZE - 1)) >>> 2;
+ }
+
+ /**
+ * Return the page table entry part of the address
+ */
+ @Inline
+ private static final int getPTE(int address) {
+ return address >>> OFFSET_BITS;
+ }
+
+ /**
+ * Is the given address mapped into memory?
+ * @param addr to check
+ * @return true => memory is mapped
+ */
+ public boolean isMapped(int addr) {
+ return getPage(getPTE(addr)) != null;
+ }
+
+ /**
+ * @return the size of a page
+ */
+ public int getPageSize() {
+ return PAGE_SIZE;
+ }
+
+ /**
+ * Is the given address aligned on a page boundary?
+ *
+ * @param addr
+ * the address to check
+ * @return whether the address is aligned
+ */
+ public boolean isPageAligned(int addr) {
+ return (addr % PAGE_SIZE) == 0;
+ }
+
+ /**
+ * Make the given address page aligned to the page beneath it
+ *
+ * @param addr
+ * the address to truncate
+ * @return the truncated address
+ */
+ public int truncateToPage(int addr) {
+ return (addr >> OFFSET_BITS) << OFFSET_BITS;
+ }
+
+ /**
+ * Make the given address page aligned to the page above it
+ *
+ * @param addr
+ * the address to truncate
+ * @return the truncated address
+ */
+ public int truncateToNextPage(int addr) {
+ return ((addr + PAGE_SIZE - 1) >> OFFSET_BITS) << OFFSET_BITS;
+ }
+
+ /**
+ * Find free consecutive pages
+ *
+ * @param pages
+ * the number of pages required
+ * @return the address found
+ */
+ private final int findFreePages(int pages) {
+ starting_page_search: for (int i = 0; i < NUM_PAGES; i++) {
+ if (getPage(i) == null) {
+ int start = i;
+ int end = i + pages;
+ for (; i <= end; i++) {
+ if (getPage(i) != null) {
+ continue starting_page_search;
+ }
+ }
+ return start << OFFSET_BITS;
+ }
+ }
+ throw new Error(
+ "No mappable consecutive pages found for an anonymous map of size"
+ + (pages * PAGE_SIZE));
+ }
+
+ /**
+ * Map an anonymous page of memory
+ *
+ * @param addr
+ * the address to map or NULL if don't care
+ * @param len
+ * the amount of memory to map
+ * @param read
+ * is the page readable
+ * @param write
+ * is the page writable
+ * @param exec
+ * is the page executable
+ */
+ public int map(int addr, int len, boolean read, boolean write, boolean exec)
+ throws MemoryMapException {
+ // Check that the address is page aligned
+ if ((addr % PAGE_SIZE) != 0) {
+ // if it is not, truncate the address down to the next page boundary and
+ // start mapping from there
+ int validPageCount = addr / PAGE_SIZE;
+ int oldStartAddress = addr;
+ addr = validPageCount * PAGE_SIZE;
+
+ if (DBT.VerifyAssertions)
+ DBT._assert(oldStartAddress > addr);
+
+ // we have to map more more memory now to reach the same end address
+ len += (oldStartAddress - addr);
+ }
+
+ // Calculate number of pages
+ int num_pages = (len + PAGE_SIZE - 1) / PAGE_SIZE;
+ // Create memory
+ int pages[][] = new int[num_pages][PAGE_SIZE / 4];
+ // Find address if not specified
+ if (addr == 0) {
+ addr = findFreePages(num_pages);
+ }
+ if (DBT_Options.debugRuntime) {
+ System.out.println("Anonymous mapping: addr=0x"
+ + Integer.toHexString(addr) + " len=" + len + (read ? " r" : " -")
+ + (write ? "w" : "-") + (exec ? "x" : "-"));
+ }
+ // Get page table entry
+ int pte = getPTE(addr);
+ for (int i = 0; i < num_pages; i++) {
+ // Check pages aren't already allocated
+ if (getPage(pte + i) != null) {
+ throw new Error("Memory map of already mapped location addr=0x"
+ + Integer.toHexString(addr) + " len=" + len);
+ }
+
+ readableMemory[pte+i] = read ? pages[i] : null;
+ writableMemory[pte+i] = write ? pages[i] : null;
+ executableMemory[pte+i] = exec ? pages[i] : null;
+ }
+ return addr;
+ }
+
+ /**
+ * Returns the page currently mapped at the given page table entry.
+ *
+ * @param pte
+ * The page table entry, for which a page is to be retrieved.
+ * @return
+ * The page mapped at the given page table entry or null, if no page is currently mapped
+ * to that entry.
+ */
+ private int[] getPage(int pte) {
+
+ if (readableMemory[pte] != null)
+ return readableMemory[pte];
+
+ if (writableMemory[pte] != null)
+ return writableMemory[pte];
+
+ if (executableMemory[pte] != null)
+ return executableMemory[pte];
+
+ return null;
+ }
+
+ @Override
+ public void changeProtection(int address, int len, boolean newRead, boolean newWrite, boolean newExec) {
+
+ while (len > 0) {
+ int pte = getPTE(address);
+ int[] page = getPage(pte);
+
+ if (page == null)
+ throw new SegmentationFault(address);
+
+ readableMemory[pte] = newRead ? page : null;
+ writableMemory[pte] = newWrite ? page : null;
+ executableMemory[pte] = newExec ? page : null;
+
+ address += PAGE_SIZE;
+ len -= PAGE_SIZE;
+ }
+ }
+
+ /**
+ * Read an int from RandomAccessFile ensuring that a byte swap isn't performed
+ *
+ * @param file
+ * file to read from
+ * @return native endian read int
+ */
+ protected int readInt(RandomAccessFile file) throws java.io.IOException {
+ if (VM_Configuration.BuildForPowerPC) {
+ return file.readInt(); // NB this will always read in big-endian format
+ } else {
+ return file.readUnsignedByte() | (file.readUnsignedByte() << 8)
+ | (file.readUnsignedByte() << 16) | (file.readByte() << 24);
+ }
+ }
+
+ /**
+ * Map a page of memory from file
+ *
+ * @param file
+ * the file map in from
+ * @param addr
+ * the address to map or NULL if don't care
+ * @param len
+ * the amount of memory to map
+ * @param read
+ * is the page readable
+ * @param write
+ * is the page writable
+ * @param exec
+ * is the page executable
+ */
+ public final int map(RandomAccessFile file, long offset, int addr, int len,
+ boolean read, boolean write, boolean exec) throws MemoryMapException {
+ // Check address is page aligned
+ if ((addr % PAGE_SIZE) != 0) {
+ MemoryMapException.unalignedAddress(addr);
+ }
+ // Check file offset is page aligned
+ /*if ((offset % PAGE_SIZE) != 0) {
+ MemoryMapException.unalignedFileOffset(offset);
+ }*/
+
+ if (DBT_Options.debugRuntime) {
+ System.out.println("Mapping file " + file + " offset=" + offset
+ + " addr=0x" + Integer.toHexString(addr) + " len=" + len
+ + (read ? " r" : " -") + (write ? "w" : "-") + (exec ? "x" : "-"));
+ }
+ addr = map(addr, len, read, write, exec);
+
+ try {
+ file.seek(offset);
+ for (int i = 0; i < len; i += 4) {
+
+ int[] page = getPage(getPTE(addr + i));
+ page[getOffset(addr + i)] = readInt(file);
+ }
+
+ return addr;
+
+ }
+ catch (java.io.IOException e) {
+ throw new Error(e);
+ }
+ }
+
+ /**
+ * Unmap a page of memory
+ *
+ * @param addr
+ * the address to unmap
+ * @param len
+ * the amount of memory to unmap
+ */
+ public final void unmap(int addr, int len) {
+ for (int i = 0; i < len; i += PAGE_SIZE) {
+
+ int pte = getPTE(addr + i);
+
+ if (getPage(pte) != null) {
+ readableMemory[pte] = null;
+ writableMemory[pte] = null;
+ executableMemory[pte] = null;
+ }
+ else {
+ throw new Error("Unmapping memory that's not mapped addr=0x"
+ + Integer.toHexString(addr) + " len=" + len);
+ }
+ }
+ }
+
+ /**
+ * Perform a 32bit load where addr is word aligned
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ protected final int loadWordAligned32(int addr) {
+ return readableMemory[getPTE(addr)][getOffset(addr)];
+ }
+
+ /**
+ * Perform a 32bit load where addr is word aligned and executable
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ protected final int loadWordAlignedInstruction32(int addr) {
+ return executableMemory[getPTE(addr)][getOffset(addr)];
+ }
+
+ /**
+ * Perform a byte load where the sign extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the sign extended result
+ */
+ public int loadSigned8(int addr) {
+ return (loadWordAligned32(addr) << ((3 - (addr & 0x3)) << 3)) >> 24;
+ // switch(addr & 3) {
+ // default:
+ // return (loadWordAligned32(addr) << 24) >> 24;
+ // case 1:
+ // return (loadWordAligned32(addr) << 16) >> 24;
+ // case 2:
+ // return (loadWordAligned32(addr) << 8) >> 24;
+ // case 3:
+ // return loadWordAligned32(addr) >> 24;
+ // }
+ }
+
+ /**
+ * Perform a byte load where the zero extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the zero extended result
+ */
+ public int loadUnsigned8(int addr) {
+ return (loadWordAligned32(addr) >> ((addr & 3) << 3)) & 0xFF;
+ // switch(addr & 3) {
+ // default:
+ // return loadWordAligned32(addr) & 0xFF;
+ // case 1:
+ // return (loadWordAligned32(addr) >> 8) & 0xFF;
+ // case 2:
+ // return (loadWordAligned32(addr) >> 16) & 0xFF;
+ // case 3:
+ // return loadWordAligned32(addr) >>> 24;
+ // }
+ }
+
+ /**
+ * Perform a 16bit load where the sign extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the sign extended result
+ */
+ public int loadSigned16(int addr) {
+ switch (addr & 3) {
+ default:
+ return (loadWordAligned32(addr) << 16) >> 16;
+ case 1:
+ return (loadWordAligned32(addr) << 8) >> 16;
+ case 2:
+ return loadWordAligned32(addr) >> 16;
+ case 3: // 2 loads to deal with spanning int problem
+ return (loadWordAligned32(addr) >>> 24)
+ | ((loadWordAligned32(addr + 1) << 24) >> 16);
+ }
+ }
+
+ /**
+ * Perform a 16bit load where the zero extended result fills the return value
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the zero extended result
+ */
+ public int loadUnsigned16(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAligned32(addr) & 0xFFFF;
+ case 1:
+ return (loadWordAligned32(addr) >> 8) & 0xFFFF;
+ case 2:
+ return (loadWordAligned32(addr) >> 16) & 0xFFFF;
+ case 3: // 2 loads to deal with spanning int problem
+ return (loadWordAligned32(addr) >>> 24)
+ | ((loadWordAligned32(addr + 1) << 8) & 0xFF00);
+ }
+ }
+
+ /**
+ * Perform a 32bit load
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int load32(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAligned32(addr);
+ case 1: // 2 loads to deal with spanning int problem
+ return ((loadWordAligned32(addr + 3) & 0xFF) << 24)
+ | (loadWordAligned32(addr) >>> 8);
+ case 2: // 2 loads to deal with spanning int problem
+ return ((loadWordAligned32(addr + 2) & 0xFFFF) << 16)
+ | (loadWordAligned32(addr) >>> 16);
+ case 3: // 2 loads to deal with spanning int problem
+ return ((loadWordAligned32(addr + 1) & 0xFFFFFF) << 8)
+ | (loadWordAligned32(addr) >>> 24);
+ }
+ }
+
+ /**
+ * Perform a 8bit load from memory that must be executable
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int loadInstruction8(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAlignedInstruction32(addr) & 0xFF;
+ case 1:
+ return (loadWordAlignedInstruction32(addr) >> 8) & 0xFF;
+ case 2:
+ return (loadWordAlignedInstruction32(addr) >> 16) & 0xFF;
+ case 3:
+ return loadWordAlignedInstruction32(addr) >>> 24;
+ }
+ }
+
+ @Override
+ public int loadInstruction16(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAlignedInstruction32(addr) >>> 16;
+ case 1:
+ return (loadWordAlignedInstruction32(addr) >> 8) & 0xFFFF;
+ case 2:
+ return loadWordAlignedInstruction32(addr) & 0xFFFF;
+ case 3: // 2 loads to deal with spanning int problem
+ return (loadWordAlignedInstruction32(addr) >>> 24)
+ | ((loadWordAlignedInstruction32(addr + 1) << 8) & 0xFF00);
+ }
+ }
+
+ /**
+ * Perform a 32bit load from memory that must be executable
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ public int loadInstruction32(int addr) {
+ switch (addr & 3) {
+ default:
+ return loadWordAlignedInstruction32(addr);
+ case 1: // 2 loads to deal with spanning int problem
+ return ((loadWordAlignedInstruction32(addr + 3) & 0xFF) << 24)
+ | (loadWordAlignedInstruction32(addr) >>> 8);
+ case 2: // 2 loads to deal with spanning int problem
+ return ((loadWordAlignedInstruction32(addr + 2) & 0xFFFF) << 16)
+ | (loadWordAlignedInstruction32(addr) >>> 16);
+ case 3: // 2 loads to deal with spanning int problem
+ return ((loadWordAlignedInstruction32(addr + 1) & 0xFFFFFF) << 8)
+ | (loadWordAlignedInstruction32(addr) >>> 24);
+ }
+ }
+
+ /**
+ * Perform a 32bit aligned store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ final protected void storeWordAligned32(int addr, int value) {
+ writableMemory[getPTE(addr)][getOffset(addr)] = value;
+ }
+
+ /**
+ * Perform a 32bit load, from writable memory, where addr is word aligned
+ *
+ * @param addr
+ * the address of the value to load
+ * @return the result
+ */
+ final protected int loadWordAligned32forWrite(int addr) {
+ return writableMemory[getPTE(addr)][getOffset(addr)];
+ }
+
+ /**
+ * Perform a byte store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public void store8(int addr, int value) {
+ switch (addr & 3) {
+ default:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFFFFFF00)
+ | (value & 0xFF));
+ break;
+ case 1:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFFFF00FF)
+ | ((value & 0xFF) << 8));
+ break;
+ case 2:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFF00FFFF)
+ | ((value & 0xFF) << 16));
+ break;
+ case 3:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0x00FFFFFF)
+ | (value << 24));
+ break;
+ }
+ }
+
+ /**
+ * Perform a 16bit store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public void store16(int addr, int value) {
+ switch (addr & 3) {
+ default:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFFFF0000)
+ | (value & 0xFFFF));
+ break;
+ case 1:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0xFF0000FF)
+ | ((value & 0xFFFF) << 8));
+ break;
+ case 2:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0x0000FFFF)
+ | (value << 16));
+ break;
+ case 3:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0x00FFFFFF)
+ | (value << 24));
+ storeWordAligned32(addr + 1,
+ (loadWordAligned32forWrite(addr + 1) & 0xFFFFFF00)
+ | ((value >> 8) & 0xFF));
+ break;
+ }
+ }
+
+ /**
+ * Perform a 32bit store
+ *
+ * @param value
+ * the value to store
+ * @param addr
+ * the address of where to store
+ */
+ public void store32(int addr, int value) {
+ switch (addr & 3) {
+ default:
+ storeWordAligned32(addr, value);
+ break;
+ case 1:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0x000000FF)
+ | (value << 8));
+ storeWordAligned32(addr + 3,
+ (loadWordAligned32forWrite(addr + 3) & 0xFFFFFF00) | (value >>> 24));
+ break;
+ case 2:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0x0000FFFF)
+ | (value << 16));
+ storeWordAligned32(addr + 2,
+ (loadWordAligned32forWrite(addr + 2) & 0xFFFF0000) | (value >>> 16));
+ break;
+ case 3:
+ storeWordAligned32(addr, (loadWordAligned32forWrite(addr) & 0x00FFFFFF)
+ | (value << 24));
+ storeWordAligned32(addr + 1,
+ (loadWordAligned32forWrite(addr + 1) & 0xFF000000) | (value >>> 8));
+ break;
+ }
+ }
+}
Deleted: src/org/binarytranslator/generic/memory/IntAddressedMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-08-15 16:24:05 UTC (rev 167)
+++ src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-08-20 14:12:59 UTC (rev 168)
@@ -1,673 +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.bi...
[truncated message content] |
|
From: <mic...@us...> - 2007-08-15 16:24:04
|
Revision: 167
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=167&view=rev
Author: michael_baer
Date: 2007-08-15 09:24:05 -0700 (Wed, 15 Aug 2007)
Log Message:
-----------
- Controlling ARM memory model using a command line paremter
- added new option to disable pearcolator inlining
Modified Paths:
--------------
src/org/binarytranslator/DBT_Options.java
src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-15 11:08:41 UTC (rev 166)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-15 16:24:05 UTC (rev 167)
@@ -175,25 +175,12 @@
}
else if (key.startsWith("arm:")) {
key = key.substring(4);
- parseArmOption(key, value);
+ ARM_Options.parseOption(key, value);
}
else {
throw new Error("Unknown argument.");
}
}
-
- private static void parseArmOption(String key, String value) {
- if (key.equalsIgnoreCase("optimizeByProfiling")) {
- ARM_Options.optimizeTranslationByProfiling = Boolean.parseBoolean(value);
- } else if (key.equalsIgnoreCase("flagEvaluation")) {
- ARM_Options.flagEvaluation = ARM_Options.FlagBehaviour.valueOf(value);
- } else if (key.equalsIgnoreCase("inline")) {
- ARM_Options.inlining = ARM_Options.InliningBehaviour.valueOf(value);
- }
- else {
- throw new Error("Unknown ARM option: " + key);
- }
- }
private static void parseDbtOption(String key, String value) {
if (key.equalsIgnoreCase("debugInstr")) {
Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-15 11:08:41 UTC (rev 166)
+++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-15 16:24:05 UTC (rev 167)
@@ -468,6 +468,9 @@
switch (ARM_Options.inlining)
{
+ case NoInlining:
+ return false;
+
case Default:
return super.inlineBranchInstruction(targetPc, jump);
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-15 11:08:41 UTC (rev 166)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-15 16:24:05 UTC (rev 167)
@@ -8,6 +8,7 @@
}
public enum InliningBehaviour {
+ NoInlining,
Default,
Functions,
FunctionCalls,
@@ -16,6 +17,11 @@
All,
}
+ public enum MemoryModel {
+ IntAddressed,
+ ByteAddressed
+ }
+
/** Set to true to enable a fastpath for the decoding of data processing instructions.. */
public final static boolean DATAPROCESSING_DECODER_FASTPATH = false;
@@ -27,4 +33,23 @@
/** Describes the default behaviour for dealing with ARM function calls and indirect jumps. */
public static InliningBehaviour inlining = InliningBehaviour.Default;
+
+ /** Sets the memory model that ARM shall use. */
+ public static MemoryModel memoryModel = MemoryModel.IntAddressed;
+
+
+ public static void parseOption(String key, String value) {
+ if (key.equalsIgnoreCase("optimizeByProfiling")) {
+ optimizeTranslationByProfiling = Boolean.parseBoolean(value);
+ } else if (key.equalsIgnoreCase("flagEvaluation")) {
+ flagEvaluation = ARM_Options.FlagBehaviour.valueOf(value);
+ } else if (key.equalsIgnoreCase("inline")) {
+ inlining = ARM_Options.InliningBehaviour.valueOf(value);
+ } else if (key.equalsIgnoreCase("memory")) {
+ memoryModel = ARM_Options.MemoryModel.valueOf(value);
+ }
+ else {
+ throw new Error("Unknown ARM option: " + key);
+ }
+ }
}
Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-15 11:08:41 UTC (rev 166)
+++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-15 16:24:05 UTC (rev 167)
@@ -5,10 +5,12 @@
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.decoder.ARM_Options;
import org.binarytranslator.arch.arm.os.process.image.ARM_ImageProcessSpace;
import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace;
import org.binarytranslator.generic.decoder.CodeTranslator;
import org.binarytranslator.generic.decoder.Interpreter;
+import org.binarytranslator.generic.memory.ByteAddressedMemory;
import org.binarytranslator.generic.memory.IntAddressedMemory;
import org.binarytranslator.generic.os.loader.Loader;
import org.binarytranslator.generic.os.process.ProcessSpace;
@@ -38,7 +40,20 @@
protected ARM_ProcessSpace() {
registers = new ARM_Registers();
- memory = new IntAddressedMemory();
+
+ switch (ARM_Options.memoryModel) {
+ case ByteAddressed:
+ memory = new ByteAddressedMemory();
+ break;
+
+ case IntAddressed:
+ memory = new IntAddressedMemory();
+ break;
+
+ default:
+ throw new RuntimeException("Unexpected ARM memory model setting: " + ARM_Options.memoryModel);
+ }
+
}
/**
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-15 11:08:39
|
Revision: 166
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=166&view=rev
Author: michael_baer
Date: 2007-08-15 04:08:41 -0700 (Wed, 15 Aug 2007)
Log Message:
-----------
- Disabled debug output by default
- added options to show arm stack and heap range
Modified Paths:
--------------
src/org/binarytranslator/DBT_Options.java
src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java
src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-14 17:25:25 UTC (rev 165)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-15 11:08:41 UTC (rev 166)
@@ -25,11 +25,8 @@
public final static boolean buildForSunVM = false;
/** Enable the profiling of application during interpretation? */
- public final static boolean profileDuringInterpretation = false;
+ public final static boolean profileDuringInterpretation = true;
- /** Debug binary loading */
- public final static boolean debugLoader = true;
-
/** Are unimplemented system calls fatal? */
public final static boolean unimplementedSystemCallsFatal = false;
@@ -77,38 +74,41 @@
public final static boolean eliminateRegisterFills = true;
/** Print dissassembly of translated instructions. */
- public static boolean debugInstr = true;
+ public static boolean debugInstr = false;
/** Print information about the lazy resolution of branch addresses...*/
- public static boolean debugBranchResolution = true;
+ public static boolean debugBranchResolution = false;
/** During code translation, print information about the creation of basic blocks. */
public final static boolean debugCFG = false;
-
- /** Debug using GDB? */
- public static boolean gdbStub = false;
-
- /** GDB stub port */
- public static int gdbStubPort = 1234;
- /** Just a temporary variable for testing. It describes, when the staged emulation controller switches from interpretation to translation. */
- public static int minTraceValue = 20;
+ /** Debug binary loading */
+ public static boolean debugLoader = false;
/** Print debug information during the translation of instructions. */
- public static boolean debugTranslation = true;
+ public static boolean debugTranslation = false;
/** In ProcessSpace, print syscall numbers. */
- public static boolean debugSyscall = true;
+ public static boolean debugSyscalls = false;
/** In ProcessSpace, print syscall numbers. */
- public static boolean debugSyscallMore = false;
+ public static boolean debugSyscallsMore = false;
/** Print out various messages about the emulator starting. */
- public static boolean debugRuntime = true;
+ public static boolean debugRuntime = false;
/** Print out messages from the memory system */
public static boolean debugMemory = false;
+
+ /** Debug using GDB? */
+ public static boolean gdbStub = false;
+
+ /** GDB stub port */
+ public static int gdbStubPort = 1234;
+ /** Just a temporary variable for testing. It describes, when the staged emulation controller switches from interpretation to translation. */
+ public static int minTraceValue = 20;
+
/** Inline calls to descendents of callbased memory? */
public static boolean inlineCallbasedMemory = false;
@@ -204,12 +204,14 @@
debugBranchResolution = Boolean.parseBoolean(value);
} else if (key.equalsIgnoreCase("debugMemory")) {
debugMemory = Boolean.parseBoolean(value);
- } else if (key.equalsIgnoreCase("debugSyscall")) {
- debugSyscall = Boolean.parseBoolean(value);
- } else if (key.equalsIgnoreCase("debugSyscallMore")) {
- debugSyscallMore = Boolean.parseBoolean(value);
+ } else if (key.equalsIgnoreCase("debugSyscalls")) {
+ debugSyscalls = Boolean.parseBoolean(value);
+ } else if (key.equalsIgnoreCase("debugSyscallsMore")) {
+ debugSyscallsMore = Boolean.parseBoolean(value);
} else if (key.equalsIgnoreCase("debugTranslation")) {
debugTranslation = Boolean.parseBoolean(value);
+ } else if (key.equalsIgnoreCase("debugLoader")) {
+ debugLoader = Boolean.parseBoolean(value);
} else if (key.equalsIgnoreCase("instrOpt0")) {
instrOpt0 = Integer.parseInt(value);
} else if (key.equalsIgnoreCase("instrOpt1")) {
Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-08-14 17:25:25 UTC (rev 165)
+++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-08-15 11:08:41 UTC (rev 166)
@@ -107,7 +107,7 @@
public void doSysCall(int callNum) {
try {
- if (DBT_Options.debugSyscall)
+ if (DBT_Options.debugSyscalls)
System.out.println("Executing Angel Syscall: " + callNum);
sysCalls[callNum].execute();
@@ -310,7 +310,7 @@
String fileName = readString(ptrBuffer, length);
- if (DBT_Options.debugSyscallMore)
+ if (DBT_Options.debugSyscallsMore)
System.out.println("Opening file: " + fileName);
try {
Modified: src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java
===================================================================
--- src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-08-14 17:25:25 UTC (rev 165)
+++ src/org/binarytranslator/generic/os/abi/linux/LinuxSystemCalls.java 2007-08-15 11:08:41 UTC (rev 166)
@@ -187,7 +187,7 @@
public void doSysCall() {
int sysCallNumber = src.getSysCallNumber();
- if (DBT_Options.debugSyscall)
+ if (DBT_Options.debugSyscalls)
System.err.println("Syscall " + sysCallToString(sysCallNumber));
arguments = src.getSysCallArguments();
@@ -357,7 +357,7 @@
// accordingly. args[0] points to the file name.
String fileName = memoryReadString(pathname);
- if (DBT_Options.debugSyscall)
+ if (DBT_Options.debugSyscalls)
System.err.println("Program tries to open: " + fileName);
FileMode mode;
@@ -527,7 +527,7 @@
String filename = memoryReadString(ptrFilename);
- if (DBT_Options.debugSyscallMore)
+ if (DBT_Options.debugSyscallsMore)
System.err.println("Stat64() denies existance of file: " + filename);
src.setSysCallError(errno.ENOENT);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-14 17:25:21
|
Revision: 165
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=165&view=rev
Author: michael_baer
Date: 2007-08-14 10:25:25 -0700 (Tue, 14 Aug 2007)
Log Message:
-----------
- Fixed bug with overlapping translator registers during MultiplyAccumulate
- Check in missing file from last commit
Modified Paths:
--------------
src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java
Added Paths:
-----------
src/org/binarytranslator/generic/fault/InsufficientMemoryException.java
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-14 15:32:09 UTC (rev 164)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-14 17:25:25 UTC (rev 165)
@@ -1955,12 +1955,16 @@
OPT_RegisterOperand result = arm2ir.getRegister(i.Rd);
//calculate the result
- arm2ir.appendInstruction(Binary.create(INT_MUL, result, operand1, operand2));
-
if (i.accumulate) {
+ OPT_RegisterOperand tmp = arm2ir.getTempInt(0);
+ arm2ir.appendInstruction(Binary.create(INT_MUL, tmp, operand1, operand2));
+
OPT_Operand operand3 = arm2ir.getRegister(i.Rn);
- arm2ir.appendInstruction(Binary.create(INT_ADD, result.copyRO(), result.copy(), operand3));
+ arm2ir.appendInstruction(Binary.create(INT_ADD, result.copyRO(), tmp.copy(), operand3));
}
+ else {
+ arm2ir.appendInstruction(Binary.create(INT_MUL, result, operand1, operand2));
+ }
if (i.updateConditionCodes) {
//set the negative & zero flag
Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-08-14 15:32:09 UTC (rev 164)
+++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-08-14 17:25:25 UTC (rev 165)
@@ -665,7 +665,7 @@
}
writeString(cmdLine, ptrBuffer);
- ps.memory.store32(ptrParamBlock + 4, cmdLine.length() + 1);
+ ps.memory.store32(ptrParamBlock + 4, cmdLine.length());
setReturn(0);
}
}
Added: src/org/binarytranslator/generic/fault/InsufficientMemoryException.java
===================================================================
--- src/org/binarytranslator/generic/fault/InsufficientMemoryException.java (rev 0)
+++ src/org/binarytranslator/generic/fault/InsufficientMemoryException.java 2007-08-14 17:25:25 UTC (rev 165)
@@ -0,0 +1,20 @@
+package org.binarytranslator.generic.fault;
+
+import org.binarytranslator.generic.os.process.ProcessSpace;
+
+/**
+ * Thrown when a process space runs out of (virtual) memory when performing an operation.
+ *
+ */
+public class InsufficientMemoryException extends RuntimeException {
+ private final String operation;
+
+ public InsufficientMemoryException(ProcessSpace ps, String operation) {
+ this.operation = operation;
+ }
+
+ @Override
+ public String toString() {
+ return "InsufficientMemoryException (Operation: " + operation + ")";
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-14 15:32:08
|
Revision: 164
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=164&view=rev
Author: michael_baer
Date: 2007-08-14 08:32:09 -0700 (Tue, 14 Aug 2007)
Log Message:
-----------
- Various smaller performance fixes
- Added functions to inline a call to CodeTranslator
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_Interpreter.java
src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.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/arch/ppc/decoder/PPC2IR.java
src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java
src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java
src/org/binarytranslator/generic/decoder/CodeTranslator.java
src/org/binarytranslator/generic/execution/StagedEmulationController.java
src/org/binarytranslator/generic/memory/CallBasedMemory.java
src/org/binarytranslator/generic/memory/IntAddressedMemory.java
src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java
src/org/binarytranslator/generic/os/loader/elf/ELF_File.java
src/org/binarytranslator/generic/os/process/ProcessSpace.java
src/org/binarytranslator/vmInterface/DBT_Trace.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -108,6 +108,9 @@
/** Print out messages from the memory system */
public static boolean debugMemory = false;
+
+ /** Inline calls to descendents of callbased memory? */
+ public static boolean inlineCallbasedMemory = false;
/** The user ID for the user running the command */
public final static int UID = 1000;
@@ -184,7 +187,7 @@
ARM_Options.optimizeTranslationByProfiling = Boolean.parseBoolean(value);
} else if (key.equalsIgnoreCase("flagEvaluation")) {
ARM_Options.flagEvaluation = ARM_Options.FlagBehaviour.valueOf(value);
- } else if (key.equalsIgnoreCase("inlining")) {
+ } else if (key.equalsIgnoreCase("inline")) {
ARM_Options.inlining = ARM_Options.InliningBehaviour.valueOf(value);
}
else {
@@ -229,6 +232,8 @@
saveProfileToFile = value;
} else if (key.equalsIgnoreCase("minTraceValue")) {
minTraceValue = Integer.parseInt(value);
+ } else if (key.equalsIgnoreCase("inlineCallbasedMemory")) {
+ inlineCallbasedMemory = Boolean.parseBoolean(value);
}
else {
throw new Error("Unknown DBT option: " + key);
Modified: src/org/binarytranslator/Main.java
===================================================================
--- src/org/binarytranslator/Main.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/Main.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -85,6 +85,10 @@
System.err.println("The specified executable '" + DBT_Options.executableFile + "' could not be found.");
return;
}
+
+ if (DBT.VerifyAssertions) {
+ System.err.println("WARNING: Assertions are enabled.");
+ }
try {
report("Loading " + DBT_Options.executableFile);
Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -477,12 +477,27 @@
else
return super.inlineBranchInstruction(targetPc, jump);
+ case FunctionCalls:
+ if (jump.type == BranchType.CALL)
+ return true;
+ else
+ return super.inlineBranchInstruction(targetPc, jump);
+
+ case FunctionReturns:
+ if (jump.type == BranchType.CALL)
+ return true;
+ else
+ return super.inlineBranchInstruction(targetPc, jump);
+
case Functions:
if (jump.type == BranchType.CALL || jump.type == BranchType.RETURN)
return true;
else
return super.inlineBranchInstruction(targetPc, jump);
+ case All:
+ return true;
+
default:
throw new RuntimeException("Unexpected inlining type.");
}
@@ -782,6 +797,9 @@
* The operand which is to be rotated.
* @param rotation
* The amount of rotation that is to be applied to the operand.
+ *
+ * @param inline
+ * Shall the invokation of this rotate right be inlined?
*/
public void appendRotateRight(OPT_RegisterOperand result, OPT_Operand rotatedOperand, OPT_Operand rotation) {
VM_TypeReference IntegerType = VM_TypeReference
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -374,7 +374,7 @@
/** The successor of this instruction, if the condition evaluates to false.*/
private final int conditionFalseSuccessor;
- /** The address of the successor of this instrction if it is constant, otherwise -1. */
+ /** The address of the successor of this instruction if it is constant, otherwise -1. */
private final int successorInstruction;
/** The address of this instruction. */
@@ -406,7 +406,10 @@
}
if (successorInstruction != -1) {
- ps.branchInfo.profileBranch(instructionAddress, conditionTrueSuccessor);
+ if (conditionTrueSuccessor == conditionFalseSuccessor)
+ ps.branchInfo.profileBranch(instructionAddress, instructionAddress);
+ else
+ ps.branchInfo.profileBranch(instructionAddress, conditionTrueSuccessor);
}
}
else {
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -10,7 +10,10 @@
public enum InliningBehaviour {
Default,
Functions,
- DynamicJumps
+ FunctionCalls,
+ FunctionReturns,
+ DynamicJumps,
+ All,
}
/** Set to true to enable a fastpath for the decoding of data processing instructions.. */
@@ -22,5 +25,6 @@
/** This variable describes, if the translated program shall be optimized using lazy evaluation.*/
public static FlagBehaviour flagEvaluation = FlagBehaviour.Lazy;
+ /** Describes the default behaviour for dealing with ARM function calls and indirect jumps. */
public static InliningBehaviour inlining = InliningBehaviour.Default;
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -764,7 +764,7 @@
*/
private float getSkipProbability() {
- if (ARM_Options.optimizeTranslationByProfiling)
+ if (!ARM_Options.optimizeTranslationByProfiling)
return -1f;
return ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4));
@@ -1279,7 +1279,7 @@
}
}
- /** Subtract. <code>Rd = op1 - op2 </code>.*/
+ /** Subtract. <code>Rd = op1 - op2</code>.*/
private final class DataProcessing_Sub extends DataProcessing {
public DataProcessing_Sub(ARM_Instructions.DataProcessing instr) {
Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -48,6 +48,18 @@
/** The directory in which temporary files are created. Note that the path is expected to end with a path delimiter.*/
private final static String TEMP_FILE_DIR = "/tmp/";
+ /** The first address on the heap. */
+ private int heapBegin;
+
+ /** The last address on the heap. */
+ private int heapEnd;
+
+ /** The first address on the stack. */
+ private int stackBegin;
+
+ /** The last address on the stack*/
+ private int stackEnd;
+
/** The file handle that is distributed with the next call to {@link #addFile(RandomAccessFile)}.
* Valid Angle handles are non-zero values (i.e. >= 1).*/
private int nextFileHandle = 1;
@@ -55,7 +67,7 @@
/** */
private AngelSystemCall[] sysCalls;
- public AngelSystemCalls(ARM_ProcessSpace ps) {
+ public AngelSystemCalls(ARM_ProcessSpace ps, int heapBegin, int heapEnd, int stackBegin, int stackEnd) {
this.ps = ps;
sysCalls = new AngelSystemCall[0x32];
@@ -84,6 +96,12 @@
sysCalls[0x18] = new Sys_Exit();
sysCalls[0x30] = new Sys_Elapsed();
sysCalls[0x31] = new Sys_TickFreq();
+
+ this.heapBegin = heapBegin;
+ this.heapEnd = heapEnd;
+
+ this.stackBegin = stackBegin;
+ this.stackEnd = stackEnd;
}
public void doSysCall(int callNum) {
@@ -128,7 +146,7 @@
}
}
- private interface AngelFileStream {
+ private static interface AngelFileStream {
boolean isTty();
int getLength();
@@ -143,7 +161,7 @@
void seek(long pos) throws IOException;
}
- private class ConsoleStream implements AngelFileStream {
+ private static class ConsoleStream implements AngelFileStream {
private String previousInputLine = null;
@@ -203,7 +221,7 @@
}
}
- private class FileStream implements AngelFileStream {
+ private static class FileStream implements AngelFileStream {
private final RandomAccessFile file;
@@ -630,11 +648,11 @@
String cmdLine = DBT_Options.executableFile;
- if (cmdLine.contains(" "))
+ if (cmdLine.contains(" ") && !cmdLine.contains("\""))
cmdLine = '"' + cmdLine + '"';
for(String s : DBT_Options.executableArguments) {
- if (s.contains(" ")) {
+ if (s.contains(" ") && !s.contains("\"")) {
s = '"' + s + '"';
}
@@ -659,10 +677,10 @@
int ptrParamBlock = ps.registers.get(1);
//return that we couldn't calculate any of the requested heap size values
- ps.memory.store32(ptrParamBlock, 0);
- ps.memory.store32(ptrParamBlock + 4, 0);
- ps.memory.store32(ptrParamBlock + 8, 0);
- ps.memory.store32(ptrParamBlock + 12, 0);
+ ps.memory.store32(ptrParamBlock, heapBegin);
+ ps.memory.store32(ptrParamBlock + 4, heapEnd);
+ ps.memory.store32(ptrParamBlock + 8, stackBegin);
+ ps.memory.store32(ptrParamBlock + 12, stackEnd);
}
}
Modified: src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/arch/arm/os/process/ARM_ProcessSpace.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -9,7 +9,7 @@
import org.binarytranslator.arch.arm.os.process.linux.ARM_LinuxProcessSpace;
import org.binarytranslator.generic.decoder.CodeTranslator;
import org.binarytranslator.generic.decoder.Interpreter;
-import org.binarytranslator.generic.memory.ByteAddressedMemory;
+import org.binarytranslator.generic.memory.IntAddressedMemory;
import org.binarytranslator.generic.os.loader.Loader;
import org.binarytranslator.generic.os.process.ProcessSpace;
import org.binarytranslator.vmInterface.DBT_Trace;
@@ -38,7 +38,7 @@
protected ARM_ProcessSpace() {
registers = new ARM_Registers();
- memory = new ByteAddressedMemory();
+ memory = new IntAddressedMemory();
}
/**
@@ -49,6 +49,7 @@
* the generation context for the HIR generation
* @return a HIR generator
*/
+ @Override
public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) {
return new ARM2IR(context, trace);
}
Modified: src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/arch/arm/os/process/image/ARM_ImageProcessSpace.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -1,26 +1,55 @@
package org.binarytranslator.arch.arm.os.process.image;
import org.binarytranslator.DBT;
+import org.binarytranslator.DBT_Options;
import org.binarytranslator.arch.arm.decoder.ARM_InstructionDecoder;
import org.binarytranslator.arch.arm.decoder.ARM_Instructions;
import org.binarytranslator.arch.arm.os.abi.semihosting.AngelSystemCalls;
import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace;
import org.binarytranslator.arch.arm.os.process.ARM_Registers;
import org.binarytranslator.generic.execution.GdbController.GdbTarget;
-import org.binarytranslator.generic.memory.AutoMappingMemory;
+import org.binarytranslator.generic.fault.InsufficientMemoryException;
import org.binarytranslator.generic.os.loader.Loader;
public class ARM_ImageProcessSpace extends ARM_ProcessSpace {
- private AngelSystemCalls sysCalls = new AngelSystemCalls(this);
+ private AngelSystemCalls sysCalls;
+ private final int STACK_SIZE = 4096 * 10;
+ private final int HEAP_SIZE = 4096 * 10;
public ARM_ImageProcessSpace() {
super();
//make sure that pages of memory are automatically mapped in as they are requested.
- memory = new AutoMappingMemory(memory);
+ //memory = new AutoMappingMemory(memory);
}
+ private int allocateFreeMemoryArea(int stackSize) throws InsufficientMemoryException
+ {
+ int pagesize = memory.getPageSize();
+ int stackStart = -1;
+ int checkedAddress = stackStart;
+
+ while (checkedAddress < 0 || checkedAddress > pagesize) {
+ if (memory.isMapped(checkedAddress)) {
+ //we cannot extend the stack into this page
+ stackStart = checkedAddress - pagesize;
+ }
+ else {
+ int stackspace = Math.abs(stackStart - checkedAddress) + pagesize;
+
+ if (stackspace >= stackSize) {
+ memory.ensureMapped(stackStart - stackSize + 1, stackStart);
+ return stackStart - stackSize + 1;
+ }
+ }
+
+ checkedAddress -= pagesize;
+ }
+
+ throw new InsufficientMemoryException(this, "Allocate free memory area for ARM stack and heap.");
+ }
+
@Override
public void doSysCall() {
@@ -91,6 +120,15 @@
@Override
public void initialise(Loader loader) {
registers.set(ARM_Registers.PC, loader.getEntryPoint());
+ int stackBegin = allocateFreeMemoryArea(STACK_SIZE);
+ int heapBegin = allocateFreeMemoryArea(HEAP_SIZE);
+
+ if (DBT_Options.debugMemory || DBT_Options.debugLoader) {
+ System.out.println(String.format("Placing ARM Heap from 0x%x to 0x%x.", heapBegin, heapBegin + HEAP_SIZE - 1));
+ System.out.println(String.format("Placing ARM Stack from 0x%x to 0x%x.", stackBegin, stackBegin + STACK_SIZE - 1));
+ }
+
+ sysCalls = new AngelSystemCalls(this, heapBegin, heapBegin + HEAP_SIZE, stackBegin, stackBegin + STACK_SIZE);
}
}
Modified: src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java
===================================================================
--- src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/arch/ppc/decoder/PPC2IR.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -29,6 +29,7 @@
import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand;
import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext;
import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator;
+import org.jikesrvm.compilers.opt.ir.OPT_IR;
import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand;
import org.jikesrvm.compilers.opt.ir.OPT_LocationOperand;
import org.jikesrvm.compilers.opt.ir.OPT_Operators;
@@ -272,6 +273,18 @@
report("CFG at end of constructor:\n" + gc.cfg);
}
}
+
+ /**
+ * Should a trace follow a branch and link instruction or should it terminate
+ * the trace?
+ *
+ * @param pc
+ * the address of the branch and link instruction
+ * @return whether the trace should continue
+ */
+ public boolean traceContinuesAfterBranchAndLink(int pc) {
+ return shallTraceStop() == false;
+ }
/**
* Translate the instruction at the given pc
Modified: src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/arch/ppc/os/process/PPC_ProcessSpace.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -140,6 +140,7 @@
* the generation context for the HIR generation
* @return a HIR generator
*/
+ @Override
public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) {
return new PPC2IR(context, trace);
}
Modified: src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java
===================================================================
--- src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/arch/x86/os/process/X86_ProcessSpace.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -12,7 +12,6 @@
import java.util.Hashtable;
import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext;
-
import org.binarytranslator.DBT_Options;
import org.binarytranslator.generic.os.process.ProcessSpace;
import org.binarytranslator.generic.memory.ByteAddressedMemory;
@@ -149,6 +148,7 @@
* @param context the generation context for the HIR generation
* @return a HIR generator
*/
+ @Override
public CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) {
return new X862IR(context, trace);
}
Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java
===================================================================
--- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -29,6 +29,7 @@
import org.jikesrvm.classloader.VM_MethodReference;
import org.jikesrvm.classloader.VM_TypeReference;
import org.jikesrvm.compilers.opt.OPT_Constants;
+import org.jikesrvm.compilers.opt.OPT_InlineDecision;
import org.jikesrvm.compilers.opt.ir.Athrow;
import org.jikesrvm.compilers.opt.ir.BBend;
import org.jikesrvm.compilers.opt.ir.Call;
@@ -45,6 +46,7 @@
import org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand;
import org.jikesrvm.compilers.opt.ir.OPT_GenerationContext;
import org.jikesrvm.compilers.opt.ir.OPT_HIRGenerator;
+import org.jikesrvm.compilers.opt.ir.OPT_Inliner;
import org.jikesrvm.compilers.opt.ir.OPT_Instruction;
import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand;
import org.jikesrvm.compilers.opt.ir.OPT_MethodOperand;
@@ -130,7 +132,7 @@
public final ProcessSpace ps;
/** The VM method's generation context. */
- protected OPT_GenerationContext gc;
+ protected final OPT_GenerationContext gc;
/** The OPT_BasicBlock in which instructions are currently being inserted */
protected OPT_BasicBlock currentBlock;
@@ -208,7 +210,7 @@
* @param context
* The JRVM generation context for this trace.
*/
- protected CodeTranslator(OPT_GenerationContext context,
+ protected CodeTranslator(OPT_GenerationContext context,
DBT_Trace trace) {
// Store the trace that we're invoked from
@@ -284,7 +286,12 @@
printNextBlocks(preFillBlock, 50);
}
+ try {
((DBT_Trace) gc.method).setNumberOfInstructions(numberOfInstructions);
+ }
+ catch (ClassCastException e) {
+ System.err.println("Error casting " + gc.method + " to DBT_Trace.");
+ }
}
@@ -531,7 +538,7 @@
/**
* Get the generation context.
*/
- public OPT_GenerationContext getGenerationContext() {
+ public final OPT_GenerationContext getGenerationContext() {
return gc;
}
@@ -545,7 +552,7 @@
* @param hirBlock
* The block that is to be registered.
*/
- protected void registerMapping(int pc, Laziness lazy, OPT_BasicBlock hirBlock) {
+ protected final void registerMapping(int pc, Laziness lazy, OPT_BasicBlock hirBlock) {
blockMap.put(lazy.makeKey(pc), hirBlock);
}
@@ -559,7 +566,7 @@
* The lazy state assumed within the returned trace.
* @return An appropriate basic block or null if no translation exists.
*/
- protected OPT_BasicBlock findMapping(int pc, Laziness lazy) {
+ protected final OPT_BasicBlock findMapping(int pc, Laziness lazy) {
return blockMap.get(lazy.makeKey(pc));
}
@@ -757,13 +764,24 @@
* within the code cache c) The trace is already too long d) the branch is
* supposedly a CALL or RETURN
*/
+
+ boolean decision = DBT_Options.singleInstrTranslation == false && jump.type == BranchType.DIRECT_BRANCH && !shallTraceStop();
+ if (!decision) {
+
+ if (DBT_Options.debugBranchResolution) {
+ String text = (!decision ? "Not inlining " : "Inlining ");
+ text += jump.type + " to 0x" + Integer.toHexString(targetPc);
+ System.out.println(text);
+ }
+
+ return false;
+ }
+
+ //only query the code cache if we have to
DBT_Trace compiledTrace = ps.codeCache.tryGet(targetPc);
+ decision = (compiledTrace == null || compiledTrace.getNumberOfInstructions() < 20) ;
- boolean decision = DBT_Options.singleInstrTranslation == false
- && (compiledTrace == null || compiledTrace.getNumberOfInstructions() < 20) && !shallTraceStop()
- && jump.type != BranchType.CALL && jump.type != BranchType.RETURN;
-
if (DBT_Options.debugBranchResolution) {
String text = (!decision ? "Not inlining " : "Inlining ");
text += jump.type + " to 0x" + Integer.toHexString(targetPc);
@@ -967,18 +985,6 @@
}
/**
- * Should a trace follow a branch and link instruction or should it terminate
- * the trace?
- *
- * @param pc
- * the address of the branch and link instruction
- * @return whether the trace should continue
- */
- public boolean traceContinuesAfterBranchAndLink(int pc) {
- return shallTraceStop() == false;
- }
-
- /**
* Load all the registers from the ProcessSpace into the pre-fill block
*/
private void preFillAllRegisters() {
@@ -1169,6 +1175,7 @@
if (intTemps == null) {
intTemps = new OPT_Register[10];
}
+
OPT_Register result = intTemps[num];
if (result == null) {
OPT_RegisterOperand regOp = gc.temps.makeTempInt();
@@ -1459,7 +1466,60 @@
callInstruction.bcIndex = trace.registerDynamicLink(methodRef, callType);
appendInstruction(callInstruction);
}
+
+ /**
+ * Execute an inlining decision inlDec for the CALL instruction
+ * callSite that is contained in ir.
+ *
+ * @param inlDec the inlining decision to execute
+ * @param ir the governing IR
+ * @param callSite the call site to inline
+ */
+ public void appendInlinedCall(OPT_Instruction callSite) {
+
+ if (DBT.VerifyAssertions)
+ DBT._assert(Call.conforms(callSite));
+
+ OPT_BasicBlock next = createBlockAfterCurrent();
+
+ //Find out where the call site is and isolate it in its own basic block.
+ currentBlock = createBlockAfterCurrent();
+ currentBlock.appendInstruction(callSite);
+
+ OPT_BasicBlock in = currentBlock.prevBasicBlockInCodeOrder();
+ OPT_BasicBlock out = currentBlock.nextBasicBlockInCodeOrder();
+
+ // Clear the sratch object of any register operands being
+ // passed as parameters.
+ // BC2IR uses this field for its own purposes, and will be confused
+ // if the scratch object has been used by someone else and not cleared.
+ for (int i = 0; i < Call.getNumberOfParams(callSite); i++) {
+ OPT_Operand arg = Call.getParam(callSite, i);
+ if (arg instanceof OPT_RegisterOperand) {
+ ((OPT_RegisterOperand) arg).scratchObject = null;
+ }
+ }
+ // Execute the inlining decision, updating ir.gc's state.
+ OPT_InlineDecision inlDec = OPT_InlineDecision.YES(Call.getMethod(callSite).getTarget(), "");
+ OPT_GenerationContext childgc = OPT_Inliner.execute(inlDec, gc, null, callSite);
+
+ // Splice the callee into the caller's code order
+ gc.cfg.removeFromCFGAndCodeOrder(currentBlock);
+ gc.cfg.breakCodeOrder(in, out);
+ gc.cfg.linkInCodeOrder(in, childgc.cfg.firstInCodeOrder());
+ gc.cfg.linkInCodeOrder(childgc.cfg.lastInCodeOrder(), out);
+
+ // Splice the callee into the caller's CFG
+ in.insertOut(childgc.prologue);
+
+ if (childgc.epilogue != null) {
+ childgc.epilogue.insertOut(out);
+ }
+
+ currentBlock = next;
+ }
+
/** Report some debug output */
protected abstract void report(String str);
@@ -1470,8 +1530,7 @@
* Plant instructions modifying a lazy state into one with no laziness
*
* @param laziness
- * the laziness to modify
- */
+ * the laziness to modify */
public abstract void resolveLaziness(Laziness laziness);
/**
@@ -1481,20 +1540,17 @@
* the status of the lazy evaluation
* @param pc
* the program counter for the instruction
- * @return the next instruction address or -1
- */
+ * @return the next instruction address or -1 */
protected abstract int translateInstruction(Laziness lazy, int pc);
/**
* Fill all the registers from the ProcessSpace, that is take the register
- * values from the process space and place them in the traces registers.
- */
+ * values from the process space and place them in the traces registers. */
protected abstract void fillAllRegisters();
/**
* Spill all the registers, that is put them from the current running trace
- * into the process space
- */
+ * into the process space. */
protected abstract void spillAllRegisters();
/** Return an array of unused registers */
Modified: src/org/binarytranslator/generic/execution/StagedEmulationController.java
===================================================================
--- src/org/binarytranslator/generic/execution/StagedEmulationController.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/generic/execution/StagedEmulationController.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -4,6 +4,7 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.TreeMap;
import org.binarytranslator.DBT;
import org.binarytranslator.DBT_Options;
@@ -38,7 +39,7 @@
}
/** Maps a dynamic basic block to the address of the first instruction within that block. */
- private final HashMap<Integer, DynamicBasicBlock> traceCache = new HashMap<Integer, DynamicBasicBlock>();
+ private final TreeMap<Integer, DynamicBasicBlock> traceCache = new TreeMap<Integer, DynamicBasicBlock>();
/** The interpreter that is used to perform the actual execution of single instructions. */
private final Interpreter interpreter;
@@ -70,10 +71,13 @@
//No, so stop and create a trace from the decoded instructions
DynamicBasicBlock newTrace = new DynamicBasicBlock(instructions);
- if (instructions.size() > 3) {
+// add this trace to the trace cache
+ traceCache.put(traceStart, newTrace);
+
+ /*if (instructions.size() > 3) {
//add this trace to the trace cache, if it contains enough instructions
traceCache.put(traceStart, newTrace);
- }
+ }*/
return newTrace;
}
@@ -94,6 +98,8 @@
trace.compiledTrace = new DBT_Trace(ps, pc);
trace.compiledTrace.compile();
trace.instructions = null;
+
+ ps.codeCache.add(pc, trace.compiledTrace);
}
/**
Modified: src/org/binarytranslator/generic/memory/CallBasedMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/generic/memory/CallBasedMemory.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -99,7 +99,7 @@
/**
* A translation helper for generating code
*/
- protected CodeTranslator helper;
+ protected CodeTranslator translator;
/**
* The generation context we're translating within
@@ -162,7 +162,7 @@
* page table into a register
*/
public void initTranslate(CodeTranslator helper) {
- this.helper = helper;
+ this.translator = helper;
this.gc = helper.getGenerationContext();
OPT_RegisterOperand memoryOp = helper.makeTemp(memoryType);
helper.appendInstruction(GetField.create(GETFIELD, memoryOp,
@@ -187,21 +187,27 @@
*/
private void translateLoad(VM_Method loadMethod, int bcIndex,
OPT_Operand addr, OPT_RegisterOperand dest) {
- OPT_Instruction s = Call.create(CALL, dest, null, null, null, 2);
+ OPT_Instruction s = Call.create(CALL, dest.copyRO(), null, null, null, 2);
VM_MethodReference loadMethRef = loadMethod.getMemberRef()
.asMethodReference();
- OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(loadMethRef,
- loadMethod);
+ OPT_MethodOperand methOp = OPT_MethodOperand.VIRTUAL(loadMethRef, loadMethod);
OPT_RegisterOperand memoryOp = new OPT_RegisterOperand(memory, memoryType);
Call.setParam(s, 0, memoryOp); // Sets 'this' pointer
- Call.setParam(s, 1, addr);
+ Call.setParam(s, 1, addr.copy());
Call.setGuard(s, new OPT_TrueGuardOperand());
Call.setMethod(s, methOp);
Call.setAddress(s, new OPT_AddressConstantOperand(loadMethod.getOffset()));
- s.position = gc.inlineSequence;
- s.bcIndex = bcIndex;
- helper.appendInstruction(s);
+
+ if (DBT_Options.inlineCallbasedMemory) {
+ translator.appendInlinedCall(s);
+ }
+ else
+ {
+ s.position = gc.inlineSequence;
+ s.bcIndex = bcIndex;
+ translator.appendInstruction(s);
+ }
}
/**
@@ -335,14 +341,21 @@
storeMethod);
OPT_RegisterOperand memoryOp = new OPT_RegisterOperand(memory, memoryType);
Call.setParam(s, 0, memoryOp); // Sets 'this' pointer
- Call.setParam(s, 1, addr);
- Call.setParam(s, 2, src);
+ Call.setParam(s, 1, addr.copy());
+ Call.setParam(s, 2, src.copy());
Call.setGuard(s, new OPT_TrueGuardOperand());
Call.setMethod(s, methOp);
Call.setAddress(s, new OPT_AddressConstantOperand(storeMethod.getOffset()));
- s.position = gc.inlineSequence;
- s.bcIndex = bcIndex;
- helper.appendInstruction(s);
+
+ if (DBT_Options.inlineCallbasedMemory) {
+ translator.appendInlinedCall(s);
+ }
+ else
+ {
+ s.position = gc.inlineSequence;
+ s.bcIndex = bcIndex;
+ translator.appendInstruction(s);
+ }
}
/**
Modified: src/org/binarytranslator/generic/memory/IntAddressedMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/generic/memory/IntAddressedMemory.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -14,6 +14,7 @@
import org.binarytranslator.DBT_Options;
import org.binarytranslator.generic.fault.SegmentationFault;
import org.jikesrvm.VM_Configuration;
+import org.vmmagic.pragma.Inline;
/**
* IntAddressedMemory:
@@ -85,6 +86,7 @@
/**
* Return the offset part of the address
*/
+ @Inline
protected int getOffset(int address) {
return (address & (PAGE_SIZE - 1)) >>> 2;
}
@@ -92,6 +94,7 @@
/**
* Return the page table entry part of the address
*/
+ @Inline
private static final int getPTE(int address) {
return address >>> OFFSET_BITS;
}
@@ -311,9 +314,10 @@
MemoryMapException.unalignedAddress(addr);
}
// Check file offset is page aligned
- if ((offset % PAGE_SIZE) != 0) {
+ /*if ((offset % PAGE_SIZE) != 0) {
MemoryMapException.unalignedFileOffset(offset);
- }
+ }*/
+
if (DBT_Options.debugRuntime) {
System.out.println("Mapping file " + file + " offset=" + offset
+ " addr=0x" + Integer.toHexString(addr) + " len=" + len
Modified: src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java
===================================================================
--- src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/generic/memory/IntAddressedPreSwappedMemory.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -420,29 +420,29 @@
// Extract the memory page number from addr.
OPT_RegisterOperand vpnRegOp = new OPT_RegisterOperand(vpnReg,
VM_TypeReference.Int);
- helper.appendInstruction(Binary.create(INT_USHR, vpnRegOp,
+ translator.appendInstruction(Binary.create(INT_USHR, vpnRegOp,
addr, new OPT_IntConstantOperand(OFFSET_BITS)));
// Extract the location of the address within the page.
OPT_RegisterOperand offsetRegOp = new OPT_RegisterOperand(offsetReg,
VM_TypeReference.Int);
- helper.appendInstruction(Binary.create(INT_AND, offsetRegOp,
+ translator.appendInstruction(Binary.create(INT_AND, offsetRegOp,
addr.copyRO(), new OPT_IntConstantOperand(PAGE_SIZE - 1)));
- helper.appendInstruction(Binary.create(INT_USHR, offsetRegOp
+ translator.appendInstruction(Binary.create(INT_USHR, offsetRegOp
.copyRO(), offsetRegOp.copyRO(), new OPT_IntConstantOperand(2)));
// Retrieve the int[] for the correct page into pageReg.
OPT_RegisterOperand pageRegOp = new OPT_RegisterOperand(pageReg,
VM_TypeReference.IntArray);
- helper.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp,
+ translator.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp,
new OPT_RegisterOperand(readableMemoryReg,
VM_TypeReference.ObjectReferenceArray), vpnRegOp.copyRO(),
new OPT_LocationOperand(VM_TypeReference.IntArray),
new OPT_TrueGuardOperand()));
// Copy to reg from the correct array element.
- helper.appendInstruction(ALoad.create(INT_ALOAD, dest,
+ translator.appendInstruction(ALoad.create(INT_ALOAD, dest,
pageRegOp.copyRO(), offsetRegOp.copyRO(), new OPT_LocationOperand(
VM_TypeReference.Int), new OPT_TrueGuardOperand()));
}
@@ -461,15 +461,15 @@
// Load as 32-bit then mask out what we need
translateAlignedLoad32(addr, dest);
// addr = (addr & 0x3) * 8
- helper.appendInstruction(Binary.create(INT_AND,
+ translator.appendInstruction(Binary.create(INT_AND,
addr.copyRO(), addr.copyRO(), new OPT_IntConstantOperand(3)));
- helper.appendInstruction(Binary.create(INT_SHL,
+ translator.appendInstruction(Binary.create(INT_SHL,
addr.copyRO(), addr.copyRO(), new OPT_IntConstantOperand(3)));
// rD <<= addr
- helper.appendInstruction(Binary.create(INT_SHL,
+ translator.appendInstruction(Binary.create(INT_SHL,
dest.copyRO(), dest.copyRO(), addr.copyRO()));
// rD >>>= 24
- helper.appendInstruction(Binary.create(INT_USHR, dest
+ translator.appendInstruction(Binary.create(INT_USHR, dest
.copyRO(), dest.copyRO(), new OPT_IntConstantOperand(24)));
}
@@ -487,17 +487,17 @@
// Load as 32-bit then mask out what we need
translateAlignedLoad32(addr, dest);
// addr = (3 - (addr & 0x3)) * 8
- helper.appendInstruction(Binary.create(INT_AND,
+ translator.appendInstruction(Binary.create(INT_AND,
addr.copyRO(), addr.copyRO(), new OPT_IntConstantOperand(3)));
- helper.appendInstruction(Binary.create(INT_SUB,
+ translator.appendInstruction(Binary.create(INT_SUB,
addr.copyRO(), new OPT_IntConstantOperand(3), addr.copyRO()));
- helper.appendInstruction(Binary.create(INT_SHL,
+ translator.appendInstruction(Binary.create(INT_SHL,
addr.copyRO(), addr.copyRO(), new OPT_IntConstantOperand(3)));
// rD >>>= addr
- helper.appendInstruction(Binary.create(INT_USHR, dest
+ translator.appendInstruction(Binary.create(INT_USHR, dest
.copyRO(), dest.copyRO(), addr.copyRO()));
// rD &= 0xff
- helper.appendInstruction(Binary.create(INT_AND,
+ translator.appendInstruction(Binary.create(INT_AND,
dest.copyRO(), dest.copyRO(), new OPT_IntConstantOperand(0xff)));
}
@@ -514,43 +514,43 @@
OPT_RegisterOperand dest) {
// The block after this load - NB could still need to plant an update for
// this instruction in here
- OPT_BasicBlock nextBlock = helper.createBlockAfterCurrent();
+ OPT_BasicBlock nextBlock = translator.createBlockAfterCurrent();
// Put call based version for (addr & 3 == 3) in aligned3
- OPT_BasicBlock aligned3 = helper.createBlockAfterCurrent();
+ OPT_BasicBlock aligned3 = translator.createBlockAfterCurrent();
// Put all other cases in aligned
- OPT_BasicBlock aligned = helper.createBlockAfterCurrent();
+ OPT_BasicBlock aligned = translator.createBlockAfterCurrent();
// Compute tempReg = addr & 3
OPT_RegisterOperand tempRegOp = new OPT_RegisterOperand(tempReg,
VM_TypeReference.Int);
- helper.appendInstruction(Binary.create(INT_AND, tempRegOp,
+ translator.appendInstruction(Binary.create(INT_AND, tempRegOp,
addr.copyRO(), new OPT_IntConstantOperand(0x3)));
// Create if (addr & 3) == 3 goto aligned3
- helper.appendInstruction(IfCmp.create(INT_IFCMP, null,
+ translator.appendInstruction(IfCmp.create(INT_IFCMP, null,
tempRegOp.copyRO(), new OPT_IntConstantOperand(0x3),
- OPT_ConditionOperand.EQUAL(), aligned3.makeJumpTarget(), helper
+ OPT_ConditionOperand.EQUAL(), aligned3.makeJumpTarget(), translator
.getConditionalBranchProfileOperand(false)));
- helper.getCurrentBlock().insertOut(aligned3);
+ translator.getCurrentBlock().insertOut(aligned3);
// Create aligned code
- helper.setCurrentBlock(aligned);
+ translator.setCurrentBlock(aligned);
translateAlignedLoad32(addr, dest);
// tempReg = (addr & 0x3) * 8
- helper.appendInstruction(Binary.create(INT_SHL, tempRegOp
+ translator.appendInstruction(Binary.create(INT_SHL, tempRegOp
.copyRO(), tempRegOp.copyRO(), new OPT_IntConstantOperand(3)));
// rD <<= tempReg
- helper.appendInstruction(Binary.create(INT_SHL,
+ translator.appendInstruction(Binary.create(INT_SHL,
dest.copyRO(), dest.copyRO(), tempRegOp.copyRO()));
// rD >>= 16
- helper.appendInstruction(Binary.create(INT_SHR,
+ translator.appendInstruction(Binary.create(INT_SHR,
dest.copyRO(), dest.copyRO(), new OPT_IntConstantOperand(16)));
- helper.appendInstruction(Goto.create(GOTO, nextBlock
+ translator.appendInstruction(Goto.create(GOTO, nextBlock
.makeJumpTarget()));
aligned.deleteNormalOut();
aligned.insertOut(nextBlock);
// Create aligned3 code
- helper.setCurrentBlock(aligned3);
+ translator.setCurrentBlock(aligned3);
translateCallBasedLoadSigned16(addr.copyRO(), dest.copyRO());
// Move to empty block for rest of load instruction
- helper.setCurrentBlock(nextBlock);
+ translator.setCurrentBlock(nextBlock);
}
/**
@@ -566,45 +566,45 @@
OPT_RegisterOperand dest) {
// The block after this load - NB could still need to plant an update for
// this instruction in here
- OPT_BasicBlock nextBlock = helper.createBlockAfterCurrent();
+ OPT_BasicBlock nextBlock = translator.createBlockAfterCurrent();
// Put call based version for (addr & 3 == 3) in aligned3
- OPT_BasicBlock aligned3 = helper.createBlockAfterCurrent();
+ OPT_BasicBlock aligned3 = translator.createBlockAfterCurrent();
// Put all other cases in aligned
- OPT_BasicBlock aligned = helper.createBlockAfterCurrent();
+ OPT_BasicBlock aligned = translator.createBlockAfterCurrent();
// Compute tempReg = addr & 3
OPT_RegisterOperand tempRegOp = new OPT_RegisterOperand(tempReg,
VM_TypeReference.Int);
- helper.appendInstruction(Binary.create(INT_AND, tempRegOp,
+ translator.appendInstruction(Binary.create(INT_AND, tempRegOp,
addr.copyRO(), new OPT_IntConstantOperand(0x3)));
// Create if (addr & 3) == 3 goto aligned3
- helper.appendInstruction(IfCmp.create(INT_IFCMP, null,
+ translator.appendInstruction(IfCmp.create(INT_IFCMP, null,
tempRegOp.copyRO(), new OPT_IntConstantOperand(0x3),
- OPT_ConditionOperand.EQUAL(), aligned3.makeJumpTarget(), helper
+ OPT_ConditionOperand.EQUAL(), aligned3.makeJumpTarget(), translator
.getConditionalBranchProfileOperand(false)));
- helper.getCurrentBlock().insertOut(aligned3);
+ translator.getCurrentBlock().insertOut(aligned3);
// Create aligned code
- helper.setCurrentBlock(aligned);
+ translator.setCurrentBlock(aligned);
translateAlignedLoad32(addr, dest);
// tempReg = (2 - (addr & 0x3)) * 8
- helper.appendInstruction(Binary.create(INT_SUB, tempRegOp
+ translator.appendInstruction(Binary.create(INT_SUB, tempRegOp
.copyRO(), new OPT_IntConstantOperand(2), tempRegOp.copyRO()));
- helper.appendInstruction(Binary.create(INT_SHL, tempRegOp
+ translator.appendInstruction(Binary.create(INT_SHL, tempRegOp
.copyRO(), tempRegOp.copyRO(), new OPT_IntConstantOperand(3)));
// rD >>>= tempReg
- helper.appendInstruction(Binary.create(INT_USHR, dest
+ translator.appendInstruction(Binary.create(INT_USHR, dest
.copyRO(), dest.copyRO(), tempRegOp.copyRO()));
// rD &= 0xffff
- helper.appendInstruction(Binary.create(INT_AND,
+ translator.appendInstruction(Binary.create(INT_AND,
dest.copyRO(), dest.copyRO(), new OPT_IntConstantOperand(0xffff)));
- helper.appendInstruction(Goto.create(GOTO, nextBlock
+ translator.appendInstruction(Goto.create(GOTO, nextBlock
.makeJumpTarget()));
aligned.deleteNormalOut();
aligned.insertOut(nextBlock);
// Create aligned3 code
- helper.setCurrentBlock(aligned3);
+ translator.setCurrentBlock(aligned3);
translateCallBasedLoadUnsigned16(addr.copyRO(), dest.copyRO());
// Move to empty block for rest of load instruction
- helper.setCurrentBlock(nextBlock);
+ translator.setCurrentBlock(nextBlock);
}
/**
@@ -618,34 +618,34 @@
public void translateLoad32(OPT_RegisterOperand addr, OPT_RegisterOperand dest) {
// The block after this load - NB could still need to plant an update for
// this instruction in here
- OPT_BasicBlock nextBlock = helper.createBlockAfterCurrent();
+ OPT_BasicBlock nextBlock = translator.createBlockAfterCurrent();
// Put call based version for (addr & 3 != 0) in aligned123
- OPT_BasicBlock aligned123 = helper.createBlockAfterCurrent();
+ OPT_BasicBlock aligned123 = translator.createBlockAfterCurrent();
// Put case (addr & 3 == 0) in aligned
- OPT_BasicBlock aligned = helper.createBlockAfterCurrent();
+ OPT_BasicBlock aligned = translator.createBlockAfterCurrent();
// Compute tempReg = addr & 3
OPT_RegisterOperand tempRegOp = new OPT_RegisterOperand(tempReg,
VM_TypeReference.Int);
- helper.appendInstruction(Binary.create(INT_AND, tempRegOp,
+ translator.appendInstruction(Binary.create(INT_AND, tempRegOp,
addr.copyRO(), new OPT_IntConstantOperand(0x3)));
// Create if (addr & 3) == 3 goto aligned3
- helper.appendInstruction(IfCmp.create(INT_IFCMP, null,
+ translator.appendInstruction(IfCmp.create(INT_IFCMP, null,
tempRegOp.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand
- .NOT_EQUAL(), aligned123.makeJumpTarget(), helper
+ .NOT_EQUAL(), aligned123.makeJumpTarget(), translator
.getConditionalBranchProfileOperand(false)));
- helper.getCurrentBlock().insertOut(aligned123);
+ translator.getCurrentBlock().insertOut(aligned123);
// Create aligned code
- helper.setCurrentBlock(aligned);
+ translator.setCurrentBlock(aligned);
translateAlignedLoad32(addr, dest);
- helper.appendInstruction(Goto.create(GOTO, nextBlock
+ translator.appendInstruction(Goto.create(GOTO, nextBlock
.makeJumpTarget()));
aligned.deleteNormalOut();
aligned.insertOut(nextBlock);
// Create aligned3 code
- helper.setCurrentBlock(aligned123);
+ translator.setCurrentBlock(aligned123);
translateCallBasedLoad32(addr.copyRO(), dest.copyRO());
// Move to empty block for rest of load instruction
- helper.setCurrentBlock(nextBlock);
+ translator.setCurrentBlock(nextBlock);
}
/**
@@ -662,29 +662,29 @@
// Extract the memory page number from addr.
OPT_RegisterOperand vpnRegOp = new OPT_RegisterOperand(vpnReg,
VM_TypeReference.Int);
- helper.appendInstruction(Binary.create(INT_USHR, vpnRegOp,
+ translator.appendInstruction(Binary.create(INT_USHR, vpnRegOp,
addr, new OPT_IntConstantOperand(OFFSET_BITS)));
// Extract the location of the address within the page.
OPT_RegisterOperand offsetRegOp = new OPT_RegisterOperand(offsetReg,
VM_TypeReference.Int);
- helper.appendInstruction(Binary.create(INT_AND, offsetRegOp,
+ translator.appendInstruction(Binary.create(INT_AND, offsetRegOp,
addr.copyRO(), new OPT_IntConstantOperand(PAGE_SIZE - 1)));
- helper.appendInstruction(Binary.create(INT_USHR, offsetRegOp
+ translator.appendInstruction(Binary.create(INT_USHR, offsetRegOp
.copyRO(), offsetRegOp.copyRO(), new OPT_IntConstantOperand(2)));
// Retrieve the int[] for the correct page into pageReg.
OPT_RegisterOperand pageRegOp = new OPT_RegisterOperand(pageReg,
VM_TypeReference.IntArray);
- helper.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp,
+ translator.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp,
new OPT_RegisterOperand(writableMemoryReg,
VM_TypeReference.ObjectReferenceArray), vpnRegOp.copyRO(),
new OPT_LocationOperand(VM_TypeReference.IntArray),
new OPT_TrueGuardOperand()));
// Copy to reg from the correct array element.
- helper.appendInstruction(ALoad.create(INT_ALOAD, dest,
+ translator.appendInstruction(ALoad.create(INT_ALOAD, dest,
pageRegOp.copyRO(), offsetRegOp.copyRO(), new OPT_LocationOperand(
VM_TypeReference.Int), new OPT_TrueGuardOperand()));
}
@@ -703,29 +703,29 @@
// Extract the memory page number from addr.
OPT_RegisterOperand vpnRegOp = new OPT_RegisterOperand(vpnReg,
VM_TypeReference.Int);
- helper.appendInstruction(Binary.create(INT_USHR, vpnRegOp,
+ translator.appendInstruction(Binary.create(INT_USHR, vpnRegOp,
addr, new OPT_IntConstantOperand(OFFSET_BITS)));
// Extract the location of the address within the page.
OPT_RegisterOperand offsetRegOp = new OPT_RegisterOperand(offsetReg,
VM_TypeReference.Int);
- helper.appendInstruction(Binary.create(INT_AND, offsetRegOp,
+ translator.appendInstruction(Binary.create(INT_AND, offsetRegOp,
addr.copyRO(), new OPT_IntConstantOperand(PAGE_SIZE - 1)));
- helper.appendInstruction(Binary.create(INT_USHR, offsetRegOp
+ translator.appendInstruction(Binary.create(INT_USHR, offsetRegOp
.copyRO(), offsetRegOp.copyRO(), new OPT_IntConstantOperand(2)));
// Retrieve the int[] for the correct page into pageReg.
OPT_RegisterOperand pageRegOp = new OPT_RegisterOperand(pageReg,
VM_TypeReference.IntArray);
- helper.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp,
+ translator.appendInstruction(ALoad.create(REF_ALOAD, pageRegOp,
new OPT_RegisterOperand(writableMemoryReg,
VM_TypeReference.ObjectReferenceArray), vpnRegOp.copyRO(),
new OPT_LocationOperand(VM_TypeReference.IntArray),
new OPT_TrueGuardOperand()));
// Copy to reg from the correct array element.
- helper.appendInstruction(ALoad.create(INT_ASTORE, src,
+ translator.appendInstruction(ALoad.create(INT_ASTORE, src,
pageRegOp.copyRO(), offsetRegOp.copyRO(), new OPT_LocationOperand(
VM_TypeReference.Int), new OPT_TrueGuardOperand()));
}
Modified: src/org/binarytranslator/generic/os/loader/elf/ELF_File.java
===================================================================
--- src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/generic/os/loader/elf/ELF_File.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -215,7 +215,7 @@
public static boolean conforms(String filename) {
RandomAccessFile rFile = null;
- report("Testing is file is ELF: " + filename);
+ report("Testing if file is ELF: " + filename);
try {
rFile = new RandomAccessFile(filename, "r");
Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java
===================================================================
--- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -70,8 +70,7 @@
* @param trace
* @return a HIR generator
*/
- public abstract CodeTranslator createTranslator(
- OPT_GenerationContext context, DBT_Trace trace) throws UnsupportedOperationException ;
+ public abstract CodeTranslator createTranslator(OPT_GenerationContext context, DBT_Trace trace) throws UnsupportedOperationException ;
/**
* Returns an instance of {@link Interpreter} that can be used to interpret instructions
Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java
===================================================================
--- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-08-11 11:28:50 UTC (rev 163)
+++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-08-14 15:32:09 UTC (rev 164)
@@ -117,7 +117,7 @@
* This list stores at which bytecode index a specific method call is executed.
* The index of an element plus {@link #CUSTOM_CALL_BCINDEX_BASE} equals the bytecode index
* for the call.*/
- private List<CustomCallInformation> customCalls = new ArrayList<CustomCallInformation>();
+ private final List<CustomCallInformation> customCalls = new ArrayList<CustomCallInformation>();
/**
* Create an optimizing compiler HIR code generator for this trace
@@ -126,7 +126,9 @@
* the generation context for the HIR generation
* @return a HIR generator
*/
+ @Override
public OPT_HIRGenerator createHIRGenerator(OPT_GenerationContext context) {
+
return ps.createTranslator(context, this);
}
@@ -322,7 +324,7 @@
* Size of bytecodes for this method
*/
public int getBytecodeLength() {
- return 256;
+ return numberOfInstructions == 0 ? 256 : numberOfInstructions;
}
public int getNumberOfInstructions() {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-11 11:29:13
|
Revision: 163
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=163&view=rev
Author: michael_baer
Date: 2007-08-11 04:28:50 -0700 (Sat, 11 Aug 2007)
Log Message:
-----------
- Fixed bugs with Lazy Evaluation
- Added option to determine ARM inlining behaviour
Modified Paths:
--------------
src/org/binarytranslator/DBT.java
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_Instructions.java
src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java
src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
src/org/binarytranslator/generic/decoder/CodeTranslator.java
Modified: src/org/binarytranslator/DBT.java
===================================================================
--- src/org/binarytranslator/DBT.java 2007-08-08 10:22:45 UTC (rev 162)
+++ src/org/binarytranslator/DBT.java 2007-08-11 11:28:50 UTC (rev 163)
@@ -17,7 +17,7 @@
*/
public final class DBT {
/** Should the following assertion be checked? */
- public static final boolean VerifyAssertions = true;
+ public static final boolean VerifyAssertions = VM.VerifyAssertions;
/**
* Assert the following condition is true, if false then fail with stack trace
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-08 10:22:45 UTC (rev 162)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-11 11:28:50 UTC (rev 163)
@@ -25,7 +25,7 @@
public final static boolean buildForSunVM = false;
/** Enable the profiling of application during interpretation? */
- public final static boolean profileDuringInterpretation = true;
+ public final static boolean profileDuringInterpretation = false;
/** Debug binary loading */
public final static boolean debugLoader = true;
@@ -182,8 +182,10 @@
private static void parseArmOption(String key, String value) {
if (key.equalsIgnoreCase("optimizeByProfiling")) {
ARM_Options.optimizeTranslationByProfiling = Boolean.parseBoolean(value);
- } else if (key.equalsIgnoreCase("flagBehaviour")) {
- ARM_Options.flagBehaviour = ARM_Options.FlagBehaviour.valueOf(value);
+ } else if (key.equalsIgnoreCase("flagEvaluation")) {
+ ARM_Options.flagEvaluation = ARM_Options.FlagBehaviour.valueOf(value);
+ } else if (key.equalsIgnoreCase("inlining")) {
+ ARM_Options.inlining = ARM_Options.InliningBehaviour.valueOf(value);
}
else {
throw new Error("Unknown ARM option: " + key);
Modified: src/org/binarytranslator/Main.java
===================================================================
--- src/org/binarytranslator/Main.java 2007-08-08 10:22:45 UTC (rev 162)
+++ src/org/binarytranslator/Main.java 2007-08-11 11:28:50 UTC (rev 163)
@@ -105,7 +105,7 @@
//on SUN's VM, only the interpreter has been tested
if (DBT_Options.buildForSunVM) {
- DBT_Options.executionController = ExecutionController.Type.StagedEmulation;
+ DBT_Options.executionController = ExecutionController.Type.Interpreter;
}
//load a previously saved branch profile from file, if the user requested it
Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-08 10:22:45 UTC (rev 162)
+++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-11 11:28:50 UTC (rev 163)
@@ -9,6 +9,7 @@
import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace;
import org.binarytranslator.arch.arm.os.process.ARM_Registers;
import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode;
+import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType;
import org.binarytranslator.generic.decoder.CodeTranslator;
import org.binarytranslator.generic.decoder.Laziness;
import org.binarytranslator.vmInterface.DBT_Trace;
@@ -143,17 +144,17 @@
super(context, trace);
translator = new ARM_Translator((ARM_ProcessSpace)ps, this);
- switch (ARM_Options.flagBehaviour) {
- case ImmediateEvaluation:
+ switch (ARM_Options.flagEvaluation) {
+ case Immediate:
flagBehavior = new ARM_ImmediateFlagBehavior();
break;
- case LazyEvaluation:
+ case Lazy:
flagBehavior = new ARM_LazyFlagBehavior();
break;
default:
- throw new RuntimeException("Unexpected flag behaviour: " + ARM_Options.flagBehaviour);
+ throw new RuntimeException("Unexpected flag behaviour: " + ARM_Options.flagEvaluation);
}
}
@@ -409,7 +410,6 @@
@Override
public void onFlagRead(Flag flag, ARM_Laziness lazy) {
resolveFlag(flag, lazy);
-
}
@Override
@@ -463,6 +463,32 @@
return result;
}
+ @Override
+ protected boolean inlineBranchInstruction(int targetPc, UnresolvedJumpInstruction jump) {
+
+ switch (ARM_Options.inlining)
+ {
+ case Default:
+ return super.inlineBranchInstruction(targetPc, jump);
+
+ case DynamicJumps:
+ if (jump.type == BranchType.INDIRECT_BRANCH)
+ return true;
+ else
+ return super.inlineBranchInstruction(targetPc, jump);
+
+ case Functions:
+ if (jump.type == BranchType.CALL || jump.type == BranchType.RETURN)
+ return true;
+ else
+ return super.inlineBranchInstruction(targetPc, jump);
+
+ default:
+ throw new RuntimeException("Unexpected inlining type.");
+ }
+
+ }
+
/**
* Returns a RegisterOperand that contains a reference to the currently used ARM_Registers instance.
* Use this reference when calling functions on ARM_Registers.
@@ -648,18 +674,20 @@
}
public void appendLogicalFlags(ARM_Laziness lazy, OPT_Operand result) {
+ zeroUsed = negativeUsed = true;
flagBehavior.appendLogicalFlags(lazy, result);
}
public void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+ zeroUsed = negativeUsed = carryUsed = overflowUsed = true;
flagBehavior.appendSubFlags(lazy, result, op1, op2);
}
public void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+ zeroUsed = negativeUsed = carryUsed = overflowUsed = true;
flagBehavior.appendAddFlags(lazy, result, op1, op2);
}
-
-
+
@Override
protected OPT_Register[] getUnusedRegisters() {
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-08-08 10:22:45 UTC (rev 162)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Instructions.java 2007-08-11 11:28:50 UTC (rev 163)
@@ -1026,7 +1026,7 @@
public LongMultiply(int instr) {
super(instr);
- unsigned = Utils.getBit(instr, 22);
+ unsigned = !Utils.getBit(instr, 22);
updateConditionCodes = Utils.getBit(instr, 20);
accumulate = Utils.getBit(instr, 21);
RdHigh = (byte) Utils.getBits(instr, 16, 19);
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-08-08 10:22:45 UTC (rev 162)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-08-11 11:28:50 UTC (rev 163)
@@ -1375,8 +1375,8 @@
//get rid of the signs, if we're supposed to do unsigned multiplication
if (i.unsigned) {
- operand1 &= 0xFFFFFFFF;
- operand2 &= 0xFFFFFFFF;
+ operand1 &= (long)0xFFFFFFFFL;
+ operand2 &= (long)0xFFFFFFFFL;
}
// calculate the result
@@ -1385,7 +1385,7 @@
if (i.accumulate) {
//treat the register as an unsigned value
long operand = regs.get(i.getRdLow());
- operand &= 0xFFFFFFFF;
+ operand &= 0xFFFFFFFFL;
result += operand;
result += regs.get(i.getRdHigh()) << 32;
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-08 10:22:45 UTC (rev 162)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-11 11:28:50 UTC (rev 163)
@@ -3,10 +3,16 @@
public class ARM_Options {
public enum FlagBehaviour {
- LazyEvaluation,
- ImmediateEvaluation
+ Lazy,
+ Immediate
}
+ public enum InliningBehaviour {
+ Default,
+ Functions,
+ DynamicJumps
+ }
+
/** Set to true to enable a fastpath for the decoding of data processing instructions.. */
public final static boolean DATAPROCESSING_DECODER_FASTPATH = false;
@@ -14,5 +20,7 @@
public static boolean optimizeTranslationByProfiling = false;
/** This variable describes, if the translated program shall be optimized using lazy evaluation.*/
- public static FlagBehaviour flagBehaviour = FlagBehaviour.LazyEvaluation;
+ public static FlagBehaviour flagEvaluation = FlagBehaviour.Lazy;
+
+ public static InliningBehaviour inlining = InliningBehaviour.Default;
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-08 10:22:45 UTC (rev 162)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-11 11:28:50 UTC (rev 163)
@@ -92,6 +92,9 @@
else
instr = ARM_InstructionDecoder.ARM32.decode(instruction, translatorFactory);
+ if (DBT_Options.debugTranslation)
+ System.out.println("Translating instruction: " + ARM_Disassembler.disassemble(pc, ps).asString() + " at 0x" + Integer.toHexString(pc));
+
if (instr.getCondition() != Condition.AL) {
instr = new ConditionalDecorator(instr);
}
@@ -1327,24 +1330,27 @@
public void translate() {
OPT_Operand operand1 = resolveOperand1();
- OPT_Operand operand2 = resolveOperand2();
+ OPT_Operand originalOperand2 = resolveOperand2();
OPT_RegisterOperand result = getResultRegister();
OPT_BasicBlock addWithoutCarry = arm2ir.createBlockAfterCurrent();
OPT_BasicBlock addWithCarry = arm2ir.createBlockAfterCurrentNotInCFG();
+
+ OPT_RegisterOperand operand2 = arm2ir.getTempInt(0);
+ arm2ir.appendInstruction(Move.create(INT_MOVE, operand2, originalOperand2));
//Is the carry set at all? if not, just jump to addWithoutCarry
- arm2ir.appendInstruction(Binary.create(INT_ADD, result, operand1, operand2));
arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.readCarryFlag(lazy), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand()));
arm2ir.getCurrentBlock().insertOut(addWithCarry);
//Yes, the carry flag is set. Pre-increase the result by one to account for the carry.
arm2ir.setCurrentBlock(addWithCarry);
- arm2ir.appendInstruction(Binary.create(INT_ADD, result.copyRO(), result.copy(), new OPT_IntConstantOperand(1)));
+ arm2ir.appendInstruction(Binary.create(INT_ADD, operand2.copyRO(), operand2.copy(), new OPT_IntConstantOperand(1)));
addWithCarry.insertOut(addWithoutCarry);
//Finally, add the second operands to the result
arm2ir.setCurrentBlock(addWithoutCarry);
+ arm2ir.appendInstruction(Binary.create(INT_ADD, result, operand1, operand2.copy()));
setAddResult(result, operand1, operand2);
}
}
@@ -1358,24 +1364,27 @@
public void translate() {
OPT_Operand operand1 = resolveOperand1();
- OPT_Operand operand2 = resolveOperand2();
+ OPT_Operand originalOperand2 = resolveOperand2();
OPT_RegisterOperand result = getResultRegister();
OPT_BasicBlock subWithoutCarry = arm2ir.createBlockAfterCurrent();
OPT_BasicBlock subWithCarry = arm2ir.createBlockAfterCurrentNotInCFG();
+
+ OPT_RegisterOperand operand2 = arm2ir.getTempInt(0);
+ arm2ir.appendInstruction(Move.create(INT_MOVE, operand2, originalOperand2));
//Is the carry set? if yes, just jump to subWithoutCarry
- arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2));
arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.readCarryFlag(lazy), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), subWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand()));
arm2ir.getCurrentBlock().insertOut(subWithCarry);
//No, the carry flag is not set. That means, we have to use the carry within the subtraction (weird arm logic).
arm2ir.setCurrentBlock(subWithCarry);
- arm2ir.appendInstruction(Binary.create(INT_SUB, result.copyRO(), result.copy(), new OPT_IntConstantOperand(1)));
+ arm2ir.appendInstruction(Binary.create(INT_ADD, operand2.copyRO(), operand2.copy(), new OPT_IntConstantOperand(1)));
subWithCarry.insertOut(subWithoutCarry);
//Finally, subtract the second operands from the result
arm2ir.setCurrentBlock(subWithoutCarry);
+ arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2.copy()));
setSubResult(result, operand1, operand2);
}
}
@@ -1846,7 +1855,7 @@
}
public int getSuccessor(int pc) {
- if (i.offset.getType() == OperandWrapper.Type.Immediate)
+ if (i.offset.getType() == OperandWrapper.Type.Immediate && !i.link)
return readPC() + i.getOffset().getImmediate();
else
return -1;
@@ -1993,8 +2002,8 @@
if (i.unsigned) {
//treat the original ints as unsigned, so get rid of the signs for the longs
- arm2ir.appendInstruction(Binary.create(LONG_AND, operand1.copyRO(), operand1.copy(), new OPT_LongConstantOperand(0xFFFFFFFF)));
- arm2ir.appendInstruction(Binary.create(LONG_AND, operand2.copyRO(), operand2.copy(), new OPT_LongConstantOperand(0xFFFFFFFF)));
+ arm2ir.appendInstruction(Binary.create(LONG_AND, operand1.copyRO(), operand1.copy(), new OPT_LongConstantOperand(0xFFFFFFFFL)));
+ arm2ir.appendInstruction(Binary.create(LONG_AND, operand2.copyRO(), operand2.copy(), new OPT_LongConstantOperand(0xFFFFFFFFL)));
}
//multiply the two operands
@@ -2005,7 +2014,7 @@
OPT_Operand operand3 = arm2ir.getRegister(i.getRdLow());
OPT_RegisterOperand tmp = arm2ir.getTempLong(0);
arm2ir.appendInstruction(Unary.create(INT_2LONG, tmp, operand3));
- arm2ir.appendInstruction(Binary.create(LONG_AND, tmp.copyRO(), tmp.copy(), new OPT_LongConstantOperand(0xFFFFFFFF)));
+ arm2ir.appendInstruction(Binary.create(LONG_AND, tmp.copyRO(), tmp.copy(), new OPT_LongConstantOperand(0xFFFFFFFFL)));
arm2ir.appendInstruction(Binary.create(LONG_ADD, result.copyRO(), result.copy(), tmp.copy()));
operand3 = arm2ir.getRegister(i.getRdHigh());
@@ -2013,6 +2022,10 @@
arm2ir.appendInstruction(Binary.create(LONG_SHL, tmp.copyRO(), tmp.copy(), new OPT_IntConstantOperand(32)));
arm2ir.appendInstruction(Binary.create(INT_ADD, result.copyRO(), result.copy(), operand3.copy()));
}
+
+ arm2ir.appendInstruction(Unary.create(LONG_2INT, arm2ir.getRegister(i.getRdLow()) ,result.copy()));
+ arm2ir.appendInstruction(Binary.create(LONG_SHR, result.copyRO(), result.copy(), new OPT_IntConstantOperand(32)));
+ arm2ir.appendInstruction(Unary.create(LONG_2INT, arm2ir.getRegister(i.getRdHigh()) ,result.copy()));
if (i.updateConditionCodes) {
//set the negative flag
@@ -2054,10 +2067,10 @@
//do we have to transfer the saved or the current PSR?
if (i.transferSavedPSR) {
- call = createCallToRegisters("getSPSR", "()V", 0);
+ call = createCallToRegisters("getSPSR", "()I", 0);
}
else {
- call = createCallToRegisters("getCPSR", "()V", 0);
+ call = createCallToRegisters("getCPSR", "()I", 0);
}
Call.setResult(call, psrValue);
Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java
===================================================================
--- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-08 10:22:45 UTC (rev 162)
+++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-11 11:28:50 UTC (rev 163)
@@ -165,7 +165,7 @@
/** This class stores information about a jump instruction within the current trace, whose
* target has not yet been resolved. */
- private final static class UnresolvedJumpInstruction {
+ protected final static class UnresolvedJumpInstruction {
/** A reference to the jump instruction within the code. This is either a GOTO or SWITCH instruction. */
public final OPT_Instruction instruction;
@@ -306,6 +306,10 @@
// Move currentBlock along
currentBlock = nextBlock;
} else {
+
+ if (DBT_Options.debugTranslation)
+ System.out.println("Translating subtrace for 0x" + Integer.toHexString(pc));
+
do {
if (DBT.VerifyAssertions)
DBT._assert(currentBlock.getNumberOfRealInstructions() == 0);
@@ -351,6 +355,9 @@
break;
}
} while (pc != -1);
+
+ if (DBT_Options.debugTranslation)
+ System.out.println("Done translating subtrace.");
}
}
@@ -608,7 +615,7 @@
// serves more as a placeholder and might be mutated later on.
appendInstruction(branch);
UnresolvedJumpInstruction unresolvedJump = new UnresolvedJumpInstruction(
- branch, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL);
+ branch, (Laziness) targetLaziness.clone(), currentPC, targetPC, branchType);
unresolvedDirectBranches.add(unresolvedJump);
switch (branchType) {
@@ -753,9 +760,17 @@
DBT_Trace compiledTrace = ps.codeCache.tryGet(targetPc);
- return DBT_Options.singleInstrTranslation == false
- && (compiledTrace == null || compiledTrace.getNumberOfInstructions() > 30) && !shallTraceStop()
+ boolean decision = DBT_Options.singleInstrTranslation == false
+ && (compiledTrace == null || compiledTrace.getNumberOfInstructions() < 20) && !shallTraceStop()
&& jump.type != BranchType.CALL && jump.type != BranchType.RETURN;
+
+ if (DBT_Options.debugBranchResolution) {
+ String text = (!decision ? "Not inlining " : "Inlining ");
+ text += jump.type + " to 0x" + Integer.toHexString(targetPc);
+ System.out.println(text);
+ }
+
+ return decision;
}
/**
@@ -782,21 +797,19 @@
// precompiled target
if (targetBB != null)
return targetBB;
-
+
+ if (currentBlock.getNumberOfRealInstructions() != 0) {
+ currentBlock = createBlockAfterCurrentNotInCFG();
+ }
+
if (!inlineBranchInstruction(targetPc, jump)) {
- // Just exit the trace and continue at the target address in a new trace
- if (currentBlock.getNumberOfRealInstructions() != 0) {
- currentBlock = createBlockAfterCurrentNotInCFG();
-
- if (DBT_Options.debugBranchResolution)
- System.out.println("Resolving branch to next block.");
- }
-
+ //Just exit the trace and continue at the target address in a new trace
targetBB = currentBlock;
appendTraceExit(jump.lazyStateAtJump, new OPT_IntConstantOperand(targetPc));
registerMapping(targetPc, jump.lazyStateAtJump, targetBB);
- } else {
+ }
+ else {
// Otherwise we will translate the jump into the trace
translateSubTrace((Laziness) jump.lazyStateAtJump.clone(), targetPc);
targetBB = findMapping(targetPc, jump.lazyStateAtJump);
@@ -1299,7 +1312,9 @@
*/
public void appendInterpretedInstruction(int pc, Laziness lazy) {
- resolveLaziness(lazy);
+ appendThrowBadInstruction(lazy, pc);
+
+/* resolveLaziness(lazy);
spillAllRegisters();
// Prepare a local variable of type Interpreter
@@ -1313,7 +1328,7 @@
VM_MethodReference getInterpreterMethodRef = (VM_MethodReference) VM_MemberReference
.findOrCreate(psTref, VM_Atom
.findOrCreateAsciiAtom("createInstructionInterpreter"), VM_Atom
- .findOrCreateAsciiAtom("()A"));
+ .findOrCreateAsciiAtom("()Lorg.binarytranslator.generic.decoder.Interpreter;"));
VM_Method getInterpreterMethod = getInterpreterMethodRef
.resolveInterfaceMethod();
@@ -1345,7 +1360,7 @@
VM_MethodReference decodeMethodRef = (VM_MethodReference) VM_MemberReference
.findOrCreate(interpreterTypeRef, VM_Atom
.findOrCreateAsciiAtom("decode"), VM_Atom
- .findOrCreateAsciiAtom("(I)A"));
+ .findOrCreateAsciiAtom("(I)Lorg.binarytranslator.generic.decoder.Interpreter.Instruction;"));
VM_Method decodeMethod = decodeMethodRef.resolveInterfaceMethod();
methOp = OPT_MethodOperand.INTERFACE(decodeMethodRef, decodeMethod);
@@ -1385,7 +1400,7 @@
appendCustomCall(s);
// Fill all registers again following interpreted instruction
- fillAllRegisters();
+ fillAllRegisters();*/
}
/** Get the method */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-08 10:22:43
|
Revision: 162
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=162&view=rev
Author: michael_baer
Date: 2007-08-08 03:22:45 -0700 (Wed, 08 Aug 2007)
Log Message:
-----------
- Compress flag state into a single integer in ARM_Laziness
- Setting blocks as infrequent using profiling information
- Move some platform-specific command line options to DBT_Options
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/arch/arm/decoder/ARM_Options.java
src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
src/org/binarytranslator/generic/decoder/CodeTranslator.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-07 22:28:53 UTC (rev 161)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-08 10:22:45 UTC (rev 162)
@@ -13,6 +13,7 @@
import java.util.Map;
import java.util.Map.Entry;
+import org.binarytranslator.arch.arm.decoder.ARM_Options;
import org.binarytranslator.generic.execution.ExecutionController;
/**
@@ -93,12 +94,6 @@
/** Just a temporary variable for testing. It describes, when the staged emulation controller switches from interpretation to translation. */
public static int minTraceValue = 20;
- /** Just a temporary variable for testing. It describes, if the translated program shall be optimized using profiling information. */
- public static boolean optimizeTranslationByProfiling = false;
-
- /** Just a temporary variable for testing. It describes, if the translated program shall be optimized using lazy evaluation.*/
- public static boolean optimizeTranslationByLazyEvaluation = true;
-
/** Print debug information during the translation of instructions. */
public static boolean debugTranslation = true;
@@ -122,7 +117,7 @@
/** Stores the arguments given to the DBT by the user. These are NOT the arguments given to the executable. */
private static HashMap<String, String> dbtArguments = null;
-
+
/** Read and parse the command line arguments. */
public static void parseArguments(String[] args) {
@@ -150,7 +145,7 @@
String value = argument.getValue();
try {
- parseSingleArgument(arg, value);
+ parseSingleOption(arg, value);
}
catch (NumberFormatException e) {
throw new Error("Argument " + arg + " is not a valid integer.");
@@ -162,14 +157,40 @@
}
/** Parses a single argument into the options class. */
- private static void parseSingleArgument(String key, String value) {
+ private static void parseSingleOption(String key, String value) {
- if (!key.startsWith("-X:dbt:")) {
- throw new Error("Invalid argument. Argument prefix '-X:dbt:' expected.");
+ if (!key.startsWith("-X:")) {
+ throw new Error("Invalid argument. Argument prefix '-X:' expected.");
}
- key = key.substring(7);
+ key = key.substring(3);
+
+ if (key.startsWith("dbt:")) {
+ key = key.substring(4);
+
+ parseDbtOption(key, value);
+ }
+ else if (key.startsWith("arm:")) {
+ key = key.substring(4);
+ parseArmOption(key, value);
+ }
+ else {
+ throw new Error("Unknown argument.");
+ }
+ }
+
+ private static void parseArmOption(String key, String value) {
+ if (key.equalsIgnoreCase("optimizeByProfiling")) {
+ ARM_Options.optimizeTranslationByProfiling = Boolean.parseBoolean(value);
+ } else if (key.equalsIgnoreCase("flagBehaviour")) {
+ ARM_Options.flagBehaviour = ARM_Options.FlagBehaviour.valueOf(value);
+ }
+ else {
+ throw new Error("Unknown ARM option: " + key);
+ }
+ }
+ private static void parseDbtOption(String key, String value) {
if (key.equalsIgnoreCase("debugInstr")) {
debugInstr = Boolean.parseBoolean(value);
} else if (key.equalsIgnoreCase("debugRuntime")) {
@@ -206,12 +227,7 @@
saveProfileToFile = value;
} else if (key.equalsIgnoreCase("minTraceValue")) {
minTraceValue = Integer.parseInt(value);
- } else if (key.equalsIgnoreCase("optimizeByProfiling")) {
- optimizeTranslationByProfiling = Boolean.parseBoolean(value);
- } else if (key.equalsIgnoreCase("optimizeByLazy")) {
- optimizeTranslationByLazyEvaluation = Boolean.parseBoolean(value);
}
-
else {
throw new Error("Unknown DBT option: " + key);
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-07 22:28:53 UTC (rev 161)
+++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-08 10:22:45 UTC (rev 162)
@@ -143,10 +143,18 @@
super(context, trace);
translator = new ARM_Translator((ARM_ProcessSpace)ps, this);
- if (DBT_Options.optimizeTranslationByLazyEvaluation)
+ switch (ARM_Options.flagBehaviour) {
+ case ImmediateEvaluation:
+ flagBehavior = new ARM_ImmediateFlagBehavior();
+ break;
+
+ case LazyEvaluation:
flagBehavior = new ARM_LazyFlagBehavior();
- else
- flagBehavior = new ARM_ImmediateFlagBehavior();
+ break;
+
+ default:
+ throw new RuntimeException("Unexpected flag behaviour: " + ARM_Options.flagBehaviour);
+ }
}
/** ARM has an interchangeable flag behavior. Flags can either be evaluated immediately or on demand using
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-08-07 22:28:53 UTC (rev 161)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-08-08 10:22:45 UTC (rev 162)
@@ -13,7 +13,7 @@
}
/** The state of the different ARM flags, compressed as bit fields within an integer. */
- private int flagValid;
+ private int validFlags;
/** The operation that has to be performed to evaluate the remaining registers */
private Operation lazinessOperation;
@@ -36,7 +36,7 @@
ARM_LazinessKey(int pc, ARM_Laziness lazy) {
this.pc = pc;
- int tmpFlagState = lazy.flagValid & 0xF;
+ int tmpFlagState = lazy.validFlags & 0xF;
tmpFlagState |= (lazinessOperation.ordinal() + 1) << 4;
this.flagState = (byte)tmpFlagState;
@@ -48,7 +48,7 @@
}
public ARM_Laziness() {
- flagValid = 0xF; //all flags are valid
+ validFlags = 0xF; //all flags are valid
lazinessOperation = Operation.Add;
}
@@ -57,22 +57,15 @@
}
public void setValid(Flag flag, boolean valid) {
- flagValid |= 1 << flag.ordinal();
+ if (valid)
+ validFlags |= 1 << flag.ordinal();
+ else
+ validFlags &= ~(1 << flag.ordinal());
}
public boolean isValid(Flag flag) {
- return (flagValid & (1 << flag.ordinal())) != 0;
+ return (validFlags & (1 << flag.ordinal())) != 0;
}
-
- public void setAddOperation() {
- flagValid = 0; // all flags are invalid
- lazinessOperation = Operation.Add;
- }
-
- public void setSubOperation() {
- flagValid = 0; // all flags are invalid
- lazinessOperation = Operation.Sub;
- }
public Operation getOperation() {
return lazinessOperation;
@@ -83,7 +76,7 @@
}
public void set(ARM_Laziness other) {
- flagValid = other.flagValid;
+ validFlags = other.validFlags;
lazinessOperation = other.lazinessOperation;
}
@@ -98,7 +91,7 @@
return false;
ARM_Laziness other = (ARM_Laziness)o;
- return flagValid == other.flagValid && lazinessOperation == other.lazinessOperation;
+ return validFlags == other.validFlags && lazinessOperation == other.lazinessOperation;
}
@Override
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-07 22:28:53 UTC (rev 161)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-08-08 10:22:45 UTC (rev 162)
@@ -1,5 +1,18 @@
package org.binarytranslator.arch.arm.decoder;
public class ARM_Options {
+
+ public enum FlagBehaviour {
+ LazyEvaluation,
+ ImmediateEvaluation
+ }
+
+ /** Set to true to enable a fastpath for the decoding of data processing instructions.. */
public final static boolean DATAPROCESSING_DECODER_FASTPATH = false;
+
+ /** This variable describes, if the translated program shall be optimized using profiling information. */
+ public static boolean optimizeTranslationByProfiling = false;
+
+ /** This variable describes, if the translated program shall be optimized using lazy evaluation.*/
+ public static FlagBehaviour flagBehaviour = FlagBehaviour.LazyEvaluation;
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-07 22:28:53 UTC (rev 161)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-08 10:22:45 UTC (rev 162)
@@ -761,7 +761,7 @@
*/
private float getSkipProbability() {
- if (DBT_Options.optimizeTranslationByProfiling)
+ if (ARM_Options.optimizeTranslationByProfiling)
return -1f;
return ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4));
@@ -922,7 +922,7 @@
conditionalInstruction.translate();
int followingInstructionAddress = pc + (inThumb() ? 2 : 4);
-
+
//yes it did, so we may need to translate the successor instruction twice
if (assumeInstructionWillBeSkipped()) {
@@ -935,16 +935,27 @@
lazy.set(lazinessWhenInstructionSkipped);
}
+ condInstructionBlock.setInfrequent();
+ nextInstruction_InstructionNotSkipped.setInfrequent();
arm2ir.setNextBlock(nextInstruction_InstructionSkipped);
-
}
else {
- //Modify block 4 so that it resolves the different laziness correctly
- arm2ir.setCurrentBlock(nextInstruction_InstructionSkipped);
- nextInstruction_InstructionSkipped.deleteNormalOut();
- arm2ir.appendBranch(followingInstructionAddress, lazinessWhenInstructionSkipped);
-
- arm2ir.setNextBlock(nextInstruction_InstructionNotSkipped);
+ if (lazy.equivalent(lazinessWhenInstructionSkipped) && conditionalInstruction.getSuccessor(pc) == followingInstructionAddress) {
+ //the conditional instruction does not change the lazy state, nor does it change the program flow
+ //therefore, we block 3 and block 4 always execute the same code. We might as well continue with block 4 then.
+ arm2ir.setNextBlock(nextInstruction_InstructionSkipped);
+ }
+ else {
+ //we can assume that the instruction will rarely be skipped
+ nextInstruction_InstructionSkipped.setInfrequent();
+
+ //Modify block 4 so that it resolves the code the be executed if the instruction was skipped
+ arm2ir.setCurrentBlock(nextInstruction_InstructionSkipped);
+ nextInstruction_InstructionSkipped.deleteNormalOut();
+ arm2ir.appendBranch(followingInstructionAddress, lazinessWhenInstructionSkipped);
+
+ arm2ir.setNextBlock(nextInstruction_InstructionNotSkipped);
+ }
}
}
Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java
===================================================================
--- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-07 22:28:53 UTC (rev 161)
+++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-08 10:22:45 UTC (rev 162)
@@ -754,7 +754,7 @@
DBT_Trace compiledTrace = ps.codeCache.tryGet(targetPc);
return DBT_Options.singleInstrTranslation == false
- && (compiledTrace == null || compiledTrace.getNumberOfInstructions() > 20) && !shallTraceStop()
+ && (compiledTrace == null || compiledTrace.getNumberOfInstructions() > 30) && !shallTraceStop()
&& jump.type != BranchType.CALL && jump.type != BranchType.RETURN;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-07 22:28:52
|
Revision: 161
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=161&view=rev
Author: michael_baer
Date: 2007-08-07 15:28:53 -0700 (Tue, 07 Aug 2007)
Log Message:
-----------
- Added support for interchangeable flag behaviour and flag laziness on ARM
- Improved usage of profiling data for conditional instructions on ARM
Modified Paths:
--------------
src/org/binarytranslator/DBT_Options.java
src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java
src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java
src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
src/org/binarytranslator/generic/decoder/CodeTranslator.java
src/org/binarytranslator/vmInterface/DBT_Trace.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -93,9 +93,12 @@
/** Just a temporary variable for testing. It describes, when the staged emulation controller switches from interpretation to translation. */
public static int minTraceValue = 20;
- /** Just a temporary variable for testing. It describes, if the translated program shall be optimized using profiling information.. */
+ /** Just a temporary variable for testing. It describes, if the translated program shall be optimized using profiling information. */
public static boolean optimizeTranslationByProfiling = false;
+ /** Just a temporary variable for testing. It describes, if the translated program shall be optimized using lazy evaluation.*/
+ public static boolean optimizeTranslationByLazyEvaluation = true;
+
/** Print debug information during the translation of instructions. */
public static boolean debugTranslation = true;
@@ -179,6 +182,8 @@
debugSyscall = Boolean.parseBoolean(value);
} else if (key.equalsIgnoreCase("debugSyscallMore")) {
debugSyscallMore = Boolean.parseBoolean(value);
+ } else if (key.equalsIgnoreCase("debugTranslation")) {
+ debugTranslation = Boolean.parseBoolean(value);
} else if (key.equalsIgnoreCase("instrOpt0")) {
instrOpt0 = Integer.parseInt(value);
} else if (key.equalsIgnoreCase("instrOpt1")) {
@@ -201,9 +206,12 @@
saveProfileToFile = value;
} else if (key.equalsIgnoreCase("minTraceValue")) {
minTraceValue = Integer.parseInt(value);
- } else if (key.equalsIgnoreCase("optimizeTranslation")) {
+ } else if (key.equalsIgnoreCase("optimizeByProfiling")) {
optimizeTranslationByProfiling = Boolean.parseBoolean(value);
+ } else if (key.equalsIgnoreCase("optimizeByLazy")) {
+ optimizeTranslationByLazyEvaluation = Boolean.parseBoolean(value);
}
+
else {
throw new Error("Unknown DBT option: " + key);
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM2IR.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/arch/arm/decoder/ARM2IR.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -3,6 +3,9 @@
import java.util.ArrayList;
import org.binarytranslator.DBT;
+import org.binarytranslator.DBT_Options;
+import org.binarytranslator.arch.arm.decoder.ARM_Laziness.Flag;
+import org.binarytranslator.arch.arm.decoder.ARM_Laziness.Operation;
import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace;
import org.binarytranslator.arch.arm.os.process.ARM_Registers;
import org.binarytranslator.arch.arm.os.process.ARM_Registers.OperatingMode;
@@ -77,6 +80,9 @@
/** The class performing the actual translation of the bytecode. */
private final ARM_Translator translator;
+ /** Determines how flags are resolved and if laziness is used.*/
+ private final ARM_FlagBehavior flagBehavior;
+
static {
psTref = VM_TypeReference.findOrCreate(ARM_ProcessSpace.class);
@@ -136,8 +142,274 @@
public ARM2IR(OPT_GenerationContext context, DBT_Trace trace) {
super(context, trace);
translator = new ARM_Translator((ARM_ProcessSpace)ps, this);
+
+ if (DBT_Options.optimizeTranslationByLazyEvaluation)
+ flagBehavior = new ARM_LazyFlagBehavior();
+ else
+ flagBehavior = new ARM_ImmediateFlagBehavior();
}
+
+ /** ARM has an interchangeable flag behavior. Flags can either be evaluated immediately or on demand using
+ * lazy evaluation. This interface encapsulates the differences. */
+ public abstract class ARM_FlagBehavior {
+
+ /**
+ * Interface helper function. If a flag behaviour wants to set a value of a flag, it shall set
+ * the {@link OPT_RegisterOperand} returned by this function.
+ */
+ protected final OPT_RegisterOperand getFlag(Flag flag) {
+ switch (flag) {
+ case Zero:
+ return new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean);
+
+ case Carry:
+ return new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean);
+
+ case Negative:
+ return new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean);
+
+ case Overflow:
+ return new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean);
+
+ default:
+ throw new RuntimeException("Unexpected flag type: " + flag);
+ }
+ }
+ /** Called before a flag is written to directly. */
+ public abstract void onFlagWrite(Flag flag, ARM_Laziness lazy);
+
+ /** Called before a flag is read. */
+ public abstract void onFlagRead(Flag flag, ARM_Laziness lazy);
+
+ /** Called when the ARM flags shall be set by a logical operation. This sets the zero and negative flag. */
+ public abstract void appendLogicalFlags(ARM_Laziness lazy, OPT_Operand result);
+
+ /** Called when the ARM flags shall be set by a ADD operation. This sets all ARM flags. */
+ public abstract void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2);
+
+ /** Called when the ARM flags shall be set by a SUB operation. This sets all ARM flags. */
+ public abstract void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2);
+ }
+
+ /** Implements a flag behavior that will immediately evaluate all flag values. */
+ public final class ARM_ImmediateFlagBehavior extends ARM_FlagBehavior {
+ @Override
+ public void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Zero), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), result.copy(), op1.copy(), OPT_ConditionOperand.LOWER(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
+ }
+
+ @Override
+ public void appendLogicalFlags(ARM_Laziness lazy, OPT_Operand result) {
+
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Zero), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+
+ }
+
+ @Override
+ public void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Zero), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Negative), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Carry), op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand()));
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, getFlag(Flag.Overflow), op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely()));
+ }
+
+ @Override
+ public void onFlagRead(Flag flag, ARM_Laziness lazy) {
+ //nothing to do here, because the flags are already resolved
+ }
+
+ @Override
+ public void onFlagWrite(Flag flag, ARM_Laziness lazy) {
+ //nothing to do here, because the flags are already resolved
+ }
+ }
+
+ /** Implements a flag behavior that will use lazy evaluation to only determine a flag value
+ * when it is necessary. */
+ public final class ARM_LazyFlagBehavior extends ARM_FlagBehavior {
+
+ /** Operands for lazy evaluation of condition codes. */
+ private OPT_Register lazyOperand1;
+ private OPT_Register lazyOperand2;
+ private OPT_Register lazyLogicalOperand;
+
+ public ARM_LazyFlagBehavior() {
+ //prepare the laziness registers
+ lazyOperand1 = makeTemp(VM_TypeReference.Int).register;
+ lazyOperand2 = makeTemp(VM_TypeReference.Int).register;
+ lazyLogicalOperand = makeTemp(VM_TypeReference.Int).register;
+ }
+
+ @Override
+ public void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+
+ appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(lazyOperand1, VM_TypeReference.Int), op1.copy()));
+ appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(lazyOperand2, VM_TypeReference.Int), op2.copy()));
+
+ lazy.setValid(Flag.Zero, false);
+ lazy.setValid(Flag.Negative, false);
+ lazy.setValid(Flag.Carry, false);
+ lazy.setValid(Flag.Overflow, false);
+ lazy.setOperation(Operation.Add);
+
+ if (DBT_Options.debugTranslation) {
+ System.out.println("New Lazy state: " + lazy);
+ }
+ }
+
+ @Override
+ public void appendLogicalFlags(ARM_Laziness lazy, OPT_Operand result) {
+ appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(lazyLogicalOperand, VM_TypeReference.Int), result.copy()));
+
+ lazy.setValid(Flag.Zero, false);
+ lazy.setValid(Flag.Negative, false);
+
+ switch (lazy.getOperation()) {
+ case Add:
+ lazy.setOperation(Operation.LogicalOpAfterAdd);
+ break;
+
+ case Sub:
+ lazy.setOperation(Operation.LogicalOpAfterSub);
+ break;
+
+ case LogicalOpAfterAdd:
+ case LogicalOpAfterSub:
+ break;
+
+ default:
+ throw new RuntimeException("Unhandled laziness operation: " + lazy.getOperation());
+ }
+
+ if (DBT_Options.debugTranslation) {
+ System.out.println("New Lazy state: " + lazy);
+ }
+ }
+
+ @Override
+ public void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+
+ appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(lazyOperand1, VM_TypeReference.Int), op1.copy()));
+ appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(lazyOperand2, VM_TypeReference.Int), op2.copy()));
+
+ lazy.setValid(Flag.Zero, false);
+ lazy.setValid(Flag.Negative, false);
+ lazy.setValid(Flag.Carry, false);
+ lazy.setValid(Flag.Overflow, false);
+ lazy.setOperation(Operation.Sub);
+
+ if (DBT_Options.debugTranslation) {
+ System.out.println("New Lazy state: " + lazy);
+ }
+ }
+
+ private void resolveFlag(ARM_Laziness.Flag flag, ARM_Laziness lazy) {
+
+ if (lazy.isValid(flag))
+ return;
+
+ if (DBT_Options.debugTranslation) {
+ System.out.println("Resolving " + flag + " flag.");
+ }
+
+ OPT_RegisterOperand flagRegister = getFlag(flag);
+ OPT_RegisterOperand op1 = new OPT_RegisterOperand(lazyOperand1, VM_TypeReference.Int);
+ OPT_RegisterOperand op2 = new OPT_RegisterOperand(lazyOperand2, VM_TypeReference.Int);
+ OPT_RegisterOperand result;
+
+ switch (lazy.getOperation()) {
+ case Add:
+ result = gc.temps.makeTempInt();
+ appendInstruction(Binary.create(INT_ADD, result, op1, op2));
+ break;
+
+ case Sub:
+ result = gc.temps.makeTempInt();
+ appendInstruction(Binary.create(INT_SUB, result, op1, op2));
+ break;
+
+ case LogicalOpAfterAdd:
+ case LogicalOpAfterSub:
+ result = new OPT_RegisterOperand(lazyLogicalOperand, VM_TypeReference.Int);
+ break;
+
+ default:
+ throw new RuntimeException("Unhandled laziness operation: " + lazy.getOperation());
+ }
+
+ switch (flag) {
+ case Zero:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ break;
+
+ case Carry:
+ switch (lazy.getOperation()) {
+ case LogicalOpAfterAdd:
+ case Add:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, result.copy(), op1.copy(), OPT_ConditionOperand.LOWER(), new OPT_BranchProfileOperand()));
+ break;
+
+ case LogicalOpAfterSub:
+ case Sub:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.BORROW_FROM_SUB().flipCode(), new OPT_BranchProfileOperand()));
+ break;
+
+ default:
+ throw new RuntimeException("Unhandled laziness operation: " + lazy.getOperation());
+ }
+ break;
+
+ case Negative:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+ break;
+
+ case Overflow:
+ switch (lazy.getOperation()) {
+ case Add:
+ case LogicalOpAfterAdd:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
+ break;
+
+ case Sub:
+ case LogicalOpAfterSub:
+ appendInstruction(BooleanCmp.create(BOOLEAN_CMP_INT, flagRegister, op1.copy(), op2.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely()));
+ break;
+
+ default:
+ throw new RuntimeException("Unhandled laziness operation: " + lazy.getOperation());
+ }
+
+ break;
+
+ default:
+ throw new RuntimeException("Unhandled flag type: " + flag);
+ }
+
+ lazy.setValid(flag, true);
+
+ if (DBT_Options.debugTranslation) {
+ System.out.println("New Lazy state: " + lazy);
+ }
+ }
+
+ @Override
+ public void onFlagRead(Flag flag, ARM_Laziness lazy) {
+ resolveFlag(flag, lazy);
+
+ }
+
+ @Override
+ public void onFlagWrite(Flag flag, ARM_Laziness lazy) {
+ lazy.setValid(flag, true);
+ }
+ }
+
@Override
protected Laziness createInitialLaziness() {
return new ARM_Laziness();
@@ -319,26 +591,67 @@
return new OPT_RegisterOperand(regMap[r], VM_TypeReference.Int);
}
- public OPT_RegisterOperand getCarryFlag() {
+ public OPT_Operand readCarryFlag(ARM_Laziness lazy) {
carryUsed = true;
+ flagBehavior.onFlagRead(Flag.Carry, lazy);
return new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean);
}
- public OPT_RegisterOperand getZeroFlag() {
+ public OPT_Operand readZeroFlag(ARM_Laziness lazy) {
zeroUsed = true;
+ flagBehavior.onFlagRead(Flag.Zero, lazy);
return new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean);
}
- public OPT_RegisterOperand getNegativeFlag() {
+ public OPT_Operand readNegativeFlag(ARM_Laziness lazy) {
negativeUsed = true;
+ flagBehavior.onFlagRead(Flag.Negative, lazy);
return new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean);
}
- public OPT_RegisterOperand getOverflowFlag() {
+ public OPT_Operand readOverflowFlag(ARM_Laziness lazy) {
overflowUsed = true;
+ flagBehavior.onFlagRead(Flag.Overflow, lazy);
return new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean);
}
+ public OPT_RegisterOperand writeCarryFlag(ARM_Laziness lazy) {
+ carryUsed = true;
+ flagBehavior.onFlagWrite(Flag.Carry, lazy);
+ return new OPT_RegisterOperand(carryFlag, VM_TypeReference.Boolean);
+ }
+
+ public OPT_RegisterOperand writeZeroFlag(ARM_Laziness lazy) {
+ zeroUsed = true;
+ flagBehavior.onFlagWrite(Flag.Zero, lazy);
+ return new OPT_RegisterOperand(zeroFlag, VM_TypeReference.Boolean);
+ }
+
+ public OPT_RegisterOperand writeNegativeFlag(ARM_Laziness lazy) {
+ negativeUsed = true;
+ flagBehavior.onFlagWrite(Flag.Negative, lazy);
+ return new OPT_RegisterOperand(negativeFlag, VM_TypeReference.Boolean);
+ }
+
+ public OPT_RegisterOperand writeOverflowFlag(ARM_Laziness lazy) {
+ overflowUsed = true;
+ flagBehavior.onFlagWrite(Flag.Overflow, lazy);
+ return new OPT_RegisterOperand(overflowFlag, VM_TypeReference.Boolean);
+ }
+
+ public void appendLogicalFlags(ARM_Laziness lazy, OPT_Operand result) {
+ flagBehavior.appendLogicalFlags(lazy, result);
+ }
+
+ public void appendSubFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+ flagBehavior.appendSubFlags(lazy, result, op1, op2);
+ }
+
+ public void appendAddFlags(ARM_Laziness lazy, OPT_Operand result, OPT_Operand op1, OPT_Operand op2) {
+ flagBehavior.appendAddFlags(lazy, result, op1, op2);
+ }
+
+
@Override
protected OPT_Register[] getUnusedRegisters() {
@@ -372,7 +685,19 @@
@Override
public void resolveLaziness(Laziness laziness) {
- //NO-OP, as we're not using laziness at the moment
+ ARM_Laziness lazy = (ARM_Laziness)laziness;
+
+ if (carryUsed)
+ flagBehavior.onFlagRead(Flag.Carry, lazy);
+
+ if (negativeUsed)
+ flagBehavior.onFlagRead(Flag.Negative, lazy);
+
+ if (overflowUsed)
+ flagBehavior.onFlagRead(Flag.Overflow, lazy);
+
+ if (zeroUsed)
+ flagBehavior.onFlagRead(Flag.Zero, lazy);
}
@Override
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -46,13 +46,18 @@
Instruction decodedInstruction;
- if ((address & 0x1) == 1) {
- short binaryInstruction = (short)ps.memory.loadInstruction16(address & 0xFFFFFFFE);
- decodedInstruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction);
+ try {
+ if ((address & 0x1) == 1) {
+ short binaryInstruction = (short)ps.memory.loadInstruction16(address & 0xFFFFFFFE);
+ decodedInstruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction);
+ }
+ else {
+ int binaryInstruction = ps.memory.loadInstruction32(address);
+ decodedInstruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction);
+ }
}
- else {
- int binaryInstruction = ps.memory.loadInstruction32(address);
- decodedInstruction = ARM_InstructionDecoder.ARM32.decode(binaryInstruction);
+ catch (Exception e) {
+ return new ARM_DisassembledInstruction("Exception (" + e + ") while reading instruction at 0x" + Integer.toHexString(address));
}
DisassemblingVisitor disassembler = new DisassemblingVisitor();
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Laziness.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -2,41 +2,115 @@
import org.binarytranslator.generic.decoder.Laziness;
-public class ARM_Laziness extends Laziness {
+public final class ARM_Laziness extends Laziness {
+ public enum Operation {
+ Add, Sub, LogicalOpAfterAdd, LogicalOpAfterSub
+ }
+
+ public enum Flag {
+ Carry, Zero, Negative, Overflow
+ }
+
+ /** The state of the different ARM flags, compressed as bit fields within an integer. */
+ private int flagValid;
+
+ /** The operation that has to be performed to evaluate the remaining registers */
+ private Operation lazinessOperation;
+
final class ARM_LazinessKey extends Key {
private final int pc;
+ private final byte flagState;
public int hashCode() {
- return pc;
+ return pc | flagState;
}
public boolean equals(Object o) {
- return ((o instanceof ARM_LazinessKey) && ((ARM_LazinessKey) o).pc == pc);
+ if (!(o instanceof ARM_LazinessKey))
+ return false;
+
+ ARM_LazinessKey otherKey = (ARM_LazinessKey)o;
+ return otherKey.pc == pc && otherKey.flagState == flagState;
}
- ARM_LazinessKey(int pc) {
+ ARM_LazinessKey(int pc, ARM_Laziness lazy) {
this.pc = pc;
+ int tmpFlagState = lazy.flagValid & 0xF;
+ tmpFlagState |= (lazinessOperation.ordinal() + 1) << 4;
+
+ this.flagState = (byte)tmpFlagState;
}
public String toString() {
- return "0x" + Integer.toHexString(pc);
+ return String.format("0x%x (%d)", pc, flagState);
}
}
+ public ARM_Laziness() {
+ flagValid = 0xF; //all flags are valid
+ lazinessOperation = Operation.Add;
+ }
+
+ private ARM_Laziness(ARM_Laziness other) {
+ set(other);
+ }
+
+ public void setValid(Flag flag, boolean valid) {
+ flagValid |= 1 << flag.ordinal();
+ }
+
+ public boolean isValid(Flag flag) {
+ return (flagValid & (1 << flag.ordinal())) != 0;
+ }
+
+ public void setAddOperation() {
+ flagValid = 0; // all flags are invalid
+ lazinessOperation = Operation.Add;
+ }
+
+ public void setSubOperation() {
+ flagValid = 0; // all flags are invalid
+ lazinessOperation = Operation.Sub;
+ }
+
+ public Operation getOperation() {
+ return lazinessOperation;
+ }
+
+ public void setOperation(Operation lazinessOperation) {
+ this.lazinessOperation = lazinessOperation;
+ }
+
+ public void set(ARM_Laziness other) {
+ flagValid = other.flagValid;
+ lazinessOperation = other.lazinessOperation;
+ }
+
@Override
public Object clone() {
- return new ARM_Laziness();
+ return new ARM_Laziness(this);
}
@Override
- public boolean equivalent(Laziness other) {
- return other instanceof ARM_Laziness;
+ public boolean equivalent(Laziness o) {
+ if (!(o instanceof ARM_Laziness))
+ return false;
+
+ ARM_Laziness other = (ARM_Laziness)o;
+ return flagValid == other.flagValid && lazinessOperation == other.lazinessOperation;
}
@Override
public Key makeKey(int pc) {
- return new ARM_LazinessKey(pc);
+ return new ARM_LazinessKey(pc, this);
}
+ @Override
+ public String toString() {
+ return "Operation: " + lazinessOperation + ", C:" + (isValid(Flag.Carry) ? "1" : "0")
+ + ", Z:" + (isValid(Flag.Zero) ? "1" : "0")
+ + ", N:" + (isValid(Flag.Negative) ? "1" : "0")
+ + ", O:" + (isValid(Flag.Overflow) ? "1" : "0");
+ }
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -377,8 +377,9 @@
curBlock.deleteNormalOut();
curBlock.insertOut(nextBlock);
curBlock.insertOut(block1);
+ OPT_Operand carryFlag = translator.arm2ir.readCarryFlag(translator.lazy);
translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand.copy(), new OPT_IntConstantOperand(1)));
- translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, translator.arm2ir.getTempValidation(0), translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, translator.arm2ir.getTempValidation(0), carryFlag, new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand()));
//Block 1
translator.arm2ir.setCurrentBlock(block1);
@@ -414,7 +415,7 @@
value = new OPT_IntConstantOperand(operand.getImmediate());
if (operand.getShiftAmount() != 0) {
- OPT_RegisterOperand carryFlag = translator.arm2ir.getCarryFlag();
+ OPT_RegisterOperand carryFlag = translator.arm2ir.writeCarryFlag(translator.lazy);
OPT_Operand shifterCarryOut = new OPT_IntConstantOperand(((operand.getImmediate() & 0x80000000) != 0) ? 1 : 0);
//otherwise there is no shifter carry out
@@ -451,7 +452,7 @@
/** Returns the register that receives the shifte carry out*/
private OPT_RegisterOperand getShifterCarryOutTarget() {
- return translator.arm2ir.getCarryFlag();
+ return translator.arm2ir.writeCarryFlag(translator.lazy);
}
/**
@@ -685,7 +686,7 @@
curBlock.insertOut(block1);
curBlock.insertOut(nextBlock);
translator.arm2ir.appendInstruction(Binary.create(INT_USHR, resultRegister, shiftedOperand.copy(), new OPT_IntConstantOperand(1)));
- translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, translator.arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ translator.arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, validation, translator.arm2ir.readCarryFlag(translator.lazy), new OPT_IntConstantOperand(1), OPT_ConditionOperand.NOT_EQUAL(), nextBlock.makeJumpTarget(), new OPT_BranchProfileOperand()));
//Block 1
translator.arm2ir.setCurrentBlock(block1);
@@ -720,7 +721,7 @@
/** Return the instruction following this one or -1, if that is not yet known. */
int getSuccessor(int pc);
}
-
+
/** All ARM instructions that are supposed to be executed conditionally
* are decorated with this decorator.
* The decorator takes care of checking the individual condition and depending on it, executing the
@@ -729,7 +730,7 @@
protected final ARM_Instruction conditionalInstruction;
protected final Condition condition;
-
+
/** Decorates an ARM interpreter instruction, by making it execute conditionally. */
protected ConditionalDecorator(ARM_Instruction i) {
conditionalInstruction = i;
@@ -738,132 +739,213 @@
public int getSuccessor(int pc) {
- boolean thumbMode = (pc & 0x1) == 1;
- return pc + (thumbMode ? 2 : 4);
+ if (assumeInstructionWillBeSkipped()) {
+ boolean thumbMode = (pc & 0x1) == 1;
+ return pc + (thumbMode ? 2 : 4);
+ }
+ else {
+ return conditionalInstruction.getSuccessor(pc);
+ }
}
public Condition getCondition() {
return condition;
}
+ /**
+ * Returns the probability that this conditional instruction will be skipped.
+ *
+ * @return
+ * The probability that this conditional instruction will be skipped. Returns -1, if this probability
+ * cannot be estimated.
+ */
+ private float getSkipProbability() {
+
+ if (DBT_Options.optimizeTranslationByProfiling)
+ return -1f;
+
+ return ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4));
+ }
+
+ /**
+ * During the processing of this conditional instruction, shall we assume that it will be skipped?
+ * This is helpful to optimize the trace.
+ *
+ * @return
+ * True if it is likely that this instruction will be skipped. False otherwise.
+ */
+ private boolean assumeInstructionWillBeSkipped() {
+ float skipProbability = getSkipProbability();
+
+ return (skipProbability == -1f || skipProbability > 0.5f);
+ }
+
+ /**
+ conditionals are implemented easily: if the condition does not hold, then just
+ jump to the block following the conditional instruction. To do this, the following structure of
+ block is built:
+
+ --------------------------------------------------------
+ 1. block that checks the condition
+ --------------------------------------------------------
+ 2. conditional instruction
+ --------------------------------------------------------
+ 3. next instruction, when the instruction was not skipped
+ --------------------------------------------------------
+ 4. next instruction, when it was skipped <- next block
+ --------------------------------------------------------
+
+ Note that the two last blocks are only necessary when laziness is used. Otherwise, the first of
+ them will remain empty.
+ */
public void translate() {
- //conditionals are implemented easily: if the condition does not hold, then just
- //jump to the block following the conditional instruction
- OPT_BasicBlock nextInstruction = arm2ir.getNextBlock();
- OPT_BasicBlock condBlock = arm2ir.createBlockAfterCurrent();
- arm2ir.getCurrentBlock().deleteNormalOut();
- arm2ir.getCurrentBlock().insertOut(nextInstruction);
- arm2ir.getCurrentBlock().insertOut(condBlock);
+
+ OPT_BasicBlock blockThatChecksCondition = arm2ir.getCurrentBlock();
+ OPT_BasicBlock nextInstruction_InstructionSkipped = arm2ir.getNextBlock();
+ OPT_BasicBlock nextInstruction_InstructionNotSkipped = arm2ir.createBlockAfterCurrent();
+ OPT_BasicBlock condInstructionBlock = arm2ir.createBlockAfterCurrent();
+
+ //prepare to translate the actual condition
+ arm2ir.setCurrentBlock(blockThatChecksCondition);
+ blockThatChecksCondition.deleteNormalOut();
+ blockThatChecksCondition.insertOut(nextInstruction_InstructionSkipped);
+ blockThatChecksCondition.insertOut(condInstructionBlock);
//Query the branch profile to get the probability that this instruction is going to get executed
OPT_BranchProfileOperand profileOperand;
- if (DBT_Options.optimizeTranslationByProfiling) {
- float skipProbability = ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4));
+ float skipProbability = getSkipProbability();
- if (skipProbability == -1 || skipProbability == 0.5f) {
- profileOperand = new OPT_BranchProfileOperand();
- }
- else if (skipProbability > 0.8f) {
- profileOperand = OPT_BranchProfileOperand.always();
- condBlock.setInfrequent();
- }
- else if (skipProbability > 0.5f) {
- profileOperand = OPT_BranchProfileOperand.likely();
- condBlock.setInfrequent();
- }
- else if (skipProbability < 0.2f) {
- profileOperand = OPT_BranchProfileOperand.never();
- }
- else {
- profileOperand = OPT_BranchProfileOperand.unlikely();
- }
+ if (skipProbability == -1 || skipProbability == 0.5f) {
+ profileOperand = new OPT_BranchProfileOperand();
}
+ else if (skipProbability > 0.8f) {
+ profileOperand = OPT_BranchProfileOperand.always();
+ condInstructionBlock.setInfrequent();
+ }
+ else if (skipProbability > 0.5f) {
+ profileOperand = OPT_BranchProfileOperand.likely();
+ condInstructionBlock.setInfrequent();
+ }
+ else if (skipProbability < 0.2f) {
+ profileOperand = OPT_BranchProfileOperand.never();
+ }
else {
- profileOperand = new OPT_BranchProfileOperand();
+ profileOperand = OPT_BranchProfileOperand.unlikely();
}
switch (condition) {
case AL:
- throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator.");
+ throw new RuntimeException("Unconditional instructions should not be decorated with a ConditionalDecorator.");
case CC:
//return !regs.isCarrySet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getCarryFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readCarryFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
break;
case CS:
//return regs.isCarrySet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getCarryFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readCarryFlag(lazy), OPT_ConditionOperand.EQUAL());
break;
case EQ:
//return regs.isZeroSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getZeroFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readZeroFlag(lazy), OPT_ConditionOperand.EQUAL());
break;
case GE:
//return regs.isNegativeSet() == regs.isOverflowSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL(), arm2ir.getOverflowFlag());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.EQUAL(), arm2ir.readOverflowFlag(lazy));
break;
case GT:
- translateCondition_GT(nextInstruction, profileOperand);
+ translateCondition_GT(nextInstruction_InstructionSkipped, profileOperand);
break;
case HI:
- translateCondition_HI(nextInstruction, profileOperand);
+ translateCondition_HI(nextInstruction_InstructionSkipped, profileOperand);
break;
case LE:
- translateCondition_LE(nextInstruction, profileOperand);
+ translateCondition_LE(nextInstruction_InstructionSkipped, profileOperand);
break;
case LS:
- translateCondition_LS(nextInstruction, profileOperand, condBlock);
+ translateCondition_LS(nextInstruction_InstructionSkipped, profileOperand, condInstructionBlock);
break;
case LT:
//return regs.isNegativeSet() != regs.isOverflowSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.getOverflowFlag());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.readOverflowFlag(lazy));
break;
case MI:
//return regs.isNegativeSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.EQUAL());
break;
case NE:
//return !regs.isZeroSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getZeroFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readZeroFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
break;
case NV:
//never execute this instruction
- translateCondition(nextInstruction, profileOperand, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL());
break;
case PL:
//return !regs.isNegativeSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readNegativeFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
break;
case VC:
//return !regs.isOverflowSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getOverflowFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readOverflowFlag(lazy), OPT_ConditionOperand.NOT_EQUAL());
break;
case VS:
//return regs.isOverflowSet();
- translateCondition(nextInstruction, profileOperand, arm2ir.getOverflowFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction_InstructionSkipped, profileOperand, arm2ir.readOverflowFlag(lazy), OPT_ConditionOperand.EQUAL());
break;
default:
throw new RuntimeException("Unexpected condition code: " + condition);
- }
+ }
+
+ //Translate the conditional instruction first to see if the lazy state is changed by the
+ //conditional instruction
+ ARM_Laziness lazinessWhenInstructionSkipped = (ARM_Laziness)lazy.clone();
- arm2ir.setCurrentBlock(condBlock);
+ arm2ir.setCurrentBlock(condInstructionBlock);
+ arm2ir.setNextBlock(nextInstruction_InstructionNotSkipped);
conditionalInstruction.translate();
+
+ int followingInstructionAddress = pc + (inThumb() ? 2 : 4);
+
+ //yes it did, so we may need to translate the successor instruction twice
+ if (assumeInstructionWillBeSkipped()) {
+
+ //Did the laziness change during the translation?
+ if (!lazy.equivalent(lazinessWhenInstructionSkipped)) {
+ //Modify block 3 so that it resolves the different laziness correctly
+ arm2ir.setCurrentBlock(nextInstruction_InstructionNotSkipped);
+ nextInstruction_InstructionNotSkipped.deleteNormalOut();
+ arm2ir.appendBranch(followingInstructionAddress, lazy);
+ lazy.set(lazinessWhenInstructionSkipped);
+ }
+
+ arm2ir.setNextBlock(nextInstruction_InstructionSkipped);
+
+ }
+ else {
+ //Modify block 4 so that it resolves the different laziness correctly
+ arm2ir.setCurrentBlock(nextInstruction_InstructionSkipped);
+ nextInstruction_InstructionSkipped.deleteNormalOut();
+ arm2ir.appendBranch(followingInstructionAddress, lazinessWhenInstructionSkipped);
+
+ arm2ir.setNextBlock(nextInstruction_InstructionNotSkipped);
+ }
}
private void translateCondition(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability, OPT_Operand operand, OPT_ConditionOperand condition) {
@@ -878,8 +960,8 @@
private void translateCondition_HI(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return regs.isCarrySet() && !regs.isZeroSet();
- OPT_Operand carry = arm2ir.getCarryFlag();
- OPT_Operand zero = arm2ir.getZeroFlag();
+ OPT_Operand carry = arm2ir.readCarryFlag(lazy);
+ OPT_Operand zero = arm2ir.readZeroFlag(lazy);
OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean();
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, carry,
@@ -890,33 +972,20 @@
private void translateCondition_LS(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability, OPT_BasicBlock actualInstruction) {
//return !regs.isCarrySet() || regs.isZeroSet();
- OPT_Operand carry = arm2ir.getCarryFlag();
- OPT_Operand zero = arm2ir.getZeroFlag();
+ OPT_Operand carry = arm2ir.readCarryFlag(lazy);
+ OPT_Operand zero = arm2ir.readZeroFlag(lazy);
OPT_RegisterOperand result = arm2ir.getTempInt(0);
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, carry, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), skipProbability));
-
-/* cond1.deleteNormalOut();
- cond1.insertOut(cond2);
- cond1.insertOut(actualInstruction);
-
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), carry, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), actualInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
-
- arm2ir.setCurrentBlock(cond2);
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), actualInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
- arm2ir.appendInstruction(Goto.create(GOTO, nextInstruction.makeJumpTarget()));
- cond2.deleteNormalOut();
- cond2.insertOut(nextInstruction);
- cond2.insertOut(actualInstruction);*/
}
private void translateCondition_GT(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet();
- OPT_Operand negative = arm2ir.getNegativeFlag();
- OPT_Operand overflow = arm2ir.getOverflowFlag();
- OPT_Operand zero = arm2ir.getZeroFlag();
+ OPT_Operand negative = arm2ir.readNegativeFlag(lazy);
+ OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
+ OPT_Operand zero = arm2ir.readZeroFlag(lazy);
OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean();
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, negative,
@@ -927,9 +996,9 @@
private void translateCondition_LE(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet());
- OPT_Operand negative = arm2ir.getNegativeFlag();
- OPT_Operand overflow = arm2ir.getOverflowFlag();
- OPT_Operand zero = arm2ir.getZeroFlag();
+ OPT_Operand negative = arm2ir.readNegativeFlag(lazy);
+ OPT_Operand overflow = arm2ir.readOverflowFlag(lazy);
+ OPT_Operand zero = arm2ir.readZeroFlag(lazy);
OPT_RegisterOperand result = arm2ir.getGenerationContext().temps.makeTempBoolean();
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, negative,
@@ -1021,21 +1090,8 @@
* The add's right-hand-side operator.
*/
protected final void setAddFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) {
- //set the carry flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), result.copy(), lhs.copy(), OPT_ConditionOperand.LOWER(), new OPT_BranchProfileOperand()));
- //set the overflow flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs.copy(), rhs.copy(), OPT_ConditionOperand.OVERFLOW_FROM_ADD(), OPT_BranchProfileOperand.unlikely()));
-
- //set the negative flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
-
- //set the zero flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ arm2ir.appendAddFlags(lazy, result, lhs, rhs);
}
/** Sets the processor flags according to the result of subtracting <code>rhs</code> from <code>lhs</code>.*/
@@ -1077,22 +1133,8 @@
* The sub's right-hand-side operator.
*/
protected final void setSubFlags(OPT_Operand result, OPT_Operand lhs, OPT_Operand rhs) {
- //set the carry flag to not(Borrow)
- OPT_ConditionOperand notBorrowFromSub = OPT_ConditionOperand.BORROW_FROM_SUB().flipCode();
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getCarryFlag(), lhs.copy(), rhs.copy(), notBorrowFromSub, new OPT_BranchProfileOperand()));
- //set the overflow flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getOverflowFlag(), lhs.copy(), rhs.copy(), OPT_ConditionOperand.OVERFLOW_FROM_SUB(), OPT_BranchProfileOperand.unlikely()));
-
- //set the negative flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
-
- //set the zero flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ arm2ir.appendSubFlags(lazy, result, lhs, rhs);
}
public Condition getCondition() {
@@ -1165,13 +1207,8 @@
protected final void setLogicalFlags(OPT_Operand result) {
//the shifter carry out has already been set during the resolve-phase
- //set the negative flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
-
- //set the zero flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ //set the negative & zero flag
+ arm2ir.appendLogicalFlags(lazy, result);
}
}
@@ -1287,7 +1324,7 @@
//Is the carry set at all? if not, just jump to addWithoutCarry
arm2ir.appendInstruction(Binary.create(INT_ADD, result, operand1, operand2));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.readCarryFlag(lazy), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), addWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand()));
arm2ir.getCurrentBlock().insertOut(addWithCarry);
//Yes, the carry flag is set. Pre-increase the result by one to account for the carry.
@@ -1318,7 +1355,7 @@
//Is the carry set? if yes, just jump to subWithoutCarry
arm2ir.appendInstruction(Binary.create(INT_SUB, result, operand1, operand2));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.getCarryFlag(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), subWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), arm2ir.readCarryFlag(lazy), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), subWithoutCarry.makeJumpTarget(), new OPT_BranchProfileOperand()));
arm2ir.getCurrentBlock().insertOut(subWithCarry);
//No, the carry flag is not set. That means, we have to use the carry within the subtraction (weird arm logic).
@@ -1674,41 +1711,7 @@
//first translate the register write back
translateWriteback(startAddress.copyRO(), nextAddress.copyRO());
-
- //shall we switch to thumb mode?
- /*OPT_BasicBlock finishInstruction = arm2ir.createBlockAfterCurrentNotInCFG();
- OPT_BasicBlock switchToARMBlock = arm2ir.createBlockAfterCurrentNotInCFG();
- OPT_BasicBlock switchToThumbBlock = arm2ir.createBlockAfterCurrentNotInCFG();
-
- //Current block
- OPT_BasicBlock currentBlock = arm2ir.getCurrentBlock();
- currentBlock.deleteNormalOut();
- currentBlock.insertOut(switchToARMBlock);
- currentBlock.insertOut(switchToThumbBlock);
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), regPC.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.BIT_TEST(), switchToThumbBlock.makeJumpTarget(), OPT_BranchProfileOperand.never()));
- arm2ir.appendInstruction(Goto.create(GOTO, switchToARMBlock.makeJumpTarget()));
-
- //Yes, switch to thumb mode
- arm2ir.setCurrentBlock(switchToThumbBlock);
- switchToThumbBlock.insertOut(finishInstruction);
- OPT_Instruction call_setThumbMode = createCallToRegisters("setThumbMode", "(Z)V", 1);
- Call.setParam(call_setThumbMode, 1, new OPT_IntConstantOperand(1));
- arm2ir.appendCustomCall(call_setThumbMode);
- arm2ir.appendInstruction(Goto.create(GOTO, finishInstruction.makeJumpTarget()));
- //No, don't switch to thumb mode
- arm2ir.setCurrentBlock(switchToARMBlock);
- switchToARMBlock.insertOut(finishInstruction);
- arm2ir.appendInstruction(Binary.create(INT_AND, regPC.copyRO(), regPC.copy(), new OPT_IntConstantOperand(0xFFFFFFFE)));
- OPT_Instruction call_setArmMode = createCallToRegisters("setThumbMode", "(Z)V", 1);
- Call.setParam(call_setArmMode, 1, new OPT_IntConstantOperand(0));
- arm2ir.appendCustomCall(call_setArmMode);
- arm2ir.appendInstruction(Goto.create(GOTO, finishInstruction.makeJumpTarget()));
-
- //according to the APCS, these types of instructions are usually function returns
- arm2ir.setCurrentBlock(finishInstruction);
- arm2ir.appendBranch(regPC, lazy, BranchType.RETURN);*/
-
arm2ir.appendBranch(regPC, lazy, BranchType.RETURN);
return;
}
@@ -1940,13 +1943,8 @@
}
if (i.updateConditionCodes) {
- //set the negative flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getNegativeFlag(), result.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
-
- //set the zero flag
- arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_INT, arm2ir.getZeroFlag(), result.copyRO(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ //set the negative & zero flag
+ arm2ir.appendLogicalFlags(lazy, result);
}
}
@@ -2006,13 +2004,13 @@
}
if (i.updateConditionCodes) {
- //set the negative flag
+ //set the negative flag
arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_LONG, arm2ir.getNegativeFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
+ BOOLEAN_CMP_LONG, arm2ir.writeNegativeFlag(lazy), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.LESS(), new OPT_BranchProfileOperand()));
//set the zero flag
arm2ir.appendInstruction(BooleanCmp.create(
- BOOLEAN_CMP_LONG, arm2ir.getZeroFlag(), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
+ BOOLEAN_CMP_LONG, arm2ir.writeZeroFlag(lazy), result.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
}
}
@@ -2223,6 +2221,7 @@
//do we actually have to perform the rotation?
arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), rotation.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), rotationBlock.makeJumpTarget(), OPT_BranchProfileOperand.never()));
arm2ir.appendInstruction(Goto.create(GOTO, remainderBlock.makeJumpTarget()));
+ arm2ir.getCurrentBlock().insertOut(remainderBlock);
//in case we are performing the rotation...
arm2ir.setCurrentBlock(rotationBlock);
Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java
===================================================================
--- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -247,7 +247,7 @@
* dependencies (unknown branch targets etc.) have been resolved. This function is useful for
* debug purposes.
*/
- protected void printTraceAfterCompletion() {
+ public void printTraceAfterCompletion() {
printTraceAfterCompletionRequested = true;
}
@@ -283,18 +283,9 @@
printTraceAfterCompletionRequested = false;
printNextBlocks(preFillBlock, 50);
}
+
+ ((DBT_Trace) gc.method).setNumberOfInstructions(numberOfInstructions);
}
- /*
- protected final void maximizeBasicBlocks(OPT_IR ir) {
- for (OPT_BasicBlock currBB = ir.cfg.firstInCodeOrder(); currBB != null;) {
- if (currBB.mergeFallThrough(ir)) {
- // don't advance currBB; it may have a new trivial fallthrough to
- // swallow
- } else {
- currBB = currBB.nextBasicBlockInCodeOrder();
- }
- }
- }*/
/**
@@ -759,8 +750,11 @@
* within the code cache c) The trace is already too long d) the branch is
* supposedly a CALL or RETURN
*/
+
+ DBT_Trace compiledTrace = ps.codeCache.tryGet(targetPc);
+
return DBT_Options.singleInstrTranslation == false
- && ps.codeCache.tryGet(targetPc) == null && !shallTraceStop()
+ && (compiledTrace == null || compiledTrace.getNumberOfInstructions() > 20) && !shallTraceStop()
&& jump.type != BranchType.CALL && jump.type != BranchType.RETURN;
}
@@ -789,7 +783,7 @@
if (targetBB != null)
return targetBB;
- if (inlineBranchInstruction(targetPc, jump)) {
+ if (!inlineBranchInstruction(targetPc, jump)) {
// Just exit the trace and continue at the target address in a new trace
if (currentBlock.getNumberOfRealInstructions() != 0) {
@@ -903,7 +897,7 @@
// Copy the value into the register specified by gc.resultReg.
appendInstruction(Move.create(INT_MOVE, new OPT_RegisterOperand(
gc.resultReg, VM_TypeReference.Int), nextPc.copy()));
- resolveLaziness(laziness);
+ resolveLaziness((Laziness)laziness.clone());
appendInstruction(Goto.create(GOTO, finishBlock.makeJumpTarget()));
currentBlock.deleteNormalOut();
currentBlock.insertOut(finishBlock);
@@ -1305,9 +1299,7 @@
*/
public void appendInterpretedInstruction(int pc, Laziness lazy) {
- if (lazy != null)
- resolveLaziness(lazy);
-
+ resolveLaziness(lazy);
spillAllRegisters();
// Prepare a local variable of type Interpreter
Modified: src/org/binarytranslator/vmInterface/DBT_Trace.java
===================================================================
--- src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-08-07 22:27:33 UTC (rev 160)
+++ src/org/binarytranslator/vmInterface/DBT_Trace.java 2007-08-07 22:28:53 UTC (rev 161)
@@ -97,6 +97,9 @@
*/
public final int pc;
+ /** The number of guest instructions that have been compiled into this trace. */
+ private int numberOfInstructions;
+
/**
* In order to allow arbitrary calls within a trace, we have to store at which bytecode index
* a method is called in which way. This class stores the necessary information. */
@@ -321,4 +324,12 @@
public int getBytecodeLength() {
return 256;
}
+
+ public int getNumberOfInstructions() {
+ return numberOfInstructions;
+ }
+
+ public void setNumberOfInstructions(int numberOfInstructions) {
+ this.numberOfInstructions = numberOfInstructions;
+ }
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-07 22:27:31
|
Revision: 160
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=160&view=rev
Author: michael_baer
Date: 2007-08-07 15:27:33 -0700 (Tue, 07 Aug 2007)
Log Message:
-----------
- Reverted removal of Pearcolator's custom OPT_Simplifier
- Adapted to compile with recent JRVM
Added Paths:
-----------
ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java
Added: ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java
===================================================================
--- ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java (rev 0)
+++ ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java 2007-08-07 22:27:33 UTC (rev 160)
@@ -0,0 +1,3643 @@
+/*
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
+ */
+package org.jikesrvm.compilers.opt;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import org.jikesrvm.VM;
+import static org.jikesrvm.VM_SizeConstants.BITS_IN_ADDRESS;
+import static org.jikesrvm.VM_SizeConstants.BITS_IN_INT;
+import static org.jikesrvm.VM_SizeConstants.BITS_IN_LONG;
+import static org.jikesrvm.VM_SizeConstants.LOG_BYTES_IN_ADDRESS;
+import org.jikesrvm.classloader.VM_Field;
+import org.jikesrvm.classloader.VM_Method;
+import org.jikesrvm.classloader.VM_Type;
+import org.jikesrvm.classloader.VM_TypeReference;
+import org.jikesrvm.compilers.opt.OPT_Simplifier.DefUseEffect;
+import org.jikesrvm.compilers.opt.ir.Binary;
+import org.jikesrvm.compilers.opt.ir.BooleanCmp;
+import org.jikesrvm.compilers.opt.ir.BooleanCmp2;
+import org.jikesrvm.compilers.opt.ir.BoundsCheck;
+import org.jikesrvm.compilers.opt.ir.Call;
+import org.jikesrvm.compilers.opt.ir.CondMove;
+import org.jikesrvm.compilers.opt.ir.Empty;
+import org.jikesrvm.compilers.opt.ir.GetField;
+import org.jikesrvm.compilers.opt.ir.GuardedBinary;
+import org.jikesrvm.compilers.opt.ir.GuardedUnary;
+import org.jikesrvm.compilers.opt.ir.InstanceOf;
+import org.jikesrvm.compilers.opt.ir.Load;
+import org.jikesrvm.compilers.opt.ir.Move;
+import org.jikesrvm.compilers.opt.ir.NullCheck;
+import org.jikesrvm.compilers.opt.ir.OPT_AbstractRegisterPool;
+import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand;
+import org.jikesrvm.compilers.opt.ir.OPT_BranchProfileOperand;
+import org.jikesrvm.compilers.opt.ir.OPT_CodeConstantOperand;
+import org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand;
+import org.jikesrvm.compilers.opt.ir.OPT_ConstantOperand;
+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_MethodOperand;
+import org.jikesrvm.compilers.opt.ir.OPT_NullConstantOperand;
+import org.jikesrvm.compilers.opt.ir.OPT_ObjectConstantOperand;
+import org.jikesrvm.compilers.opt.ir.OPT_Operand;
+import org.jikesrvm.compilers.opt.ir.OPT_Operator;
+import org.jikesrvm.compilers.opt.ir.OPT_OperatorNames;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.ADDR_2INT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.ADDR_2LONG_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.ARRAYLENGTH_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_ADDR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_DOUBLE;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_FLOAT;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_INT;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_INT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_LONG;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_NOT;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_NOT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOUNDS_CHECK_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CALL_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CHECKCAST_NOTNULL;
+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_2FLOAT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_2INT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_2LONG_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_ADD_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_AS_LONG_BITS_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_CMPG_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_CMPL_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_COND_MOVE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_DIV_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_MOVE;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_MUL_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_NEG;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_NEG_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_REM_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_SUB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_2DOUBLE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_2INT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_2LONG_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_ADD_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_AS_INT_BITS_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_CMPG_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_CMPL_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_COND_MOVE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_DIV_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_MOVE;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_MUL_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_NEG;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_NEG_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_REM_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_SUB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GETFIELD_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_ARRAY_ELEMENT_TIB_FROM_TIB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_CLASS_TIB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_DOES_IMPLEMENT_FROM_TIB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_OBJ_TIB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_SUPERCLASS_IDS_FROM_TIB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_TYPE_FROM_TIB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GUARD_COMBINE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GUARD_COND_MOVE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GUARD_MOVE;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INSTANCEOF_NOTNULL;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INSTANCEOF_NOTNULL_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_2ADDRSigExt_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2ADDRZerExt_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2BYTE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2DOUBLE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2FLOAT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2LONG_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2SHORT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2USHORT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_ADD;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_ADD_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_AND_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_BITS_AS_FLOAT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_COND_MOVE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_DIV_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_MOVE;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_MUL_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_NEG;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_NEG_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_NOT;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_NOT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_OR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_REM_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SHL;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SHL_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SHR;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SHR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SUB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_USHR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_XOR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_ZERO_CHECK_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_2ADDR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_2DOUBLE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_2FLOAT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_2INT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_ADD;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_ADD_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_AND_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_BITS_AS_DOUBLE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_CMP_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_COND_MOVE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_DIV_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_MOVE;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_MUL_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_NEG;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_NEG_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_NOT;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_NOT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_OR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_REM_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SHL;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SHL_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SHR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SUB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_USHR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_XOR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_ZERO_CHECK_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.MUST_IMPLEMENT_INTERFACE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.NOP;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.NULL_CHECK_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.REF_ADD;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_ADD_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_AND_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_COND_MOVE_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_LOAD_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_MOVE;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_NEG;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_NOT;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_NOT_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_OR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_SHL;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_SHL_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_SHR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_SUB_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_USHR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_XOR_opcode;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.TRAP;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.TRAP_IF;
+import static org.jikesrvm.compilers.opt.ir.OPT_Operators.TRAP_IF_opcode;
+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_TrueGuardOperand;
+import org.jikesrvm.compilers.opt.ir.OPT_TypeOperand;
+import org.jikesrvm.compilers.opt.ir.OPT_UnreachableOperand;
+import org.jikesrvm.compilers.opt.ir.StoreCheck;
+import org.jikesrvm.compilers.opt.ir.Trap;
+import org.jikesrvm.compilers.opt.ir.TrapIf;
+import org.jikesrvm.compilers.opt.ir.TypeCheck;
+import org.jikesrvm.compilers.opt.ir.Unary;
+import org.jikesrvm.compilers.opt.ir.ZeroCheck;
+import org.jikesrvm.objectmodel.VM_TIBLayoutConstants;
+import org.jikesrvm.runtime.VM_Reflection;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.Word;
+
+/**
+ * A constant folder, strength reducer and axiomatic simplifier.
+ *
+ * <p> This module performs no analysis, it simply attempts to
+ * simplify the instruction as is. The intent is that
+ * analysis modules can call this transformation engine, allowing us to
+ * share the tedious simplification code among multiple analysis modules.
+ *
+ * <p> NOTE: For maintainability purposes, I've intentionally avoided being
+ * clever about combining 'similar' operators together into a combined case
+ * of the main switch switch statement. Also, operators are in sorted ordered
+ * within each major grouping. Please maintain this coding style.
+ * I'd rather have this module be 2000 lines of obviously correct code than
+ * 500 lines of clever code.
+ */
+public abstract class OPT_Simplifier extends OPT_IRTools {
+ // NOTE: The convention is that constant folding is controlled based
+ // on the type of the result of the operator, not the type of its inputs.
+ /**
+ * Constant fold integer operations?
+ */
+ public static final boolean CF_INT = true;
+ /**
+ * Constant fold address operations?
+ */
+ public static final boolean CF_LONG = true;
+
+ /**
+ * Constant fold address operations?
+ */
+ public static final boolean CF_ADDR = true;
+
+ /**
+ * Constant fold float operations? Default is true, flip to avoid
+ * consuming precious JTOC slots to hold new constant values.
+ */
+ public static final boolean CF_FLOAT = true;
+ /**
+ * Constant fold double operations? Default is true, flip to avoid
+ * consuming precious JTOC slots to hold new constant values.
+ */
+ public static final boolean CF_DOUBLE = true;
+ /**
+ * Constant fold field operations? Default is true, flip to avoid
+ * consuming precious JTOC slots to hold new constant values.
+ */
+ public static final boolean CF_FIELDS = true;
+
+ /**
+ * Constant fold TIB operations? Default is true, flip to avoid
+ * consuming precious JTOC slots to hold new constant values.
+ */
+ public static final boolean CF_TIB = true;
+
+ /**
+ * Effect of the simplification on Def-Use chains
+ */
+ public enum DefUseEffect {
+ /**
+ * Enumeration value to indicate an operation is unchanged,
+ * although the order of operands may have been canonicalized and
+ * type information strengthened.
+ */
+ UNCHANGED,
+ /**
+ * Enumeration value to indicate an operation has been replaced by
+ * a move instruction with a constant right hand side.
+ */
+ MOVE_FOLDED,
+ /**
+ * Enumeration value to indicate an operation has been replaced by
+ * a move instruction with a non-constant right hand side.
+ */
+ MOVE_REDUCED,
+ /**
+ * Enumeration value to indicate an operation has been replaced by
+ * an unconditional trap instruction.
+ */
+ TRAP_REDUCED,
+ /**
+ * Enumeration value to indicate an operation has been replaced by
+ * a cheaper, but non-move instruction.
+ */
+ REDUCED
+ }
+
+ /**
+ * Given an instruction, attempt to simplify it.
+ * The instruction will be mutated in place.
+ *
+ * <p> We don't deal with branching operations here --
+ * doing peephole optimizations of branches
+ * is the job of a separate module.
+ *
+ * @param regpool register pool in case simplification requires a temporary register
+ * @param s the instruction to simplify
+ * @return one of UNCHANGED, MOVE_FOLDED, MOVE_REDUCED, TRAP_REDUCED, REDUCED
+ */
+ public static DefUseEffect simplify(OPT_AbstractRegisterPool regpool, OPT_Instruction s) {
+ DefUseEffect result;
+ char opcode = s.getOpcode();
+ switch (opcode) {
+ ////////////////////
+ // GUARD operations
+ ////////////////////
+ case GUARD_COMBINE_opcode:
+ result = guardCombine(s);
+ break;
+ ////////////////////
+ // TRAP operations
+ ////////////////////
+ case TRAP_IF_opcode:
+ result = trapIf(s);
+ break;
+ case NULL_CHECK_opcode:
+ result = nullCheck(s);
+ break;
+ case INT_ZERO_CHECK_opcode:
+ result = intZeroCheck(s);
+ break;
+ case LONG_ZERO_CHECK_opcode:
+ result = longZeroCheck(s);
+ break;
+ case CHECKCAST_opcode:
+ result = checkcast(s);
+ break;
+ case CHECKCAST_UNRESOLVED_opcode:
+ result = checkcast(s);
+ break;
+ case CHECKCAST_NOTNULL_opcode:
+ result = checkcastNotNull(s);
+ break;
+ case INSTANCEOF_opcode:
+ result = instanceOf(s);
+ break;
+ case INSTANCEOF_NOTNULL_opcode:
+ result = instanceOfNotNull(s);
+ break;
+ case OBJARRAY_STORE_CHECK_opcode:
+ result = objarrayStoreCheck(s);
+ break;
+ case OBJARRAY_STORE_CHECK_NOTNULL_opcode:
+ result = objarrayStoreCheckNotNull(s);
+ break;
+ case MUST_IMPLEMENT_INTERFACE_opcode:
+ result = mustImplementInterface(s);
+ break;
+ ////////////////////
+ // Conditional moves
+ ////////////////////
+ case INT_COND_MOVE_opcode:
+ result = intCondMove(s);
+ break;
+ case LONG_COND_MOVE_opcode:
+ result = longCondMove(s);
+ break;
+ case FLOAT_COND_MOVE_opcode:
+ result = floatCondMove(s);
+ break;
+ case DOUBLE_COND_MOVE_opcode:
+ result = doubleCondMove(s);
+ break;
+ case REF_COND_MOVE_opcode:
+ result = refCondMove(s);
+ break;
+ case GUARD_COND_MOVE_opcode:
+ result = guardCondMove(s);
+ break;
+ ////////////////////
+ // INT ALU operations
+ ////////////////////
+ case BOOLEAN_NOT_opcode:
+ result = booleanNot(s);
+ break;
+ case BOOLEAN_CMP_INT_opcode:
+ result = booleanCmpInt(s);
+ break;
+ case BOOLEAN_CMP_ADDR_opcode:
+ result = booleanCmpAddr(s);
+ break;
+ case BOOLEAN_CMP2_INT_OR_opcode:
+ result = booleanCmp2IntOr(s);
+ break;
+ // case BOOLEAN_CMP2_INT_AND:
+ // result = booleanCmp2IntAnd(s);
+ // break;
+ case INT_ADD_opcode:
+ result = intAdd(s);
+ break;
+ case INT_AND_opcode:
+ result = intAnd(s);
+ break;
+ case INT_DIV_opcode:
+ result = intDiv(s);
+ break;
+ case INT_MUL_opcode:
+ result = intMul(regpool, s);
+ break;
+ case INT_NEG_opcode:
+ result = intNeg(s);
+ break;
+ case INT_NOT_opcode:
+ result = intNot(s);
+ break;
+ case INT_OR_opcode:
+ result = intOr(s);
+ break;
+ case INT_REM_opcode:
+ result = intRem(s);
+ break;
+ case INT_SHL_opcode:
+ result = intShl(s);
+ break;
+ case INT_SHR_opcode:
+ result = intShr(s);
+ break;
+ case INT_SUB_opcode:
+ result = intSub(s);
+ break;
+ case INT_USHR_opcode:
+ result = intUshr(s);
+ break;
+ case INT_XOR_opcode:
+ result = intXor(s);
+ break;
+ ////////////////////
+ // WORD ALU operations
+ ////////////////////
+ case REF_ADD_opcode:
+ result = refAdd(s);
+ break;
+ case REF_AND_opcode:
+ result = refAnd(s);
+ break;
+ case REF_SHL_opcode:
+ result = refShl(s);
+ break;
+ case REF_SHR_opcode:
+ result = refShr(s);
+ break;
+ case REF_NOT_opcode:
+ result = refNot(s);
+ break;
+ case REF_OR_opcode:
+ result = refOr(s);
+ break;
+ case REF_SUB_opcode:
+ result = refSub(s);
+ break;
+ case REF_USHR_opcode:
+ result = refUshr(s);
+ break;
+ case REF_XOR_opcode:
+ result = refXor(s);
+ break;
+ ////////////////////
+ // LONG ALU operations
+ ////////////////////
+ case LONG_ADD_opcode:
+ result = longAdd(s);
+ break;
+ case LONG_AND_opcode:
+ result = longAnd(s);
+ break;
+ case LONG_CMP_opcode:
+ result = longCmp(s);
+ break;
+ case LONG_DIV_opcode:
+ result = longDiv(s);
+ break;
+ case LONG_MUL_opcode:
+ result = longMul(regpool, s);
+ break;
+ case LONG_NEG_opcode:
+ result = longNeg(s);
+ break;
+ case LONG_NOT_opcode:
+ result = longNot(s);
+ break;
+ case LONG_OR_opcode:
+ result = longOr(s);
+ break;
+ case LONG_REM_opcode:
+ result = longRem(s);
+ break;
+ case LONG_SHL_opcode:
+ result = longShl(s);
+ break;
+ case LONG_SHR_opcode:
+ result = longShr(s);
+ break;
+ case LONG_SUB_opcode:
+ result = longSub(s);
+ break;
+ case LONG_USHR_opcode:
+ result = longUshr(s);
+ break;
+ case LONG_XOR_opcode:
+ result = longXor(s);
+ break;
+ ////////////////////
+ // FLOAT ALU operations
+ ////////////////////
+ case FLOAT_ADD_opcode:
+ result = floatAdd(s);
+ break;
+ case FLOAT_CMPG_opcode:
+ result = floatCmpg(s);
+ break;
+ case FLOAT_CMPL_opcode:
+ result = floatCmpl(s);
+ break;
+ case FLOAT_DIV_opcode:
+ result = floatDiv(s);
+ break;
+ case FLOAT_MUL_opcode:
+ result = floatMul(s);
+ break;
+ case FLOAT_NEG_opcode:
+ result = floatNeg(s);
+ break;
+ case FLOAT_REM_opcode:
+ result = floatRem(s);
+ break;
+ case FLOAT_SUB_opcode:
+ result = floatSub(s);
+ break;
+ ////////////////////
+ // DOUBLE ALU operations
+ ////////////////////
+ case DOUBLE_ADD_opcode:
+ result = doubleAdd(s);
+ break;
+ case DOUBLE_CMPG_opcode:
+ result = doubleCmpg(s);
+ break;
+ case DOUBLE_CMPL_opcode:
+ result = doubleCmpl(s);
+ break;
+ case DOUBLE_DIV_opcode:
+ result = doubleDiv(s);
+ break;
+ case DOUBLE_MUL_opcode:
+ result = doubleMul(s);
+ break;
+ case DOUBLE_NEG_opcode:
+ result = doubleNeg(s);
+ break;
+ case DOUBLE_REM_opcode:
+ result = doubleRem(s);
+ break;
+ case DOUBLE_SUB_opcode:
+ result = doubleSub(s);
+ break;
+ ////////////////////
+ // CONVERSION operations
+ ////////////////////
+ case DOUBLE_2FLOAT_opcode:
+ result = double2Float(s);
+ break;
+ case DOUBLE_2INT_opcode:
+ result = double2Int(s);
+ break;
+ case DOUBLE_2LONG_opcode:
+ result = double2Long(s);
+ break;
+ case DOUBLE_AS_LONG_BITS_opcode:
+ result = doubleAsLongBits(s);
+ break;
+ case INT_2DOUBLE_opcode:
+ result = int2Double(s);
+ break;
+ case INT_2BYTE_opcode:
+ result = int2Byte(s);
+ break;
+ case INT_2USHORT_opcode:
+ result = int2UShort(s);
+ break;
+ case INT_2FLOAT_opcode:
+ result = int2Float(s);
+ break;
+ case INT_2LONG_opcode:
+ result = int2Long(s);
+ break;
+ case INT_2ADDRSigExt_opcode:
+ result = int2AddrSigExt(s);
+ break;
+ case INT_2ADDRZerExt_opcode:
+ result = int2AddrZerExt(s);
+ break;
+ case LONG_2ADDR_opcode:
+ result = long2Addr(s);
+ break;
+ case INT_2SHORT_opcode:
+ result = int2Short(s);
+ break;
+ case INT_BITS_AS_FLOAT_opcode:
+ result = intBitsAsFloat(s);
+ break;
+ case ADDR_2INT_opcode:
+ result = addr2Int(s);
+ break;
+ case ADDR_2LONG_opcode:
+ result = addr2Long(s);
+ break;
+ case FLOAT_2DOUBLE_opcode:
+ result = float2Double(s);
+ break;
+ case FLOAT_2INT_opcode:
+ result = float2Int(s);
+ break;
+ case FLOAT_2LONG_opcode:
+ result = float2Long(s);
+ break;
+ case FLOAT_AS_INT_BITS_opcode:
+ result = floatAsIntBits(s);
+ break;
+ case LONG_2FLOAT_opcode:
+ result = long2Float(s);
+ break;
+ case LONG_2INT_opcode:
+ result = long2Int(s);
+ break;
+ case LONG_2DOUBLE_opcode:
+ result = long2Double(s);
+ break;
+ case LONG_BITS_AS_DOUBLE_opcode:
+ result = longBitsAsDouble(s);
+ break;
+ ////////////////////
+ // Field operations
+ ////////////////////
+ case ARRAYLENGTH_opcode:
+ result = arrayLength(s);
+ break;
+ case BOUNDS_CHECK_opcode:
+ result = boundsCheck(s);
+ break;
+ case CALL_opcode:
+ result = call(s);
+ break;
+ case GETFIELD_opcode:
+ result = getField(s);
+ break;
+ case GET_OBJ_TIB_opcode:
+ result = getObjTib(s);
+ break;
+ case GET_CLASS_TIB_opcode:
+ result = getClassTib(s);
+ break;
+ case GET_TYPE_FROM_TIB_opcode:
+ result = getTypeFromTib(s);
+ break;
+ case GET_ARRAY_ELEMENT_TIB_FROM_TIB_opcode:
+ result = getArrayElementTibFromTib(s);
+ break;
+ case GET_SUPERCLASS_IDS_FROM_TIB_opcode:
+ result = getSuperclassIdsFromTib(s);
+ break;
+ case GET_DOES_IMPLEMENT_FROM_TIB_opcode:
+ result = getDoesImplementFromTib(s);
+ break;
+ case REF_LOAD_opcode:
+ result = refLoad(s);
+ break;
+ default:
+ result = DefUseEffect.UNCHANGED;
+ }
+ if (VM.VerifyAssertions) {
+ switch (result) {
+ case MOVE_FOLDED:
+ // Check move has constant RHS
+ VM._assert(Move.conforms(s) && (Move.getVal(s) instanceof OPT_ConstantOperand),
+ "RHS of move " +
+ s +
+ " should be constant during simplification of " +
+ OPT_OperatorNames.operatorName[opcode]);
+ break;
+ case MOVE_REDUCED:
+ // Check move has non-constant RHS
+ VM._assert(Move.conforms(s) && !(Move.getVal(s) instanceof OPT_ConstantOperand),
+ "RHS of move " +
+ s +
+ " shouldn't be constant during simplification of " +
+ OPT_OperatorNames.operatorName[opcode]);
+ break;
+ default:
+ // Nothing to check
+ }
+ }
+ return result;
+ }
+
+ private static DefUseEffect guardCombine(OPT_Instruction s) {
+ OPT_Operand op1 = Binary.getVal1(s);
+ OPT_Operand op2 = Binary.getVal2(s);
+ if (op1.similar(op2) || (op2 instanceof OPT_TrueGuardOperand)) {
+ Move.mutate(s, GUARD_MOVE, Binary.getClearResult(s), op1);
+ if (op1 instanceof OPT_TrueGuardOperand) {
+ // BOTH true guards: FOLD
+ return DefUseEffect.MOVE_FOLDED;
+ } else {
+ // ONLY OP2 IS TrueGuard: MOVE REDUCE
+ return DefUseEffect.MOVE_REDUCED;
+ }
+ } else if (op1 instanceof OPT_TrueGuardOperand) {
+ // ONLY OP1 IS TrueGuard: MOVE REDUCE
+ Move.mutate(s, GUARD_MOVE, Binary.getClearResult(s), op2);
+ return DefUseEffect.MOVE_REDUCED;
+ } else {
+ return DefUseEffect.UNCHANGED;
+ }
+ }
+
+ private static DefUseEffect trapIf(OPT_Instruction s) {
+ {
+ OPT_Operand op1 = TrapIf.getVal1(s);
+ OPT_Operand op2 = TrapIf.getVal2(s);
+ if (op1.isConstant()) {
+ if (op2.isConstant()) {
+ int willTrap = TrapIf.getCond(s).evaluate(op1, op2);
+ if (willTrap == OPT_ConditionOperand.TRUE) {
+ Trap.mutate(s, TRAP, TrapIf.getClearGuardResult(s), TrapIf.getClearTCode(s));
+ return DefUseEffect.TRAP_REDUCED;
+ } else if (willTrap == OPT_ConditionOperand.FALSE) {
+ Move.mutate(s, GUARD_MOVE, TrapIf.getClearGuardResult(s), TG());
+ return DefUseEffect.MOVE_FOLDED;
+ }
+ } else {
+ // canonicalize
+ TrapIf.mutate(s,
+ TRAP_IF,
+ TrapIf.getClearGuardResult(s),
+ TrapIf.getClearVal2(s),
+ TrapIf.getClearVal1(s),
+ TrapIf.getClearCond(s).flipOperands(),
+ TrapIf.getClearTCode(s));
+ }
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect nullCheck(OPT_Instruction s) {
+ OPT_Operand ref = NullCheck.getRef(s);
+ if (ref.isNullConstant() || (ref.isAddressConstant() && ref.asAddressConstant().value.isZero())) {
+ Trap.mutate(s, TRAP, NullCheck.getClearGuardResult(s), OPT_TrapCodeOperand.NullPtr());
+ return DefUseEffect.TRAP_REDUCED;
+ } else if (ref.isConstant()) {
+ // object, string, class or non-null address constant
+
+ // Make the slightly suspect assumption that all non-zero address
+ // constants are actually valid pointers. Not necessarily true,
+ // but unclear what else we can do.
+ Move.mutate(s, GUARD_MOVE, NullCheck.getClearGuardResult(s), TG());
+ return DefUseEffect.MOVE_FOLDED;
+ } else {
+ return DefUseEffect.UNCHANGED;
+ }
+ }
+
+ private static DefUseEffect intZeroCheck(OPT_Instruction s) {
+ {
+ OPT_Operand op = ZeroCheck.getValue(s);
+ if (op.isIntConstant()) {
+ int val = op.asIntConstant().value;
+ if (val == 0) {
+ Trap.mutate(s, TRAP, ZeroCheck.getClearGuardResult(s), OPT_TrapCodeOperand.DivByZero());
+ return DefUseEffect.TRAP_REDUCED;
+ } else {
+ Move.mutate(s, GUARD_MOVE, ZeroCheck.getClearGuardResult(s), TG());
+ return DefUseEffect.MOVE_FOLDED;
+ }
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect longZeroCheck(OPT_Instruction s) {
+ {
+ OPT_Operand op = ZeroCheck.getValue(s);
+ if (op.isLongConstant()) {
+ long val = op.asLongConstant().value;
+ if (val == 0L) {
+ Trap.mutate(s, TRAP, ZeroCheck.getClearGuardResult(s), OPT_TrapCodeOperand.DivByZero());
+ return DefUseEffect.TRAP_REDUCED;
+ } else {
+ Move.mutate(s, GUARD_MOVE, ZeroCheck.getClearGuardResult(s), TG());
+ return DefUseEffect.MOVE_FOLDED;
+ }
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+ private static DefUseEffect checkcast(OPT_Instruction s) {
+ OPT_Operand ref = TypeCheck.getRef(s);
+ if (ref.isNullConstant()) {
+ Empty.mutate(s, NOP);
+ return DefUseEffect.REDUCED;
+ } else if (ref.isConstant()) {
+ s.operator = CHECKCAST_NOTNULL;
+ return checkcastNotNull(s);
+ } else {
+ VM_TypeReference lhsType = TypeCheck.getType(s).getTypeRef();
+ VM_TypeReference rhsType = ref.getType();
+ byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType);
+ if (ans == OPT_Constants.YES) {
+ Empty.mutate(s, NOP);
+ return DefUseEffect.REDUCED;
+ } else {
+ // NOTE: OPT_Constants.NO can't help us because (T)null always succeeds
+ return DefUseEffect.UNCHANGED;
+ }
+ }
+ }
+
+ private static DefUseEffect checkcastNotNull(OPT_Instruction s) {
+ OPT_Operand ref = TypeCheck.getRef(s);
+ VM_TypeReference lhsType = TypeCheck.getType(s).getTypeRef();
+ VM_TypeReference rhsType = ref.getType();
+ byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType);
+ if (ans == OPT_Constants.YES) {
+ Empty.mutate(s, NOP);
+ return DefUseEffect.REDUCED;
+ } else if (ans == OPT_Constants.NO) {
+ VM_Type rType = rhsType.peekType();
+ if (rType != null && rType.isClassType() && rType.asClass().isFinal()) {
+ // only final (or precise) rhs types can be optimized since rhsType may be conservative
+ Trap.mutate(s, TRAP, null, OPT_TrapCodeOperand.CheckCast());
+ return DefUseEffect.TRAP_REDUCED;
+ } else {
+ return DefUseEffect.UNCHANGED;
+ }
+ } else {
+ return DefUseEffect.UNCHANGED;
+ }
+ }
+ private static DefUseEffect instanceOf(OPT_Instruction s) {
+ OPT_Operand ref = InstanceOf.getRef(s);
+ if (ref.isNullConstant()) {
+ Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0));
+ return DefUseEffect.MOVE_FOLDED;
+ } else if (ref.isConstant()) {
+ s.operator = INSTANCEOF_NOTNULL;
+ return instanceOfNotNull(s);
+ } else {
+ VM_TypeReference lhsType = InstanceOf.getType(s).getTypeRef();
+ VM_TypeReference rhsType = ref.getType();
+ byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType);
+ // NOTE: OPT_Constants.YES doesn't help because ref may be null and null instanceof T is false
+ if (ans == OPT_Constants.NO) {
+ VM_Type rType = rhsType.peekType();
+ if (rType != null && rType.isClassType() && rType.asClass().isFinal()) {
+ // only final (or precise) rhs types can be optimized since rhsType may be conservative
+ Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0));
+ return DefUseEffect.MOVE_FOLDED;
+ } else {
+ return DefUseEffect.UNCHANGED;
+ }
+ } else {
+ return DefUseEffect.UNCHANGED;
+ }
+ }
+ }
+
+ private static DefUseEffect instanceOfNotNull(OPT_Instruction s) {
+ {
+ OPT_Operand ref = InstanceOf.getRef(s);
+ VM_TypeReference lhsType = InstanceOf.getType(s).getTypeRef();
+ VM_TypeReference rhsType = ref.getType();
+ byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType);
+ if (ans == OPT_Constants.YES) {
+ Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(1));
+ return DefUseEffect.MOVE_FOLDED;
+ } else if (ans == OPT_Constants.NO) {
+ VM_Type rType = rhsType.peekType();
+ if (rType != null && rType.isClassType() && rType.asClass().isFinal()) {
+ // only final (or precise) rhs types can be optimized since rhsType may be conservative
+ Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0));
+ return DefUseEffect.MOVE_FOLDED;
+ }
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect objarrayStoreCheck(OPT_Instruction s) {
+ OPT_Operand val = StoreCheck.getVal(s);
+ if (val.isNullConstant()) {
+ // Writing null into an array is trivially safe
+ Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s));
+ return DefUseEffect.MOVE_REDUCED;
+ } else {
+ OPT_Operand ref = StoreCheck.getRef(s);
+ VM_TypeReference arrayTypeRef = ref.getType();
+ VM_Type typeOfIMElem = arrayTypeRef.getInnermostElementType().peekType();
+ if (typeOfIMElem != null) {
+ VM_Type typeOfVal = val.getType().peekType();
+ if ((typeOfIMElem == typeOfVal) && (typeOfIMElem.isPrimitiveType() || typeOfIMElem.asClass().isFinal())) {
+ // Writing something of a final type to an array of that
+ // final type is safe
+ Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s));
+ return DefUseEffect.MOVE_REDUCED;
+ }
+ }
+ if (ref.isConstant() && (arrayTypeRef == VM_TypeReference.JavaLangObjectArray)) {
+ // We know this to be an array of objects so any store must
+ // be safe
+ Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s));
+ return DefUseEffect.MOVE_REDUCED;
+ }
+ if (val.isConstant() && ref.isConstant()) {
+ // writing a constant value into a constant array
+ byte ans = OPT_ClassLoaderProxy.includesType(arrayTypeRef.getArrayElementType(), val.getType());
+ if (ans == OPT_Constants.YES) {
+ // all stores should succeed
+ Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s));
+ return DefUseEffect.MOVE_REDUCED;
+ } else if (ans == OPT_Constants.NO) {
+ // all stores will fail
+ Trap.mutate(s, TRAP, StoreCheck.getClearGuardResult(s), OPT_TrapCodeOperand.StoreCheck());
+ return DefUseEffect.TRAP_REDUCED;
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+ }
+
+ private static DefUseEffect objarrayStoreCheckNotNull(OPT_Instruction s) {
+ OPT_Operand val = StoreCheck.getVal(s);
+ OPT_Operand ref = StoreCheck.getRef(s);
+ VM_TypeReference arrayTypeRef = ref.getType();
+ VM_Type typeOfIMElem = arrayTypeRef.getInnermostElementType().peekType();
+ if (typeOfIMElem != null) {
+ VM_Type typeOfVal = val.getType().peekType();
+ if ((typeOfIMElem == typeOfVal) && (typeOfIMElem.isPrimitiveType() || typeOfIMElem.asClass().isFinal())) {
+ // Writing something of a final type to an array of that
+ // final type is safe
+ Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s));
+ return DefUseEffect.MOVE_REDUCED;
+ }
+ }
+ if (ref.isConstant() && (arrayTypeRef == VM_TypeReference.JavaLangObjectArray)) {
+ // We know this to be an array of objects so any store must
+ // be safe
+ Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s));
+ return DefUseEffect.MOVE_REDUCED;
+ }
+ if (val.isConstant() && ref.isConstant()) {
+ // writing a constant value into a constant array
+ byte ans = OPT_ClassLoaderProxy.includesType(arrayTypeRef.getArrayElementType(), val.getType());
+ if (ans == OPT_Constants.YES) {
+ // all stores should succeed
+ Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s));
+ return DefUseEffect.MOVE_REDUCED;
+ } else if (ans == OPT_Constants.NO) {
+ // all stores will fail
+ Trap.mutate(s, TRAP, StoreCheck.getClearGuardResult(s), OPT_TrapCodeOperand.StoreCheck());
+ return DefUseEffect.TRAP_REDUCED;
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect mustImplementInterface(OPT_Instruction s) {
+ OPT_Operand ref = TypeCheck.getRef(s);
+ if (ref.isNullConstant()) {
+ // Possible sitatution from constant propagation. This operation
+ // is really a nop as a null_check should have happened already
+ Trap.mutate(s, TRAP, null, OPT_TrapCodeOperand.NullPtr());
+ return DefUseEffect.TRAP_REDUCED;
+ } else {
+ VM_TypeReference lhsType = TypeCheck.getType(s).getTypeRef(); // the interface that must be implemented
+ VM_TypeReference rhsType = ref.getType(); // our type
+ byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType);
+ if (ans == OPT_Constants.YES) {
+ Empty.mutate(s, NOP);
+ return DefUseEffect.REDUCED;
+ } else if (ans == OPT_Constants.NO) {
+ VM_Type rType = rhsType.peekType();
+ if (rType != null && rType.isClassType() && rType.asClass().isFinal()) {
+ // only final (or precise) rhs types can be optimized since rhsType may be conservative
+ Trap.mutate(s, TRAP, null, OPT_TrapCodeOperand.MustImplement());
+ return DefUseEffect.TRAP_REDUCED;
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+ }
+
+ private static DefUseEffect intCondMove(OPT_Instruction s) {
+ {
+ OPT_Operand val1 = CondMove.getVal1(s);
+ OPT_Operand val2 = CondMove.getVal2(s);
+ int cond = CondMove.getCond(s).evaluate(val1, val2);
+ if (cond != OPT_ConditionOperand.UNKNOWN) {
+ // BOTH CONSTANTS OR SIMILAR: FOLD
+ OPT_Operand val =
+ (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s);
+ Move.mutate(s, INT_MOVE, CondMove.getClearResult(s), val);
+ return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ if (val1.isConstant() && !val2.isConstant()) {
+ // Canonicalize by switching operands and fliping code.
+ OPT_Operand tmp = CondMove.getClearVal1(s);
+ CondMove.setVal1(s, CondMove.getClearVal2(s));
+ CondMove.setVal2(s, tmp);
+ CondMove.getCond(s).flipOperands();
+ }
+ OPT_Operand tv = CondMove.getTrueValue(s);
+ OPT_Operand fv = CondMove.getFalseValue(s);
+ if (tv.similar(fv)) {
+ Move.mutate(s, INT_MOVE, CondMove.getClearResult(s), tv);
+ return tv.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ if (tv.isIntConstant() && fv.isIntConstant() && !CondMove.getCond(s).isFLOATINGPOINT()) {
+ int itv = tv.asIntConstant().value;
+ int ifv = fv.asIntConstant().value;
+ OPT_Operator op = null;
+ if (val1.isLong()) {
+ op = BOOLEAN_CMP_LONG;
+ } else if (val1.isFloat()) {
+ op = BOOLEAN_CMP_FLOAT;
+ } else if (val1.isDouble()) {
+ op = BOOLEAN_CMP_DOUBLE;
+ } else {
+ op = BOOLEAN_CMP_INT;
+ }
+ if (itv == 1 && ifv == 0) {
+ BooleanCmp.mutate(s,
+ op,
+ CondMove.getClearResult(s),
+ CondMove.getClearVal1(s),
+ CondMove.getClearVal2(s),
+ CondMove.getClearCond(s),
+ new OPT_BranchProfileOperand());
+ return DefUseEffect.REDUCED;
+ }
+ if (itv == 0 && ifv == 1) {
+ BooleanCmp.mutate(s,
+ op,
+ CondMove.getClearResult(s),
+ CondMove.getClearVal1(s),
+ CondMove.getClearVal2(s),
+ CondMove.getClearCond(s).flipCode(),
+ new OPT_BranchProfileOperand());
+ return DefUseEffect.REDUCED;
+ }
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect longCondMove(OPT_Instruction s) {
+ {
+ OPT_Operand val1 = CondMove.getVal1(s);
+ OPT_Operand val2 = CondMove.getVal2(s);
+ int cond = CondMove.getCond(s).evaluate(val1, val2);
+ if (cond != OPT_ConditionOperand.UNKNOWN) {
+ // BOTH CONSTANTS OR SIMILAR: FOLD
+ OPT_Operand val =
+ (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s);
+ Move.mutate(s, LONG_MOVE, CondMove.getClearResult(s), val);
+ return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ if (val1.isConstant() && !val2.isConstant()) {
+ // Canonicalize by switching operands and fliping code.
+ OPT_Operand tmp = CondMove.getClearVal1(s);
+ CondMove.setVal1(s, CondMove.getClearVal2(s));
+ CondMove.setVal2(s, tmp);
+ CondMove.getCond(s).flipOperands();
+ }
+ OPT_Operand tv = CondMove.getTrueValue(s);
+ OPT_Operand fv = CondMove.getFalseValue(s);
+ if (tv.similar(fv)) {
+ Move.mutate(s, LONG_MOVE, CondMove.getClearResult(s), tv);
+ return tv.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ if (tv.isLongConstant() && fv.isLongConstant() && !CondMove.getCond(s).isFLOATINGPOINT()) {
+ long itv = tv.asLongConstant().value;
+ long ifv = fv.asLongConstant().value;
+ OPT_Operator op = null;
+ if (val1.isLong()) {
+ op = BOOLEAN_CMP_LONG;
+ } else if (val1.isFloat()) {
+ op = BOOLEAN_CMP_FLOAT;
+ } else if (val1.isDouble()) {
+ op = BOOLEAN_CMP_DOUBLE;
+ } else {
+ op = BOOLEAN_CMP_INT;
+ }
+ if (itv == 1 && ifv == 0) {
+ BooleanCmp.mutate(s,
+ op,
+ CondMove.getClearResult(s),
+ CondMove.getClearVal1(s),
+ CondMove.getClearVal2(s),
+ CondMove.getClearCond(s),
+ new OPT_BranchProfileOperand());
+ return DefUseEffect.REDUCED;
+ }
+ if (itv == 0 && ifv == 1) {
+ BooleanCmp.mutate(s,
+ op,
+ CondMove.getClearResult(s),
+ CondMove.getClearVal1(s),
+ CondMove.getClearVal2(s),
+ CondMove.getClearCond(s).flipCode(),
+ new OPT_BranchProfileOperand());
+ return DefUseEffect.REDUCED;
+ }
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect floatCondMove(OPT_Instruction s) {
+ {
+ OPT_Operand val1 = CondMove.getVal1(s);
+ OPT_Operand val2 = CondMove.getVal2(s);
+ int cond = CondMove.getCond(s).evaluate(val1, val2);
+ if (cond != OPT_ConditionOperand.UNKNOWN) {
+ // BOTH CONSTANTS OR SIMILAR: FOLD
+ OPT_Operand val =
+ (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s);
+ Move.mutate(s, FLOAT_MOVE, CondMove.getClearResult(s), val);
+ return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ if (val1.isConstant() && !val2.isConstant()) {
+ // Canonicalize by switching operands and fliping code.
+ OPT_Operand tmp = CondMove.getClearVal1(s);
+ CondMove.setVal1(s, CondMove.getClearVal2(s));
+ CondMove.setVal2(s, tmp);
+ CondMove.getCond(s).flipOperands();
+ }
+ OPT_Operand tv = CondMove.getTrueValue(s);
+ OPT_Operand fv = CondMove.getFalseValue(s);
+ if (tv.similar(fv)) {
+ Move.mutate(s, FLOAT_MOVE, CondMove.getClearResult(s), tv);
+ return tv.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect doubleCondMove(OPT_Instruction s) {
+ {
+ OPT_Operand val1 = CondMove.getVal1(s);
+ OPT_Operand val2 = CondMove.getVal2(s);
+ int cond = CondMove.getCond(s).evaluate(val1, val2);
+ if (cond != OPT_ConditionOperand.UNKNOWN) {
+ // BOTH CONSTANTS OR SIMILAR: FOLD
+ OPT_Operand val =
+ (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s);
+ Move.mutate(s, DOUBLE_MOVE, CondMove.getClearResult(s), val);
+ return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ if (val1.isConstant() && !val2.isConstant()) {
+ // Canonicalize by switching operands and fliping code.
+ OPT_Operand tmp = CondMove.getClearVal1(s);
+ CondMove.setVal1(s, CondMove.getClearVal2(s));
+ CondMove.setVal2(s, tmp);
+ CondMove.getCond(s).flipOperands();
+ }
+ OPT_Operand tv = CondMove.getTrueValue(s);
+ OPT_Operand fv = CondMove.getFalseValue(s);
+ if (tv.similar(fv)) {
+ Move.mutate(s, DOUBLE_MOVE, CondMove.getClearResult(s), tv);
+ return tv.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect refCondMove(OPT_Instruction s) {
+ {
+ OPT_Operand val1 = CondMove.getVal1(s);
+ if (val1.isConstant()) {
+ OPT_Operand val2 = CondMove.getVal2(s);
+ if (val2.isConstant()) {
+ // BOTH CONSTANTS: FOLD
+ int cond = CondMove.getCond(s).evaluate(val1, val2);
+ if (cond != OPT_ConditionOperand.UNKNOWN) {
+ OPT_Operand val =
+ (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s);
+ Move.mutate(s, REF_MOVE, CondMove.getClearResult(s), val);
+ return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ } else {
+ // Canonicalize by switching operands and fliping code.
+ OPT_Operand tmp = CondMove.getClearVal1(s);
+ CondMove.setVal1(s, CondMove.getClearVal2(s));
+ CondMove.setVal2(s, tmp);
+ CondMove.getCond(s).flipOperands();
+ }
+ }
+ if (CondMove.getTrueValue(s).similar(CondMove.getFalseValue(s))) {
+ OPT_Operand val = CondMove.getClearTrueValue(s);
+ Move.mutate(s, REF_MOVE, CondMove.getClearResult(s), val);
+ return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect guardCondMove(OPT_Instruction s) {
+ {
+ OPT_Operand val1 = CondMove.getVal1(s);
+ if (val1.isConstant()) {
+ OPT_Operand val2 = CondMove.getVal2(s);
+ if (val2.isConstant()) {
+ // BOTH CONSTANTS: FOLD
+ int cond = CondMove.getCond(s).evaluate(val1, val2);
+ if (cond == OPT_ConditionOperand.UNKNOWN) {
+ OPT_Operand val =
+ (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s);
+ Move.mutate(s, GUARD_MOVE, CondMove.getClearResult(s), val);
+ return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ } else {
+ // Canonicalize by switching operands and fliping code.
+ OPT_Operand tmp = CondMove.getClearVal1(s);
+ CondMove.setVal1(s, CondMove.getClearVal2(s));
+ CondMove.setVal2(s, tmp);
+ CondMove.getCond(s).flipOperands();
+ }
+ }
+ if (CondMove.getTrueValue(s).similar(CondMove.getFalseValue(s))) {
+ OPT_Operand val = CondMove.getClearTrueValue(s);
+ Move.mutate(s, GUARD_MOVE, CondMove.getClearResult(s), val);
+ return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect booleanNot(OPT_Instruction s) {
+ if (CF_INT) {
+ OPT_Operand op = Unary.getVal(s);
+ if (op.isIntConstant()) {
+ // CONSTANT: FOLD
+ int val = op.asIntConstant().value;
+ if (val == 0) {
+ Move.mutate(s, INT_MOVE, Unary.getClearResult(s), IC(1));
+ } else {
+ Move.mutate(s, INT_MOVE, Unary.getClearResult(s), IC(0));
+ }
+ return DefUseEffect.MOVE_FOLDED;
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect booleanCmp2IntOr(OPT_Instruction s) {
+ if (CF_INT) {
+ OPT_Operand op1 = BooleanCmp2.getVal1(s);
+ OPT_Operand op2 = BooleanCmp2.getVal2(s);
+ if (op1.isConstant()) {
+ if (op2.isConstant()) {
+ // 1st 2 operands are constants, can fold if result is true
+ int cond1 = BooleanCmp2.getCond1(s).evaluate(op1, op2);
+ if (cond1 == OPT_ConditionOperand.TRUE) {
+ Move.mutate(s, REF_MOVE, BooleanCmp2.getResult(s), IC(1));
+ return DefUseEffect.MOVE_FOLDED;
+ } else if (cond1 == OPT_ConditionOperand.FALSE) {
+ BooleanCmp.mutate(s, BOOLEAN_CMP_INT, BooleanCmp2.getResult(s),
+ BooleanCmp2.getVal3(s), BooleanCmp2.getVal4(s), BooleanCmp2
+ .getCond2(s), BooleanCmp2.getBranchProfile2(s));
+ DefUseEffect result = booleanCmpInt(s);
+ return (result == DefUseEffect.UNCHANGED) ? DefUseEffect.REDUCED
+ : result;
+ }
+ }
+ }
+ OPT_Operand op3 = BooleanCmp2.getVal3(s);
+ OPT_Operand op4 = BooleanCmp2.getVal4(s);
+ if (op3.isConstant()) {
+ if (op4.isConstant()) {
+ // 3rd and 4th operands are constants, can fold if result is true
+ int cond2 = BooleanCmp2.getCond1(s).evaluate(op3, op4);
+ if (cond2 == OPT_ConditionOperand.TRUE) {
+ Move.mutate(s, REF_MOVE, BooleanCmp2.getResult(s), IC(1));
+ return DefUseEffect.MOVE_FOLDED;
+ } else if (cond2 == OPT_ConditionOperand.FALSE) {
+ BooleanCmp.mutate(s, BOOLEAN_CMP_INT, BooleanCmp2.getResult(s),
+ BooleanCmp2.getVal1(s), BooleanCmp2.getVal2(s), BooleanCmp2
+ .getCond1(s), BooleanCmp2.getBranchProfile1(s));
+ DefUseEffect result = booleanCmpInt(s);
+ return (result == DefUseEffect.UNCHANGED) ? DefUseEffect.REDUCED
+ : result;
+ }
+ }
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect booleanCmpInt(OPT_Instruction s) {
+ if (CF_INT) {
+ OPT_Operand op1 = BooleanCmp.getVal1(s);
+ OPT_Operand op2 = BooleanCmp.getVal2(s);
+ if (op1.isConstant()) {
+ if (op2.isConstant()) {
+ // BOTH CONSTANTS: FOLD
+ int cond = BooleanCmp.getCond(s).evaluate(op1, op2);
+ if (cond != OPT_ConditionOperand.UNKNOWN) {
+ Move.mutate(s, INT_MOVE, BooleanCmp.getResult(s), (cond == OPT_ConditionOperand.TRUE) ? IC(1) : IC(0));
+ return DefUseEffect.MOVE_FOLDED;
+ }
+ } else {
+ // Canonicalize by switching operands and fliping code.
+ BooleanCmp.setVal1(s, op2);
+ BooleanCmp.setVal2(s, op1);
+ BooleanCmp.getCond(s).flipOperands();
+ op2 = op1;
+ op1 = BooleanCmp.getVal1(s);
+ }
+ }
+ // try to fold boolean compares involving one boolean constant
+ // e.g.: x = (y == true) ? true : false ==> x = y
+ // or: x = (y == false) ? true : false ==> x = !y
+ if (op1.getType().isBooleanType() && op2.isConstant()) {
+ OPT_ConditionOperand cond = BooleanCmp.getCond(s);
+ int op2value = op2.asIntConstant().value;
+ if ((cond.isNOT_EQUAL() && (op2value == 0)) || (cond.isEQUAL() && (op2value == 1))) {
+ Move.mutate(s, INT_MOVE, BooleanCmp.getResult(s), op1);
+ return DefUseEffect.MOVE_REDUCED;
+ } else if ((cond.isEQUAL() && (op2value == 0)) || (cond.isNOT_EQUAL() && (op2value == 1))) {
+ Unary.mutate(s, BOOLEAN_NOT, BooleanCmp.getResult(s), op1);
+ return DefUseEffect.REDUCED;
+ }
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect booleanCmpAddr(OPT_Instruction s) {
+ if (CF_ADDR) {
+ OPT_Operand op1 = BooleanCmp.getVal1(s);
+ OPT_Operand op2 = BooleanCmp.getVal2(s);
+ if (op1.isConstant()) {
+ if (op2.isConstant()) {
+ // BOTH CONSTANTS: FOLD
+ int cond = BooleanCmp.getCond(s).evaluate(op1, op2);
+ if (cond != OPT_ConditionOperand.UNKNOWN) {
+ Move.mutate(s, REF_MOVE, BooleanCmp.getResult(s), (cond == OPT_ConditionOperand.TRUE) ? IC(1) : IC(0));
+ return DefUseEffect.MOVE_FOLDED;
+ }
+ } else {
+ // Canonicalize by switching operands and fliping code.
+ OPT_Operand tmp = BooleanCmp.getClearVal1(s);
+ BooleanCmp.setVal1(s, BooleanCmp.getClearVal2(s));
+ BooleanCmp.setVal2(s, tmp);
+ BooleanCmp.getCond(s).flipOperands();
+ }
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect intAdd(OPT_Instruction s) {
+ if (CF_INT) {
+ canonicalizeCommutativeOperator(s);
+ OPT_Operand op2 = Binary.getVal2(s);
+ if (op2.isIntConstant()) {
+ int val2 = op2.asIntConstant().value;
+ OPT_Operand op1 = Binary.getVal1(s);
+ if (op1.isIntConstant()) {
+ // BOTH CONSTANTS: FOLD
+ int val1 = op1.asIntConstant().value;
+ Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 + val2));
+ return DefUseEffect.MOVE_FOLDED;
+ } else {
+ // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
+ if (val2 == 0) {
+ Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary.getClearVal1(s));
+ return DefUseEffect.MOVE_REDUCED;
+ }
+ }
+ } else {
+ OPT_Operand op1 = Binary.getVal1(s);
+ if (op1.similar(op2)) {
+ // Adding something to itself is the same as a multiply by 2 so
+ // canonicalize as a shift left
+ Binary.mutate(s, INT_SHL, Binary.getClearResult(s), op1, IC(1));
+ return DefUseEffect.UNCHANGED;
+ }
+ }
+ }
+ return DefUseEffect.UNCHANGED;
+ }
+
+ private static DefUseEffect intAnd(OPT_Instruction s) {
+ if (CF_INT) {
+ canonicalizeCommutativeOperator(s);
+ OPT_Operand op1 = Binary.getVal1(s);
+ OPT_Operand op2 = Binary.getVal2(s);
+ if (op1.similar(op2)) {
+ // THE SAME OPERAND: x & x == x
+ Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary.getClearVal1(s));
+ return op1.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED;
+ }
+ if (op2.isIntConstant()) {
+ int val2 = op2.asIntConstant().value;
+ if (op1.isIntConstant()) {
+ // BOTH CONSTANTS: FOLD
+ int val1 = op1.asIntConstant().value;
+ Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 & val2));
+ return DefUseEffect.MOVE_FOLDED;
+ } else {
+ // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
+ if (val2 == 0) { // x & 0 == 0
+ Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0));
+ return DefUseEffect.MOVE_FOLDED;
...
[truncated message content] |
|
From: <mic...@us...> - 2007-08-07 09:39:58
|
Revision: 159
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=159&view=rev
Author: michael_baer
Date: 2007-08-07 02:40:00 -0700 (Tue, 07 Aug 2007)
Log Message:
-----------
Changes for most recent ARM version
Modified Paths:
--------------
rvmroot.patch
Modified: rvmroot.patch
===================================================================
--- rvmroot.patch 2007-08-06 15:25:12 UTC (rev 158)
+++ rvmroot.patch 2007-08-07 09:40:00 UTC (rev 159)
@@ -142,9 +142,9 @@
--- build/primordials/RVM_OPT.txt (revision 12759)
+++ build/primordials/RVM_OPT.txt (working copy)
@@ -16,3 +16,15 @@
- Ljava/io/FileReader;
Ljava/io/PushbackReader;
[Lorg/jikesrvm/compilers/opt/OPT_Simplifier$DefUseEffect;
+ [Lorg/jikesrvm/compilers/opt/ir/OPT_Operator;
+[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$ELF_Identity$AddressSize;
+[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$ELF_Identity$ByteOrder;
+[Lorg/binarytranslator/generic/os/loader/elf/ELF_File$Header$ObjectFileType;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-06 15:25:10
|
Revision: 158
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=158&view=rev
Author: michael_baer
Date: 2007-08-06 08:25:12 -0700 (Mon, 06 Aug 2007)
Log Message:
-----------
- Made optimizations by profiling optional
Modified Paths:
--------------
src/org/binarytranslator/DBT_Options.java
src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
src/org/binarytranslator/generic/decoder/CodeTranslator.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-06 15:23:44 UTC (rev 157)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-06 15:25:12 UTC (rev 158)
@@ -93,6 +93,9 @@
/** Just a temporary variable for testing. It describes, when the staged emulation controller switches from interpretation to translation. */
public static int minTraceValue = 20;
+ /** Just a temporary variable for testing. It describes, if the translated program shall be optimized using profiling information.. */
+ public static boolean optimizeTranslationByProfiling = false;
+
/** Print debug information during the translation of instructions. */
public static boolean debugTranslation = true;
@@ -198,8 +201,9 @@
saveProfileToFile = value;
} else if (key.equalsIgnoreCase("minTraceValue")) {
minTraceValue = Integer.parseInt(value);
+ } else if (key.equalsIgnoreCase("optimizeTranslation")) {
+ optimizeTranslationByProfiling = Boolean.parseBoolean(value);
}
-
else {
throw new Error("Unknown DBT option: " + key);
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-06 15:23:44 UTC (rev 157)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-06 15:25:12 UTC (rev 158)
@@ -756,23 +756,31 @@
arm2ir.getCurrentBlock().insertOut(condBlock);
//Query the branch profile to get the probability that this instruction is going to get executed
- float skipProbability = ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4));
OPT_BranchProfileOperand profileOperand;
- if (skipProbability == -1 || skipProbability == 0.5f) {
- profileOperand = new OPT_BranchProfileOperand();
+ if (DBT_Options.optimizeTranslationByProfiling) {
+ float skipProbability = ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4));
+
+ if (skipProbability == -1 || skipProbability == 0.5f) {
+ profileOperand = new OPT_BranchProfileOperand();
+ }
+ else if (skipProbability > 0.8f) {
+ profileOperand = OPT_BranchProfileOperand.always();
+ condBlock.setInfrequent();
+ }
+ else if (skipProbability > 0.5f) {
+ profileOperand = OPT_BranchProfileOperand.likely();
+ condBlock.setInfrequent();
+ }
+ else if (skipProbability < 0.2f) {
+ profileOperand = OPT_BranchProfileOperand.never();
+ }
+ else {
+ profileOperand = OPT_BranchProfileOperand.unlikely();
+ }
}
- else if (skipProbability > 0.8f) {
- profileOperand = OPT_BranchProfileOperand.always();
- }
- else if (skipProbability > 0.5f) {
- profileOperand = OPT_BranchProfileOperand.likely();
- }
- else if (skipProbability < 0.2f) {
- profileOperand = OPT_BranchProfileOperand.never();
- }
else {
- profileOperand = OPT_BranchProfileOperand.unlikely();
+ profileOperand = new OPT_BranchProfileOperand();
}
switch (condition) {
@@ -2208,8 +2216,22 @@
//rotation = (address & 0x3) * 8
arm2ir.appendInstruction(Binary.create(INT_AND, rotation, address.copy(), new OPT_IntConstantOperand(0x3)));
+
+ OPT_BasicBlock remainderBlock = arm2ir.createBlockAfterCurrent();
+ OPT_BasicBlock rotationBlock = arm2ir.createBlockAfterCurrent();
+
+ //do we actually have to perform the rotation?
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), rotation.copy(), new OPT_IntConstantOperand(0), OPT_ConditionOperand.NOT_EQUAL(), rotationBlock.makeJumpTarget(), OPT_BranchProfileOperand.never()));
+ arm2ir.appendInstruction(Goto.create(GOTO, remainderBlock.makeJumpTarget()));
+
+ //in case we are performing the rotation...
+ arm2ir.setCurrentBlock(rotationBlock);
+ rotationBlock.setInfrequent();
arm2ir.appendInstruction(Binary.create(INT_SHL, rotation.copyRO(), rotation.copy(), new OPT_IntConstantOperand(3)));
arm2ir.appendRotateRight(value.copyRO(), value.copy(), rotation.copy());
+
+ //continue with the remainder of the instruction
+ arm2ir.setCurrentBlock(remainderBlock);
//allow further usage of the memory address
address = adrCopy;
@@ -2284,6 +2306,7 @@
arm2ir.appendBranch(arm2ir.getRegister(i.Rd), lazy, BranchType.INDIRECT_BRANCH);
}
}
+
public Condition getCondition() {
return i.condition;
Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java
===================================================================
--- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-06 15:23:44 UTC (rev 157)
+++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-08-06 15:25:12 UTC (rev 158)
@@ -158,7 +158,7 @@
/**
* This variable is being set by a call to {@link #printTraceAfterCompletion()} and notifies
* the system that the current trace shall be printed, after it has been completed. */
- private boolean requestPrintTrace;
+ private boolean printTraceAfterCompletionRequested;
/** Map to locate HIR basic blocks to re-use translation within a trace */
protected final HashMap<Laziness.Key, OPT_BasicBlock> blockMap;
@@ -248,7 +248,7 @@
* debug purposes.
*/
protected void printTraceAfterCompletion() {
- requestPrintTrace = true;
+ printTraceAfterCompletionRequested = true;
}
/** This is the main loop, which generates the HIR. */
@@ -263,7 +263,10 @@
while (unresolvedDirectBranches.size() > 0 || unresolvedDynamicBranches.size() > 0) {
// Resolve all open direct branches first
- resolveAllDirectBranches();
+ do {
+ resolveAllDirectBranches();
+ }
+ while (unresolvedDirectBranches.size() > 0);
// Resolve unresolved dynamic jumps
resolveAllDynamicBranches();
@@ -276,14 +279,24 @@
eliminateRegisterFills(getUnusedRegisters());
}
- if (requestPrintTrace) {
- requestPrintTrace = false;
+ if (printTraceAfterCompletionRequested) {
+ printTraceAfterCompletionRequested = false;
printNextBlocks(preFillBlock, 50);
}
-
- // TODO: maximizeBasicBlocks()
}
+ /*
+ protected final void maximizeBasicBlocks(OPT_IR ir) {
+ for (OPT_BasicBlock currBB = ir.cfg.firstInCodeOrder(); currBB != null;) {
+ if (currBB.mergeFallThrough(ir)) {
+ // don't advance currBB; it may have a new trivial fallthrough to
+ // swallow
+ } else {
+ currBB = currBB.nextBasicBlockInCodeOrder();
+ }
+ }
+ }*/
+
/**
* Translate a sequence of instructions upto an instruction that doesn't know
* its immediate/default successor. The currentBlock should be an empty basic
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-06 15:23:41
|
Revision: 157
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=157&view=rev
Author: michael_baer
Date: 2007-08-06 08:23:44 -0700 (Mon, 06 Aug 2007)
Log Message:
-----------
- changes to compile with latest RVM
Modified Paths:
--------------
ext/org/jikesrvm/classloader/VM_Member.java
ext/org/jikesrvm/classloader/VM_Method.java
ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java
ext/org/jikesrvm/compilers/opt/ia32/OPT_BURS_Helpers.java
ext/org/jikesrvm/compilers/opt/ir/OPT_BC2IR.java
Modified: ext/org/jikesrvm/classloader/VM_Member.java
===================================================================
--- ext/org/jikesrvm/classloader/VM_Member.java 2007-08-06 14:18:07 UTC (rev 156)
+++ ext/org/jikesrvm/classloader/VM_Member.java 2007-08-06 15:23:44 UTC (rev 157)
@@ -1,29 +1,30 @@
/*
- * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net).
- * The Jikes RVM project is distributed under the Common Public License (CPL).
- * A copy of the license is included in the distribution, and is also
- * available at http://www.opensource.org/licenses/cpl1.0.php
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
*
- * (C) Copyright IBM Corp 2001,2002
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
*/
package org.jikesrvm.classloader;
-import org.jikesrvm.*;
-import org.vmmagic.pragma.*;
+import org.jikesrvm.VM;
+import org.jikesrvm.VM_Constants;
+import org.vmmagic.pragma.Uninterruptible;
import org.vmmagic.unboxed.Offset;
/**
* A field or method of a java class.
- *
- * @author Bowen Alpern
- * @author Dave Grove
- * @author Derek Lieber
*/
public abstract class VM_Member extends VM_AnnotatedElement implements VM_Constants, VM_ClassLoaderConstants {
/** Initial value for a field offset - indicates field not laid out. */
- private static final int NO_OFFSET = Short.MIN_VALUE+1;
-
+ private static final int NO_OFFSET = Short.MIN_VALUE + 1;
+
/**
* The class that declared this member, avaliable by calling
* getDeclaringClass once the class is loaded.
@@ -54,15 +55,14 @@
/**
* NOTE: Only {@link VM_Class} is allowed to create an instance of a VM_Member.
- *
+ *
* @param declaringClass the VM_TypeReference object of the class that declared this member
* @param memRef the canonical memberReference for this member.
* @param modifiers modifiers associated with this member.
* @param signature generic type of this member
* @param annotations array of runtime visible annotations
*/
- protected VM_Member(VM_TypeReference declaringClass, VM_MemberReference memRef,
- short modifiers, VM_Atom signature,
+ protected VM_Member(VM_TypeReference declaringClass, VM_MemberReference memRef, short modifiers, VM_Atom signature,
VM_Annotation[] annotations) {
super(annotations);
this.declaringClass = declaringClass;
@@ -80,34 +80,34 @@
/**
* Class that declared this field or method. Not available before
* the class is loaded.
- */
+ */
@Uninterruptible
public final VM_Class getDeclaringClass() {
- return declaringClass.peekResolvedType().asClass();
+ return declaringClass.peekType().asClass();
}
/**
* Canonical member reference for this member.
- */
+ */
@Uninterruptible
- public final VM_MemberReference getMemberRef() {
+ public final VM_MemberReference getMemberRef() {
return memRef;
}
/**
* Name of this member.
- */
+ */
@Uninterruptible
- public final VM_Atom getName() {
+ public final VM_Atom getName() {
return memRef.getName();
}
/**
* Descriptor for this member.
* something like "I" for a field or "(I)V" for a method.
- */
+ */
@Uninterruptible
- public final VM_Atom getDescriptor() {
+ public final VM_Atom getDescriptor() {
return memRef.getDescriptor();
}
@@ -124,7 +124,7 @@
* and thus may be used to find the member by first finding the member reference.
*/
@Uninterruptible
- public final int getId() {
+ public final int getId() {
return memRef.getId();
}
@@ -132,34 +132,34 @@
* Define hashcode in terms of VM_Atom.hashCode to enable
* consistent hash codes during bootImage writing and run-time.
*/
- public int hashCode() {
+ public int hashCode() {
return memRef.hashCode();
}
public final String toString() {
return declaringClass + "." + getName() + " " + getDescriptor();
}
-
+
/**
* Usable from classes outside its package?
- */
+ */
public final boolean isPublic() {
- return (modifiers & ACC_PUBLIC) != 0;
+ return (modifiers & ACC_PUBLIC) != 0;
}
/**
* Usable only from this class?
- */
- public final boolean isPrivate() {
- return (modifiers & ACC_PRIVATE) != 0;
+ */
+ public final boolean isPrivate() {
+ return (modifiers & ACC_PRIVATE) != 0;
}
-
+
/**
* Usable from subclasses?
- */
- public final boolean isProtected() {
- return (modifiers & ACC_PROTECTED) != 0;
- }
+ */
+ public final boolean isProtected() {
+ return (modifiers & ACC_PROTECTED) != 0;
+ }
/**
* Get the member's modifiers.
@@ -167,10 +167,10 @@
public final int getModifiers() {
return modifiers;
}
-
+
/**
* Has the field been laid out in the object yet ?
- *
+ *
* @return
*/
public final boolean hasOffset() {
@@ -179,7 +179,7 @@
//------------------------------------------------------------------//
// Section 2. //
- // The following are available after the declaring class has been //
+ // The following are available after the declaring class has been //
// "resolved". //
//------------------------------------------------------------------//
@@ -191,10 +191,10 @@
* <li> For a non-static field: offset of field from start of object
* <li> For a non-static method: offset of code object reference from start of tib
* </ul>
- */
+ */
@Uninterruptible
- public final Offset getOffset() {
- if (VM.VerifyAssertions) VM._assert(declaringClass.isResolved());
+ public final Offset getOffset() {
+ if (VM.VerifyAssertions) VM._assert(declaringClass.isLoaded());
if (VM.VerifyAssertions) VM._assert(offset != NO_OFFSET);
return Offset.fromIntSignExtend(offset);
}
Modified: ext/org/jikesrvm/classloader/VM_Method.java
===================================================================
--- ext/org/jikesrvm/classloader/VM_Method.java 2007-08-06 14:18:07 UTC (rev 156)
+++ ext/org/jikesrvm/classloader/VM_Method.java 2007-08-06 15:23:44 UTC (rev 157)
@@ -1,121 +1,96 @@
/*
- * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net).
- * The Jikes RVM project is distributed under the Common Public License (CPL).
- * A copy of the license is included in the distribution, and is also
- * available at http://www.opensource.org/licenses/cpl1.0.php
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
*
- * (C) Copyright IBM Corp 2001,2002
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
*/
package org.jikesrvm.classloader;
-import org.jikesrvm.*;
+import java.io.DataInputStream;
+import java.io.IOException;
import org.jikesrvm.ArchitectureSpecific.VM_CodeArray;
import org.jikesrvm.ArchitectureSpecific.VM_LazyCompilationTrampolineGenerator;
+import org.jikesrvm.VM;
import org.jikesrvm.compilers.common.VM_CompiledMethod;
import org.jikesrvm.compilers.common.VM_CompiledMethods;
-import org.jikesrvm.runtime.VM_Statics;
import org.jikesrvm.runtime.VM_Entrypoints;
-
-import java.io.DataInputStream;
-import java.io.IOException;
-
+import org.jikesrvm.runtime.VM_Statics;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.pragma.Unpreemptible;
import org.vmmagic.unboxed.Offset;
-import org.vmmagic.pragma.*;
/**
- * A method of a java class corresponding to a method_info structure in the
- * class file. A method is read from a class file using the {@link #readMethod}
- * method.
- *
- * @author Bowen Alpern
- * @author Dave Grove
- * @author Derek Lieber
- * @author Ian Rogers
+ * A method of a java class corresponding to a method_info structure
+ * in the class file. A method is read from a class file using the
+ * {@link #readMethod} method.
*/
-public abstract class VM_Method extends VM_Member implements
- VM_BytecodeConstants {
+public abstract class VM_Method extends VM_Member implements VM_BytecodeConstants {
/**
* current compiled method for this method
*/
protected VM_CompiledMethod currentCompiledMethod;
-
/**
* exceptions this method might throw (null --> none)
*/
protected final VM_TypeReference[] exceptionTypes;
-
/**
- * Method paramter annotations from the class file that are described as
- * runtime visible. These annotations are available to the reflection API.
+ * Method paramter annotations from the class file that are
+ * described as runtime visible. These annotations are available to
+ * the reflection API.
*/
protected final VM_Annotation[] parameterAnnotations;
-
/**
* A value present in the method info tables of annotation types. It
* represents the default result from an annotation method.
*/
protected final Object annotationDefault;
-
/**
- * The offset of this virtual method in the jtoc if it's been placed there by
- * constant propagation, otherwise 0.
+ * The offset of this virtual method in the jtoc if it's been placed
+ * there by constant propagation, otherwise 0.
*/
private Offset jtocOffset;
/**
* Construct a read method
- *
- * @param declaringClass
- * the VM_Class object of the class that declared this field
- * @param memRef
- * the canonical memberReference for this method.
- * @param modifiers
- * modifiers associated with this method.
- * @param exceptionTypes
- * exceptions thrown by this method.
- * @param signature
- * generic type of this method.
- * @param annotations
- * array of runtime visible annotations
- * @param parameterAnnotations
- * array of runtime visible parameter annotations
- * @param annotationDefault
- * value for this annotation that appears
+ *
+ * @param declaringClass the VM_Class object of the class that declared this field
+ * @param memRef the canonical memberReference for this method.
+ * @param modifiers modifiers associated with this method.
+ * @param exceptionTypes exceptions thrown by this method.
+ * @param signature generic type of this method.
+ * @param annotations array of runtime visible annotations
+ * @param parameterAnnotations array of runtime visible parameter annotations
+ * @param annotationDefault value for this annotation that appears
*/
- protected VM_Method(VM_TypeReference declaringClass,
- VM_MemberReference memRef, short modifiers,
- VM_TypeReference[] exceptionTypes, VM_Atom signature,
- VM_Annotation[] annotations, VM_Annotation[] parameterAnnotations,
- Object annotationDefault) {
- super(declaringClass, memRef, (short) (modifiers & APPLICABLE_TO_METHODS),
- signature, annotations);
+ protected VM_Method(VM_TypeReference declaringClass, VM_MemberReference memRef, short modifiers,
+ VM_TypeReference[] exceptionTypes, VM_Atom signature, VM_Annotation[] annotations,
+ VM_Annotation[] parameterAnnotations, Object annotationDefault) {
+ super(declaringClass, memRef, (short) (modifiers & APPLICABLE_TO_METHODS), signature, annotations);
this.parameterAnnotations = parameterAnnotations;
this.annotationDefault = annotationDefault;
- memRef.asMethodReference().setResolvedMember(this);
this.exceptionTypes = exceptionTypes;
this.jtocOffset = Offset.fromIntSignExtend(-1);
}
/**
- * Called from {@link VM_Class#readClass(VM_TypeReference, DataInputStream)}
- * to create an instance of a VM_Method by reading the relevant data from the
- * argument bytecode stream.
- *
- * @param declaringClass
- * the VM_TypeReference of the class being loaded
- * @param constantPool
- * the constantPool of the VM_Class object that's being constructed
- * @param memRef
- * the canonical memberReference for this member.
- * @param modifiers
- * modifiers associated with this member.
- * @param input
- * the DataInputStream to read the method's attributes from
+ * Called from {@link VM_Class#readClass(VM_TypeReference,DataInputStream)} to create an
+ * instance of a VM_Method by reading the relevant data from the argument bytecode stream.
+ *
+ * @param declaringClass the VM_TypeReference of the class being loaded
+ * @param constantPool the constantPool of the VM_Class object that's being constructed
+ * @param memRef the canonical memberReference for this member.
+ * @param modifiers modifiers associated with this member.
+ * @param input the DataInputStream to read the method's attributes from
*/
- static VM_Method readMethod(VM_TypeReference declaringClass,
- int[] constantPool, VM_MemberReference memRef, short modifiers,
- DataInputStream input) throws IOException {
+ static VM_Method readMethod(VM_TypeReference declaringClass, int[] constantPool, VM_MemberReference memRef,
+ short modifiers, DataInputStream input) throws IOException {
short tmp_localWords = 0;
short tmp_operandWords = 0;
byte[] tmp_bytecodes = null;
@@ -129,8 +104,7 @@
// Read the attributes
for (int i = 0, n = input.readUnsignedShort(); i < n; i++) {
- VM_Atom attName = VM_Class
- .getUtf(constantPool, input.readUnsignedShort());
+ VM_Atom attName = VM_Class.getUtf(constantPool, input.readUnsignedShort());
int attLength = input.readInt();
// Only bother to interpret non-boring Method attributes
@@ -139,8 +113,7 @@
tmp_localWords = input.readShort();
tmp_bytecodes = new byte[input.readInt()];
input.readFully(tmp_bytecodes);
- tmp_exceptionHandlerMap = VM_ExceptionHandlerMap
- .readExceptionHandlerMap(input, constantPool);
+ tmp_exceptionHandlerMap = VM_ExceptionHandlerMap.readExceptionHandlerMap(input, constantPool);
// Read the attributes portion of the code attribute
for (int j = 0, n2 = input.readUnsignedShort(); j < n2; j++) {
@@ -158,8 +131,7 @@
}
}
} else {
- // All other entries in the attribute portion of the code attribute
- // are boring.
+ // All other entries in the attribute portion of the code attribute are boring.
input.skipBytes(attLength);
}
}
@@ -168,25 +140,21 @@
if (cnt != 0) {
tmp_exceptionTypes = new VM_TypeReference[cnt];
for (int j = 0, m = tmp_exceptionTypes.length; j < m; ++j) {
- tmp_exceptionTypes[j] = VM_Class.getTypeRef(constantPool, input
- .readUnsignedShort());
+ tmp_exceptionTypes[j] = VM_Class.getTypeRef(constantPool, input.readUnsignedShort());
}
}
} else if (attName == VM_ClassLoader.syntheticAttributeName) {
modifiers |= ACC_SYNTHETIC;
} else if (attName == VM_ClassLoader.signatureAttributeName) {
- tmp_signature = VM_Class
- .getUtf(constantPool, input.readUnsignedShort());
+ tmp_signature = VM_Class.getUtf(constantPool, input.readUnsignedShort());
} else if (attName == VM_ClassLoader.runtimeVisibleAnnotationsAttributeName) {
- annotations = VM_AnnotatedElement.readAnnotations(constantPool, input,
- 2, declaringClass.getClassLoader());
+ annotations = VM_AnnotatedElement.readAnnotations(constantPool, input, 2, declaringClass.getClassLoader());
} else if (attName == VM_ClassLoader.runtimeVisibleParameterAnnotationsAttributeName) {
- parameterAnnotations = VM_AnnotatedElement.readAnnotations(
- constantPool, input, 1, declaringClass.getClassLoader());
+ parameterAnnotations =
+ VM_AnnotatedElement.readAnnotations(constantPool, input, 1, declaringClass.getClassLoader());
} else if (attName == VM_ClassLoader.annotationDefaultAttributeName) {
try {
- tmp_annotationDefault = VM_Annotation.readValue(constantPool, input,
- declaringClass.getClassLoader());
+ tmp_annotationDefault = VM_Annotation.readValue(constantPool, input, declaringClass.getClassLoader());
} catch (ClassNotFoundException e) {
throw new Error(e);
}
@@ -197,73 +165,100 @@
}
VM_Method method;
if ((modifiers & ACC_NATIVE) != 0) {
- method = new VM_NativeMethod(declaringClass, memRef, modifiers,
- tmp_exceptionTypes, tmp_signature, annotations, parameterAnnotations,
- tmp_annotationDefault);
+ method =
+ new VM_NativeMethod(declaringClass,
+ memRef,
+ modifiers,
+ tmp_exceptionTypes,
+ tmp_signature,
+ annotations,
+ parameterAnnotations,
+ tmp_annotationDefault);
} else if ((modifiers & ACC_ABSTRACT) != 0) {
- method = new VM_AbstractMethod(declaringClass, memRef, modifiers,
- tmp_exceptionTypes, tmp_signature, annotations, parameterAnnotations,
- tmp_annotationDefault);
+ method =
+ new VM_AbstractMethod(declaringClass,
+ memRef,
+ modifiers,
+ tmp_exceptionTypes,
+ tmp_signature,
+ annotations,
+ parameterAnnotations,
+ tmp_annotationDefault);
} else {
- method = new VM_NormalMethod(declaringClass, memRef, modifiers,
- tmp_exceptionTypes, tmp_localWords, tmp_operandWords, tmp_bytecodes,
- tmp_exceptionHandlerMap, tmp_lineNumberMap, constantPool,
- tmp_signature, annotations, parameterAnnotations,
- tmp_annotationDefault);
+ method =
+ new VM_NormalMethod(declaringClass,
+ memRef,
+ modifiers,
+ tmp_exceptionTypes,
+ tmp_localWords,
+ tmp_operandWords,
+ tmp_bytecodes,
+ tmp_exceptionHandlerMap,
+ tmp_lineNumberMap,
+ constantPool,
+ tmp_signature,
+ annotations,
+ parameterAnnotations,
+ tmp_annotationDefault);
}
return method;
}
/**
- * Create a copy of the method that occurs in the annotation interface. The
- * method body will contain a read of the field at the constant pool index
- * specified.
- *
- * @param annotationClass
- * the class this method belongs to
- * @param constantPool
- * for the class
- * @param memRef
- * the member reference corresponding to this method
- * @param interfaceMethod
- * the interface method that will copied to produce the annotation
- * method
- * @param constantPoolIndex
- * the index of the field that will be returned by this method
+ * Create a copy of the method that occurs in the annotation
+ * interface. The method body will contain a read of the field at
+ * the constant pool index specified.
+ *
+ * @param annotationClass the class this method belongs to
+ * @param constantPool for the class
+ * @param memRef the member reference corresponding to this method
+ * @param interfaceMethod the interface method that will copied to
+ * produce the annotation method
+ * @param constantPoolIndex the index of the field that will be
+ * returned by this method
* @return the created method
*/
- static VM_Method createAnnotationMethod(VM_TypeReference annotationClass,
- int[] constantPool, VM_MemberReference memRef, VM_Method interfaceMethod,
- int constantPoolIndex) {
- byte[] bytecodes = new byte[] { (byte) JBC_aload_0, (byte) JBC_getfield,
- (byte) (constantPoolIndex >>> 8), (byte) constantPoolIndex,
+ static VM_Method createAnnotationMethod(VM_TypeReference annotationClass, int[] constantPool,
+ VM_MemberReference memRef, VM_Method interfaceMethod,
+ int constantPoolIndex) {
+ byte[] bytecodes =
+ new byte[]{
+ (byte) JBC_aload_0,
+ (byte) JBC_getfield, (byte) (constantPoolIndex >>> 8), (byte) constantPoolIndex,
// Xreturn
- (byte) typeRefToReturnBytecode(interfaceMethod.getReturnType()) };
- return new VM_NormalMethod(annotationClass, memRef, (short) (ACC_PUBLIC
- | ACC_FINAL | ACC_SYNTHETIC), null, (short) 1, (short) 2, bytecodes,
- null, null, constantPool, null, null, null, null);
+ (byte) typeRefToReturnBytecode(interfaceMethod.getReturnType())};
+ return new VM_NormalMethod(annotationClass,
+ memRef,
+ (short) (ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC),
+ null,
+ (short) 1,
+ (short) 2,
+ bytecodes,
+ null,
+ null,
+ constantPool,
+ null,
+ null,
+ null,
+ null);
}
/**
* Create a method to initialise the annotation class
- *
- * @param aClass
- * the class this method belongs to
- * @param constantPool
- * for the class
- * @param memRef
- * the member reference corresponding to this method
- * @param objectInitIndex
- * an index into the constant pool for a method reference to
- * java.lang.Object.<init>
+ *
+ * @param aClass the class this method belongs to
+ * @param constantPool for the class
+ * @param memRef the member reference corresponding to this method
+ * @param objectInitIndex an index into the constant pool for a
+ * method reference to java.lang.Object.<init>
* @param aFields
* @param aMethods
* @return the created method
*/
- static VM_Method createAnnotationInit(VM_TypeReference aClass,
- int[] constantPool, VM_MemberReference memRef, int objectInitIndex,
- VM_Field[] aFields, VM_Method[] aMethods, int[] defaultConstants) {
+ static VM_Method createAnnotationInit(VM_TypeReference aClass, int[] constantPool, VM_MemberReference memRef,
+ int objectInitIndex, VM_Field[] aFields, VM_Method[] aMethods,
+ int[] defaultConstants) {
byte[] bytecode = new byte[6 + (defaultConstants.length * 7)];
bytecode[0] = (byte) JBC_aload_0; // stack[0] = this
bytecode[1] = (byte) JBC_aload_1; // stack[1] = instanceof VM_Annotation
@@ -272,7 +267,7 @@
bytecode[4] = (byte) objectInitIndex;
for (int i = 0, j = 0; i < aMethods.length; i++) {
if (aMethods[i].annotationDefault != null) {
- bytecode[(j * 7) + 5 + 0] = (byte) JBC_aload_0; // stack[0] = this
+ bytecode[(j * 7) + 5 + 0] = (byte) JBC_aload_0; // stack[0] = this
if (VM_Class.getLiteralSize(constantPool, defaultConstants[j]) == BYTES_IN_INT) {
bytecode[(j * 7) + 5 + 1] = (byte) JBC_ldc_w; // stack[1] = value
} else {
@@ -287,22 +282,36 @@
}
}
bytecode[bytecode.length - 1] = (byte) JBC_return;
- return new VM_NormalMethod(aClass, memRef,
- (short) (ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC), null, (short) 2,
- (short) 3, bytecode, null, null, constantPool, null, null, null, null);
+ return new VM_NormalMethod(aClass,
+ memRef,
+ (short) (ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC),
+ null,
+ (short) 2,
+ (short) 3,
+ bytecode,
+ null,
+ null,
+ constantPool,
+ null,
+ null,
+ null,
+ null);
}
/**
- * What would be the appropriate return bytecode for the given type reference?
+ * What would be the appropriate return bytecode for the given type
+ * reference?
*/
private static int typeRefToReturnBytecode(VM_TypeReference tr) {
if (!tr.isPrimitiveType()) {
return JBC_areturn;
} else {
- VM_Primitive pt = (VM_Primitive) tr.peekResolvedType();
- if ((pt == VM_Type.BooleanType) || (pt == VM_Type.ByteType)
- || (pt == VM_Type.ShortType) || (pt == VM_Type.CharType)
- || (pt == VM_Type.IntType)) {
+ VM_Primitive pt = (VM_Primitive) tr.peekType();
+ if ((pt == VM_Type.BooleanType) ||
+ (pt == VM_Type.ByteType) ||
+ (pt == VM_Type.ShortType) ||
+ (pt == VM_Type.CharType) ||
+ (pt == VM_Type.IntType)) {
return JBC_ireturn;
} else if (pt == VM_Type.LongType) {
return JBC_lreturn;
@@ -350,8 +359,8 @@
}
/**
- * Type of this method's parameters. Note: does *not* include implicit "this"
- * parameter, if any.
+ * Type of this method's parameters.
+ * Note: does *not* include implicit "this" parameter, if any.
*/
@Uninterruptible
public final VM_TypeReference[] getParameterTypes() {
@@ -359,8 +368,8 @@
}
/**
- * Space required by this method for its parameters, in words. Note: does
- * *not* include implicit "this" parameter, if any.
+ * Space required by this method for its parameters, in words.
+ * Note: does *not* include implicit "this" parameter, if any.
*/
@Uninterruptible
public final int getParameterWords() {
@@ -375,12 +384,11 @@
}
/**
- * Get the current compiled method for this method. Will return null if there
- * is no current compiled method!
- *
- * We make this method Unpreemptible to avoid a race-condition in
- * VM_Reflection.invoke.
- *
+ * Get the current compiled method for this method.
+ * Will return null if there is no current compiled method!
+ *
+ * We make this method Unpreemptible to avoid a race-condition
+ * in VM_Reflection.invoke.
* @return compiled method
*/
@Unpreemptible
@@ -424,8 +432,7 @@
* Not implemented in Java and use C not JNI calling convention
*/
public final boolean isSysCall() {
- return isNative() && isStatic()
- && isAnnotationDeclared(VM_TypeReference.SysCall);
+ return isNative() && isStatic() && isAnnotationDeclared(VM_TypeReference.SysCall);
}
/**
@@ -444,9 +451,8 @@
}
/**
- * Exceptions thrown by this method - something like {
- * "java/lang/IOException", "java/lang/EOFException" }
- *
+ * Exceptions thrown by this method -
+ * something like { "java/lang/IOException", "java/lang/EOFException" }
* @return info (null --> method doesn't throw any exceptions)
*/
@Uninterruptible
@@ -455,47 +461,36 @@
}
/**
- * Is this method interruptible? In other words, should the compiler insert
- * yieldpoints in method prologue, epilogue, and backwards branches. Also,
- * only methods that are Interruptible have stackoverflow checks in the method
- * prologue (since there is no mechanism for handling a stackoverflow that
- * doesn't violate the uninterruptiblity of the method). To determine if a
- * method is interruptible, the following conditions are checked (<em>in order</em>):
+ * Is this method interruptible?
+ * In other words, should the compiler insert yieldpoints
+ * in method prologue, epilogue, and backwards branches.
+ * Also, only methods that are Interruptible have stackoverflow checks
+ * in the method prologue (since there is no mechanism for handling a stackoverflow
+ * that doesn't violate the uninterruptiblity of the method).
+ * To determine if a method is interruptible, the following conditions
+ * are checked (<em>in order</em>):
* <ul>
* <li> If it is a <clinit> or <init> method then it is interruptible.
- * <li> If is the synthetic 'this' method used by jikes to factor out default
- * initializers for <init> methods then it is interruptible.
- * <li> If it is annotated with <CODE>Interruptible</CODE> it is
- * interruptible.
- * <li> If it is annotated with <CODE>Preemptible</CODE> it is
- * interruptible.
- * <li> If it is annotated with <CODE>Uninterruptible</CODE> it is not
- * interruptible.
- * <li> If it is annotated with <CODE>UninterruptibleNoWarn</CODE> it is not
- * interruptible.
- * <li> If it is annotated with <CODE>Unpreemptible</CODE> it is not
- * interruptible.
+ * <li> If is the synthetic 'this' method used by jikes to
+ * factor out default initializers for <init> methods then it is interruptible.
+ * <li> If it is annotated with <CODE>Interruptible</CODE> it is interruptible.
+ * <li> If it is annotated with <CODE>Preemptible</CODE> it is interruptible.
+ * <li> If it is annotated with <CODE>Uninterruptible</CODE> it is not interruptible.
+ * <li> If it is annotated with <CODE>UninterruptibleNoWarn</CODE> it is not interruptible.
+ * <li> If it is annotated with <CODE>Unpreemptible</CODE> it is not interruptible.
* <li> If its declaring class is annotated with <CODE>Uninterruptible</CODE>
- * or <CODE>Unpreemptible</CODE> it is not interruptible.
+ * or <CODE>Unpreemptible</CODE> it is not interruptible.
* </ul>
*/
public final boolean isInterruptible() {
- if (isClassInitializer() || isObjectInitializer())
- return true;
- if (isObjectInitializerHelper())
- return true;
- if (hasInterruptibleAnnotation())
- return true;
- if (hasPreemptibleAnnotation())
- return true;
- if (hasUninterruptibleNoWarnAnnotation())
- return false;
- if (hasUninterruptibleAnnotation())
- return false;
- if (hasUnpreemptibleAnnotation())
- return false;
- if (getDeclaringClass().hasUnpreemptibleAnnotation())
- return false;
+ if (isClassInitializer() || isObjectInitializer()) return true;
+ if (isObjectInitializerHelper()) return true;
+ if (hasInterruptibleAnnotation()) return true;
+ if (hasPreemptibleAnnotation()) return true;
+ if (hasUninterruptibleNoWarnAnnotation()) return false;
+ if (hasUninterruptibleAnnotation()) return false;
+ if (hasUnpreemptibleAnnotation()) return false;
+ if (getDeclaringClass().hasUnpreemptibleAnnotation()) return false;
return !getDeclaringClass().hasUninterruptibleAnnotation();
}
@@ -503,20 +498,13 @@
* Is the method Unpreemptible? See the comment in {@link #isInterruptible}
*/
public final boolean isUnpreemptible() {
- if (isClassInitializer() || isObjectInitializer())
- return false;
- if (isObjectInitializerHelper())
- return false;
- if (hasInterruptibleAnnotation())
- return false;
- if (hasPreemptibleAnnotation())
- return false;
- if (hasUninterruptibleAnnotation())
- return false;
- if (hasUninterruptibleNoWarnAnnotation())
- return false;
- if (hasUnpreemptibleAnnotation())
- return true;
+ if (isClassInitializer() || isObjectInitializer()) return false;
+ if (isObjectInitializerHelper()) return false;
+ if (hasInterruptibleAnnotation()) return false;
+ if (hasPreemptibleAnnotation()) return false;
+ if (hasUninterruptibleAnnotation()) return false;
+ if (hasUninterruptibleNoWarnAnnotation()) return false;
+ if (hasUnpreemptibleAnnotation()) return true;
return getDeclaringClass().hasUnpreemptibleAnnotation();
}
@@ -524,28 +512,30 @@
* Is the method Uninterruptible? See the comment in {@link #isInterruptible}
*/
public final boolean isUninterruptible() {
- if (isClassInitializer() || isObjectInitializer())
- return false;
- if (isObjectInitializerHelper())
- return false;
- if (hasInterruptibleAnnotation())
- return false;
- if (hasPreemptibleAnnotation())
- return false;
- if (hasUnpreemptibleAnnotation())
- return false;
- if (hasUninterruptibleAnnotation())
- return true;
- if (hasUninterruptibleNoWarnAnnotation())
- return true;
+ if (isClassInitializer() || isObjectInitializer()) return false;
+ if (isObjectInitializerHelper()) return false;
+ if (hasInterruptibleAnnotation()) return false;
+ if (hasPreemptibleAnnotation()) return false;
+ if (hasUnpreemptibleAnnotation()) return false;
+ if (hasUninterruptibleAnnotation()) return true;
+ if (hasUninterruptibleNoWarnAnnotation()) return true;
return getDeclaringClass().hasUninterruptibleAnnotation();
}
/**
- * Has this method been marked as forbidden to inline? ie., it is marked with
- * the <CODE>NoInline</CODE> annotation or the <CODE>NoOptCompile</CODE>
- * annotation?
+ * Is the method Pure? That is would it, without any side effects, return the
+ * same value given the same arguments?
+ *
+ * @return whether the method has a pure annotation
*/
+ public final boolean isPure() {
+ return hasPureAnnotation();
+ }
+ /**
+ * Has this method been marked as forbidden to inline?
+ * ie., it is marked with the <CODE>NoInline</CODE> annotation or
+ * the <CODE>NoOptCompile</CODE> annotation?
+ */
public final boolean hasNoInlinePragma() {
return (hasNoInlineAnnotation() || hasNoOptCompileAnnotation());
}
@@ -554,57 +544,48 @@
* @return true if the method may write to a given field
*/
public boolean mayWrite(VM_Field field) {
- return true; // be conservative. native methods can write to anything
+ return true; // be conservative. native methods can write to anything
}
/**
- * @return true if the method is the implementation of a runtime service that
- * is called "under the covers" from the generated code and thus is
- * not subject to inlining via the normal mechanisms.
+ * @return true if the method is the implementation of a runtime service
+ * that is called "under the covers" from the generated code and thus is not subject to
+ * inlining via the normal mechanisms.
*/
public boolean isRuntimeServiceMethod() {
- return false; // only VM_NormalMethods can be runtime service impls in Jikes
- // RVM and they override this method
+ return false; // only VM_NormalMethods can be runtime service impls in Jikes RVM and they override this method
}
- // ------------------------------------------------------------------//
- // Section 2. //
- // The following are available after the declaring class has been //
- // "resolved". //
- // ------------------------------------------------------------------//
+ //------------------------------------------------------------------//
+ // Section 2. //
+ // The following are available after the declaring class has been //
+ // "resolved". //
+ //------------------------------------------------------------------//
/**
- * Get the code array that corresponds to the entry point (prologue) for the
- * method.
+ * Get the code array that corresponds to the entry point (prologue) for the method.
*/
public final synchronized VM_CodeArray getCurrentEntryCodeArray() {
VM_Class declaringClass = getDeclaringClass();
- if (VM.VerifyAssertions)
- VM._assert(declaringClass.isResolved());
+ if (VM.VerifyAssertions) VM._assert(declaringClass.isResolved());
if (isCompiled()) {
return currentCompiledMethod.getEntryCodeArray();
} else if (!VM.writingBootImage || isNative()) {
if (!isStatic() && !isObjectInitializer() && !isPrivate()) {
// A non-private virtual method.
- if (declaringClass.isJavaLangObjectType()
- || declaringClass.getSuperClass().findVirtualMethod(getName(),
- getDescriptor()) == null) {
- // The root method of a virtual method family can use the lazy method
- // invoker directly.
- return VM_Entrypoints.lazyMethodInvokerMethod
- .getCurrentEntryCodeArray();
+ if (declaringClass.isJavaLangObjectType() ||
+ declaringClass.getSuperClass().findVirtualMethod(getName(), getDescriptor()) == null) {
+ // The root method of a virtual method family can use the lazy method invoker directly.
+ return VM_Entrypoints.lazyMethodInvokerMethod.getCurrentEntryCodeArray();
} else {
- // All other virtual methods in the family must generate unique stubs
- // to
- // ensure correct operation of the method test (guarded inlining of
- // virtual calls).
+ // All other virtual methods in the family must generate unique stubs to
+ // ensure correct operation of the method test (guarded inlining of virtual calls).
return VM_LazyCompilationTrampolineGenerator.getTrampoline();
}
} else {
// We'll never do a method test against this method.
// Therefore we can use the lazy method invoker directly.
- return VM_Entrypoints.lazyMethodInvokerMethod
- .getCurrentEntryCodeArray();
+ return VM_Entrypoints.lazyMethodInvokerMethod.getCurrentEntryCodeArray();
}
} else {
compile();
@@ -613,17 +594,15 @@
}
/**
- * Generate machine code for this method if valid machine code doesn't already
- * exist. Return the resulting VM_CompiledMethod object.
+ * Generate machine code for this method if valid
+ * machine code doesn't already exist.
+ * Return the resulting VM_CompiledMethod object.
*/
public final synchronized void compile() {
- if (VM.VerifyAssertions)
- VM._assert(getDeclaringClass().isResolved());
- if (isCompiled())
- return;
+ if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isResolved());
+ if (isCompiled()) return;
- if (VM.TraceClassLoading && VM.runningVM)
- VM.sysWrite("VM_Method: (begin) compiling " + this + "\n");
+ if (VM.TraceClassLoading && VM.runningVM) VM.sysWrite("VM_Method: (begin) compiling " + this + "\n");
VM_CompiledMethod cm = genCode();
@@ -636,37 +615,31 @@
}
}
- if (VM.TraceClassLoading && VM.runningVM)
- VM.sysWrite("VM_Method: (end) compiling " + this + "\n");
+ if (VM.TraceClassLoading && VM.runningVM) VM.sysWrite("VM_Method: (end) compiling " + this + "\n");
}
protected abstract VM_CompiledMethod genCode();
- // ----------------------------------------------------------------//
- // Section 3. //
+ //----------------------------------------------------------------//
+ // Section 3. //
// The following are available after the declaring class has been //
- // "instantiated". //
- // ----------------------------------------------------------------//
+ // "instantiated". //
+ //----------------------------------------------------------------//
/**
* Change machine code that will be used by future executions of this method
* (ie. optimized <-> non-optimized)
- *
- * @param compiledMethod
- * new machine code Side effect: updates jtoc or method dispatch
- * tables ("type information blocks") for this class and its
- * subclasses
+ * @param compiledMethod new machine code
+ * Side effect: updates jtoc or method dispatch tables
+ * ("type information blocks")
+ * for this class and its subclasses
*/
- public synchronized void replaceCompiledMethod(
- VM_CompiledMethod compiledMethod) {
- if (VM.VerifyAssertions)
- VM._assert(getDeclaringClass().isInstantiated());
- // If we're replacing with a non-null compiledMethod, ensure that is still
- // valid!
+ public synchronized void replaceCompiledMethod(VM_CompiledMethod compiledMethod) {
+ if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isInstantiated());
+ // If we're replacing with a non-null compiledMethod, ensure that is still valid!
if (compiledMethod != null) {
synchronized (compiledMethod) {
- if (compiledMethod.isInvalid())
- return;
+ if (compiledMethod.isInvalid()) return;
}
}
@@ -693,8 +666,7 @@
* If CM is the current compiled code for this, then invaldiate it.
*/
public final synchronized void invalidateCompiledMethod(VM_CompiledMethod cm) {
- if (VM.VerifyAssertions)
- VM._assert(getDeclaringClass().isInstantiated());
+ if (VM.VerifyAssertions) VM._assert(getDeclaringClass().isInstantiated());
if (currentCompiledMethod == cm) {
replaceCompiledMethod(null);
}
@@ -704,8 +676,7 @@
* Find or create a jtoc offset for this method
*/
public final synchronized Offset findOrCreateJtocOffset() {
- if (VM.VerifyAssertions)
- VM._assert(!isStatic() && !isObjectInitializer());
+ if (VM.VerifyAssertions) VM._assert(!isStatic() && !isObjectInitializer());
if (jtocOffset.EQ(Offset.zero())) {
jtocOffset = VM_Statics.allocateReferenceSlot();
VM_Statics.setSlotContents(jtocOffset, getCurrentEntryCodeArray());
Modified: ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java
===================================================================
--- ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java 2007-08-06 14:18:07 UTC (rev 156)
+++ ext/org/jikesrvm/compilers/common/VM_RuntimeCompiler.java 2007-08-06 15:23:44 UTC (rev 157)
@@ -1,85 +1,97 @@
/*
- * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net).
- * The Jikes RVM project is distributed under the Common Public License (CPL).
- * A copy of the license is included in the distribution, and is also
- * available at http://www.opensource.org/licenses/cpl1.0.php
+ * This file is part of the Jikes RVM project (http://jikesrvm.org).
*
- * (C) Copyright IBM Corp. 2001, 2005
+ * This file is licensed to You under the Common Public License (CPL);
+ * You may not use this file except in compliance with the License. You
+ * may obtain a copy of the License at
+ *
+ * http://www.opensource.org/licenses/cpl1.0.php
+ *
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.
*/
package org.jikesrvm.compilers.common;
-import org.jikesrvm.*;
-import org.jikesrvm.classloader.*;
-import org.jikesrvm.compilers.baseline.*;
-import org.jikesrvm.compilers.opt.*;
+import org.jikesrvm.ArchitectureSpecific;
+import org.jikesrvm.ArchitectureSpecific.VM_JNICompiler;
+import org.jikesrvm.VM;
+import org.jikesrvm.VM_Callbacks;
+import org.jikesrvm.VM_Constants;
import org.jikesrvm.adaptive.controller.VM_Controller;
import org.jikesrvm.adaptive.controller.VM_ControllerMemory;
import org.jikesrvm.adaptive.controller.VM_ControllerPlan;
import org.jikesrvm.adaptive.recompilation.VM_InvocationCounts;
import org.jikesrvm.adaptive.recompilation.VM_PreCompile;
import org.jikesrvm.adaptive.recompilation.instrumentation.VM_AOSInstrumentationPlan;
-import org.jikesrvm.adaptive.util.*;
-import org.jikesrvm.ArchitectureSpecific.VM_JNICompiler;
+import org.jikesrvm.adaptive.util.VM_AOSGenerator;
+import org.jikesrvm.adaptive.util.VM_AOSLogging;
+import org.jikesrvm.adaptive.util.VM_CompilerAdviceAttribute;
+import org.jikesrvm.classloader.VM_NativeMethod;
+import org.jikesrvm.classloader.VM_NormalMethod;
+import org.jikesrvm.classloader.VM_Type;
+import org.jikesrvm.classloader.VM_TypeReference;
+import org.jikesrvm.compilers.baseline.VM_BaselineCompiler;
+import org.jikesrvm.compilers.opt.OPT_CompilationPlan;
+import org.jikesrvm.compilers.opt.OPT_Compiler;
+import org.jikesrvm.compilers.opt.OPT_MagicNotImplementedException;
+import org.jikesrvm.compilers.opt.OPT_OptimizationPlanElement;
+import org.jikesrvm.compilers.opt.OPT_OptimizationPlanner;
+import org.jikesrvm.compilers.opt.OPT_OptimizingCompilerException;
+import org.jikesrvm.compilers.opt.OPT_Options;
import org.jikesrvm.runtime.VM_Time;
-import org.jikesrvm.scheduler.VM_Thread;
+import org.jikesrvm.scheduler.VM_Scheduler;
/**
- * Harness to select which compiler to dynamically compile a method in first
- * invocation.
- *
- * A place to put code common to all runtime compilers. This includes
- * instrumentation code to get equivalent data for each of the runtime
- * compilers.
+ * Harness to select which compiler to dynamically
+ * compile a method in first invocation.
+ *
+ * A place to put code common to all runtime compilers.
+ * This includes instrumentation code to get equivalent data for
+ * each of the runtime compilers.
* <p>
* We collect the following data for each compiler
* <ol>
- * <li> total number of methods complied by the compiler
- * <li> total compilation time in milliseconds.
- * <li> total number of bytes of bytecodes compiled by the compiler (under the
- * assumption that there is no padding in the bytecode array and thus
- * VM_Method.getBytecodes().length is the number bytes of bytecode for a method)
- * <li> total number of machine code insructions generated by the compiler
- * (under the assumption that there is no (excessive) padding in the machine
- * code array and thus VM_CompiledMethod.numberOfInsturctions() is a close
- * enough approximation of the number of machinecodes generated)
+ * <li>
+ * total number of methods complied by the compiler
+ * <li>
+ * total compilation time in milliseconds.
+ * <li>
+ * total number of bytes of bytecodes compiled by the compiler
+ * (under the assumption that there is no padding in the bytecode
+ * array and thus VM_Method.getBytecodes().length is the number bytes
+ * of bytecode for a method)
+ * <li>
+ * total number of machine code insructions generated by the compiler
+ * (under the assumption that there is no (excessive) padding in the
+ * machine code array and thus VM_CompiledMethod.numberOfInsturctions()
+ * is a close enough approximation of the number of machinecodes generated)
* </ol>
- * Note that even if 3. & 4. are inflated due to padding, the numbers will still
- * be an accurate measure of the space costs of the compile-only approach.
- *
- * @author Matthew Arnold
- * @author Dave Grove
- * @author Michael Hind
+ * Note that even if 3. & 4. are inflated due to padding, the numbers will
+ * still be an accurate measure of the space costs of the compile-only
+ * approach.
*/
-public class VM_RuntimeCompiler implements VM_Constants,
- VM_Callbacks.ExitMonitor {
+public class VM_RuntimeCompiler implements VM_Constants, VM_Callbacks.ExitMonitor {
// Use these to encode the compiler for record()
public static final byte JNI_COMPILER = 0;
-
public static final byte BASELINE_COMPILER = 1;
-
public static final byte OPT_COMPILER = 2;
// Data accumulators
- private static final String[] name = { "JNI\t", "Base\t", "Opt\t" }; // Output
- // names
+ private static final String[] name = {"JNI\t", "Base\t", "Opt\t"}; // Output names
+ private static int[] totalMethods = {0, 0, 0};
+ private static double[] totalCompTime = {0, 0, 0};
+ private static int[] totalBCLength = {0, 0, 0};
+ private static int[] totalMCLength = {0, 0, 0};
- private static int[] totalMethods = { 0, 0, 0 };
-
- private static double[] totalCompTime = { 0, 0, 0 };
-
- private static int[] totalBCLength = { 0, 0, 0 };
-
- private static int[] totalMCLength = { 0, 0, 0 };
-
// running sum of the natural logs of the rates,
- // used for geometric mean, the product of rates is too big for doubles
- // so we use the principle of logs to help us
- // We compute e ** ((log a + log b + ... + log n) / n )
- private static double[] totalLogOfRates = { 0, 0, 0 };
+ // used for geometric mean, the product of rates is too big for doubles
+ // so we use the principle of logs to help us
+ // We compute e ** ((log a + log b + ... + log n) / n )
+ private static double[] totalLogOfRates = {0, 0, 0};
// We can't record values until Math.log is loaded, so we miss the first few
- private static int[] totalLogValueMethods = { 0, 0, 0 };
+ private static int[] totalLogValueMethods = {0, 0, 0};
private static String[] earlyOptArgs = new String[0];
@@ -93,8 +105,7 @@
// because the opt compiler is not reentrant.
// When we actually fix defect 2912, we'll have to implement a different
// scheme that can distinguish between recursive opt compilation by the same
- // thread (always bad) and parallel opt compilation (currently bad, future
- // ok).
+ // thread (always bad) and parallel opt compilation (currently bad, future ok).
// NOTE: This code can be quite subtle, so please be absolutely sure
// you know what you're doing before modifying it!!!
protected static boolean compilationInProgress;
@@ -104,82 +115,69 @@
// Cache objects needed to cons up compilation plans
// TODO: cutting link to opt compiler by declaring type as object.
- public static Object /* OPT_Options */options;
+ public static final Object /* OPT_Options */ options = VM.BuildForAdaptiveSystem ? new OPT_Options() : null;
+ public static Object /* OPT_OptimizationPlanElement[] */ optimizationPlan;
- public static Object /* OPT_OptimizationPlanElement[] */optimizationPlan;
-
/**
* To be called when the VM is about to exit.
- *
- * @param value
- * the exit value
+ * @param value the exit value
*/
public void notifyExit(int value) {
report(false);
}
/**
- * This method records the time and sizes (bytecode and machine code) for a
- * compilation.
- *
- * @param compiler
- * the compiler used
- * @param method
- * the resulting VM_Method
- * @param compiledMethod
- * the resulting compiled method
+ * This method records the time and sizes (bytecode and machine code) for
+ * a compilation.
+ * @param compiler the compiler used
+ * @param method the resulting VM_Method
+ * @param compiledMethod the resulting compiled method
*/
- public static void record(byte compiler, VM_NormalMethod method,
- VM_CompiledMethod compiledMethod) {
+ public static void record(byte compiler, VM_NormalMethod method, VM_CompiledMethod compiledMethod) {
- recordCompilation(compiler, method.getBytecodeLength(), compiledMethod
- .numberOfInstructions(), compiledMethod.getCompilationTime());
+ recordCompilation(compiler,
+ method.getBytecodeLength(),
+ compiledMethod.numberOfInstructions(),
+ compiledMethod.getCompilationTime());
if (VM.BuildForAdaptiveSystem) {
if (VM_AOSLogging.booted()) {
- VM_AOSLogging.recordUpdatedCompilationRates(compiler, method, method
- .getBytecodeLength(), totalBCLength[compiler], compiledMethod
- .numberOfInstructions(), totalMCLength[compiler], compiledMethod
- .getCompilationTime(), totalCompTime[compiler],
- totalLogOfRates[compiler], totalLogValueMethods[compiler],
- totalMethods[compiler]);
+ VM_AOSLogging.recordUpdatedCompilationRates(compiler,
+ method,
+ method.getBytecodeLength(),
+ totalBCLength[compiler],
+ compiledMethod.numberOfInstructions(),
+ totalMCLength[compiler],
+ compiledMethod.getCompilationTime(),
+ totalCompTime[compiler],
+ totalLogOfRates[compiler],
+ totalLogValueMethods[compiler],
+ totalMethods[compiler]);
}
}
}
/**
- * This method records the time and sizes (bytecode and machine code) for a
- * compilation
- *
- * @param compiler
- * the compiler used
- * @param method
- * the resulting VM_Method
- * @param compiledMethod
- * the resulting compiled method
+ * This method records the time and sizes (bytecode and machine code) for
+ * a compilation
+ * @param compiler the compiler used
+ * @param method the resulting VM_Method
+ * @param compiledMethod the resulting compiled method
*/
- public static void record(byte compiler, VM_NativeMethod method,
- VM_CompiledMethod compiledMethod) {
+ public static void record(byte compiler, VM_NativeMethod method, VM_CompiledMethod compiledMethod) {
recordCompilation(compiler, 0, // don't have any bytecode info, its native
- compiledMethod.numberOfInstructions(), compiledMethod
- .getCompilationTime());
+ compiledMethod.numberOfInstructions(), compiledMethod.getCompilationTime());
}
/**
* This method does the actual recording
- *
- * @param compiler
- * the compiler used
- * @param BCLength
- * the number of bytecodes in method source
- * @param MCLength
- * the length of the generated machine code
- * @param compTime
- * the compilation time in ms
+ * @param compiler the compiler used
+ * @param BCLength the number of bytecodes in method source
+ * @param MCLength the length of the generated machine code
+ * @param compTime the compilation time in ms
*/
- private static void recordCompilation(byte compiler, int BCLength,
- int MCLength, double compTime) {
+ private static void recordCompilation(byte compiler, int BCLength, int MCLength, double compTime) {
totalMethods[compiler]++;
totalMCLength[compiler] += MCLength;
@@ -193,8 +191,8 @@
// need to be fully booted before calling log
if (VM.fullyBooted) {
// we want the geometric mean, but the product of rates is too big
- // for doubles, so we use the principle of logs to help us
- // We compute e ** ((log a + log b + ... + log n) / n )
+ // for doubles, so we use the principle of logs to help us
+ // We compute e ** ((log a + log b + ... + log n) / n )
totalLogOfRates[compiler] += Math.log(rate);
totalLogValueMethods[compiler]++;
}
@@ -203,9 +201,7 @@
/**
* This method produces a summary report of compilation activities
- *
- * @param explain
- * Explains the metrics used in the report
+ * @param explain Explains the metrics used in the report
*/
public static void report(boolean explain) {
VM.sysWrite("\n\t\tCompilation Subsystem Report\n");
@@ -224,27 +220,21 @@
VM.sysWrite("NA");
} else {
// Bytecode bytes per millisecond,
- // use unweighted geomean
- VM
- .sysWrite(Math.exp(totalLogOfRates[i] / totalLogValueMethods[i]),
- 2);
+ // use unweighted geomean
+ VM.sysWrite(Math.exp(totalLogOfRates[i] / totalLogValueMethods[i]), 2);
}
VM.sysWrite("\t");
// Ratio of machine code bytes to bytecode bytes
if (i != JNI_COMPILER) {
- VM
- .sysWrite(
- (double) (totalMCLength[i] << ArchitectureSpecific.VM_RegisterConstants.LG_INSTRUCTION_WIDTH)
- / (double) totalBCLength[i], 2);
+ VM.sysWrite((double) (totalMCLength[i] << ArchitectureSpecific.VM_RegisterConstants.LG_INSTRUCTION_WIDTH) /
+ (double) totalBCLength[i], 2);
} else {
VM.sysWrite("NA");
}
VM.sysWrite("\t");
// Generated machine code Kbytes
- VM
- .sysWrite(
- (double) (totalMCLength[i] << ArchitectureSpecific.VM_RegisterConstants.LG_INSTRUCTION_WIDTH) / 1024,
- 1);
+ VM.sysWrite((double) (totalMCLength[i] << ArchitectureSpecific.VM_RegisterConstants.LG_INSTRUCTION_WIDTH) /
+ 1024, 1);
VM.sysWrite("\t");
// Compiled bytecode Kbytes
if (i != JNI_COMPILER) {
@@ -258,34 +248,23 @@
if (explain) {
// Generate an explanation of the metrics reported
VM.sysWrite("\t\t\tExplanation of Metrics\n");
- VM
- .sysWrite("#Meths:\t\tTotal number of methods compiled by the compiler\n");
+ VM.sysWrite("#Meths:\t\tTotal number of methods compiled by the compiler\n");
VM.sysWrite("Time:\t\tTotal compilation time in milliseconds\n");
- VM
- .sysWrite("bcb/ms:\t\tNumber of bytecode bytes complied per millisecond\n");
+ VM.sysWrite("bcb/ms:\t\tNumber of bytecode bytes complied per millisecond\n");
VM.sysWrite("mcb/bcb:\tRatio of machine code bytes to bytecode bytes\n");
- VM
- .sysWrite("MCKB:\t\tTotal number of machine code bytes generated in kilobytes\n");
- VM
- .sysWrite("BCKB:\t\tTotal number of bytecode bytes compiled in kilobytes\n");
+ VM.sysWrite("MCKB:\t\tTotal number of machine code bytes generated in kilobytes\n");
+ VM.sysWrite("BCKB:\t\tTotal number of bytecode bytes compiled in kilobytes\n");
}
VM_BaselineCompiler.generateBaselineCompilerSubsystemReport(explain);
if (VM.BuildForAdaptiveSystem) {
// Get the opt's report
- VM_TypeReference theTypeRef = VM_TypeReference
- .findOrCreate(
- VM_BootstrapClassLoader.getBootstrapClassLoader(),
- VM_Atom
- .findOrCreateAsciiAtom("Lorg/jikesrvm/opt/OPT_OptimizationPlanner;"));
- VM_Type theType = theTypeRef.peekResolvedType();
+ VM_Type theType = VM_TypeReference.OPT_OptimizationPlanner.peekType();
if (theType != null && theType.asClass().isInitialized()) {
- OPT_OptimizationPlanner
- .generateOptimizingCompilerSubsystemReport(explain);
+ OPT_OptimizationPlanner.generateOptimizingCompilerSubsystemReport(explain);
} else {
- VM
- .sysWrite("\n\tNot generating Optimizing Compiler SubSystem Report because \n");
+ VM.sysWrite("\n\tNot generating Optimizing Compiler SubSystem Report because \n");
VM.sysWrite("\tthe opt compiler was never invoked.\n\n");
}
}
@@ -295,32 +274,35 @@
* Return the current estimate of basline-compiler rate, in bcb/msec
*/
public static double getBaselineRate() {
- return Math.exp(totalLogOfRates[BASELINE_COMPILER]
- / totalLogValueMethods[BASELINE_COMPILER]);
+ return Math.exp(totalLogOfRates[BASELINE_COMPILER] / tota...
[truncated message content] |
|
From: <mic...@us...> - 2007-08-06 14:18:05
|
Revision: 156
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=156&view=rev
Author: michael_baer
Date: 2007-08-06 07:18:07 -0700 (Mon, 06 Aug 2007)
Log Message:
-----------
- Removed file due to lack of differences against current JRVM version
Removed Paths:
-------------
ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java
Deleted: ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java
===================================================================
--- ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java 2007-08-06 09:37:44 UTC (rev 155)
+++ ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java 2007-08-06 14:18:07 UTC (rev 156)
@@ -1,3266 +0,0 @@
-/*
- * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net).
- * The Jikes RVM project is distributed under the Common Public License (CPL).
- * A copy of the license is included in the distribution, and is also
- * available at http://www.opensource.org/licenses/cpl1.0.php
- *
- * (C) Copyright IBM Corp. 2001
- */
-package org.jikesrvm.compilers.opt;
-
-import org.jikesrvm.classloader.*;
-import org.jikesrvm.compilers.opt.ir.*;
-import org.jikesrvm.objectmodel.VM_TIBLayoutConstants;
-import org.jikesrvm.VM;
-import org.vmmagic.unboxed.*;
-import java.lang.reflect.Array;
-import static org.jikesrvm.VM_SizeConstants.*;
-import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*;
-
-/**
- * A constant folder, strength reducer and axiomatic simplifier.
- *
- * <p>
- * This module performs no analysis, it simply attempts to simplify the
- * instruction as is. The intent is that analysis modules can call this
- * transformation engine, allowing us to share the tedious simplification code
- * among multiple analysis modules.
- *
- * <p>
- * NOTE: For maintainability purposes, I've intentionally avoided being clever
- * about combining 'similar' operators together into a combined case of the main
- * switch switch statement. Also, operators are in sorted ordered within each
- * major grouping. Please maintain this coding style. I'd rather have this
- * module be 2000 lines of obviously correct code than 500 lines of clever code.
- *
- * @author Dave Grove
- * @author Ian Rogers
- */
-public abstract class OPT_Simplifier extends OPT_IRTools {
- // NOTE: The convention is that constant folding is controlled based
- // on the type of the result of the operator, not the type of its inputs.
- /**
- * Constant fold integer operations?
- */
- public static final boolean CF_INT = true;
-
- /**
- * Constant fold address operations?
- */
- public static final boolean CF_LONG = true;
-
- /**
- * Constant fold address operations?
- */
- public static final boolean CF_ADDR = true;
-
- /**
- * Constant fold float operations? Default is true, flip to avoid consuming
- * precious JTOC slots to hold new constant values.
- */
- public static final boolean CF_FLOAT = true;
-
- /**
- * Constant fold double operations? Default is true, flip to avoid consuming
- * precious JTOC slots to hold new constant values.
- */
- public static final boolean CF_DOUBLE = true;
-
- /**
- * Constant fold field operations? Default is true, flip to avoid consuming
- * precious JTOC slots to hold new constant values.
- */
- public static final boolean CF_FIELDS = false;
-
- /**
- * Constant fold TIB operations? Default is true, flip to avoid consuming
- * precious JTOC slots to hold new constant values.
- */
- public static final boolean CF_TIB = false;
-
- /**
- * Effect of the simplification on Def-Use chains
- */
- public enum DefUseEffect {
- /**
- * Enumeration value to indicate an operation is unchanged, although the
- * order of operands may have been canonicalized and type information
- * strengthened.
- */
- UNCHANGED,
- /**
- * Enumeration value to indicate an operation has been replaced by a move
- * instruction with a constant right hand side.
- */
- MOVE_FOLDED,
- /**
- * Enumeration value to indicate an operation has been replaced by a move
- * instruction with a non-constant right hand side.
- */
- MOVE_REDUCED,
- /**
- * Enumeration value to indicate an operation has been replaced by an
- * unconditional trap instruction.
- */
- TRAP_REDUCED,
- /**
- * Enumeration value to indicate an operation has been replaced by a
- * cheaper, but non-move instruction.
- */
- REDUCED
- }
-
- /**
- * Given an instruction, attempt to simplify it. The instruction will be
- * mutated in place.
- *
- * <p>
- * We don't deal with branching operations here -- doing peephole
- * optimizations of branches is the job of a separate module.
- *
- * @param regpool
- * register pool in case simplification requires a temporary register
- * @param s
- * the instruction to simplify
- * @return one of UNCHANGED, MOVE_FOLDED, MOVE_REDUCED, TRAP_REDUCED, REDUCED
- */
- public static DefUseEffect simplify(OPT_AbstractRegisterPool regpool,
- OPT_Instruction s) {
- DefUseEffect result;
- char opcode = s.getOpcode();
- switch (opcode) {
- // //////////////////
- // GUARD operations
- // //////////////////
- case GUARD_COMBINE_opcode:
- result = guardCombine(s);
- break;
- // //////////////////
- // TRAP operations
- // //////////////////
- case TRAP_IF_opcode:
- result = trapIf(s);
- break;
- case NULL_CHECK_opcode:
- result = nullCheck(s);
- break;
- case INT_ZERO_CHECK_opcode:
- result = intZeroCheck(s);
- break;
- case LONG_ZERO_CHECK_opcode:
- result = longZeroCheck(s);
- break;
- case CHECKCAST_opcode:
- result = checkcast(regpool, s);
- break;
- case CHECKCAST_UNRESOLVED_opcode:
- result = checkcast(regpool, s);
- break;
- case CHECKCAST_NOTNULL_opcode:
- result = checkcastNotNull(s);
- break;
- case INSTANCEOF_opcode:
- result = instanceOf(regpool, s);
- break;
- case INSTANCEOF_NOTNULL_opcode:
- result = instanceOfNotNull(s);
- break;
- case OBJARRAY_STORE_CHECK_opcode:
- result = objarrayStoreCheck(s);
- break;
- case OBJARRAY_STORE_CHECK_NOTNULL_opcode:
- result = objarrayStoreCheckNotNull(s);
- break;
- case MUST_IMPLEMENT_INTERFACE_opcode:
- result = mustImplementInterface(s);
- break;
- // //////////////////
- // Conditional moves
- // //////////////////
- case INT_COND_MOVE_opcode:
- result = intCondMove(s);
- break;
- case LONG_COND_MOVE_opcode:
- result = longCondMove(s);
- break;
- case FLOAT_COND_MOVE_opcode:
- result = floatCondMove(s);
- break;
- case DOUBLE_COND_MOVE_opcode:
- result = doubleCondMove(s);
- break;
- case REF_COND_MOVE_opcode:
- result = refCondMove(s);
- break;
- case GUARD_COND_MOVE_opcode:
- result = guardCondMove(s);
- break;
- // //////////////////
- // INT ALU operations
- // //////////////////
- case BOOLEAN_NOT_opcode:
- result = booleanNot(s);
- break;
- case BOOLEAN_CMP_INT_opcode:
- result = booleanCmpInt(s);
- break;
- case BOOLEAN_CMP_ADDR_opcode:
- result = booleanCmpAddr(s);
- break;
- case BOOLEAN_CMP2_INT_OR_opcode:
- result = booleanCmp2IntOr(s);
- break;
- // case BOOLEAN_CMP2_INT_AND:
- // result = booleanCmp2IntAnd(s);
- // break;
- case INT_ADD_opcode:
- result = intAdd(s);
- break;
- case INT_AND_opcode:
- result = intAnd(s);
- break;
- case INT_DIV_opcode:
- result = intDiv(s);
- break;
- case INT_MUL_opcode:
- result = intMul(regpool, s);
- break;
- case INT_NEG_opcode:
- result = intNeg(s);
- break;
- case INT_NOT_opcode:
- result = intNot(s);
- break;
- case INT_OR_opcode:
- result = intOr(s);
- break;
- case INT_REM_opcode:
- result = intRem(s);
- break;
- case INT_SHL_opcode:
- result = intShl(s);
- break;
- case INT_SHR_opcode:
- result = intShr(s);
- break;
- case INT_SUB_opcode:
- result = intSub(s);
- break;
- case INT_USHR_opcode:
- result = intUshr(s);
- break;
- case INT_XOR_opcode:
- result = intXor(s);
- break;
- // //////////////////
- // WORD ALU operations
- // //////////////////
- case REF_ADD_opcode:
- result = refAdd(s);
- break;
- case REF_AND_opcode:
- result = refAnd(s);
- break;
- case REF_SHL_opcode:
- result = refShl(s);
- break;
- case REF_SHR_opcode:
- result = refShr(s);
- break;
- case REF_NOT_opcode:
- result = refNot(s);
- break;
- case REF_OR_opcode:
- result = refOr(s);
- break;
- case REF_SUB_opcode:
- result = refSub(s);
- break;
- case REF_USHR_opcode:
- result = regUshr(s);
- break;
- case REF_XOR_opcode:
- result = refXor(s);
- break;
- // //////////////////
- // LONG ALU operations
- // //////////////////
- case LONG_ADD_opcode:
- result = longAdd(s);
- break;
- case LONG_AND_opcode:
- result = longAnd(s);
- break;
- case LONG_CMP_opcode:
- result = longCmp(s);
- break;
- case LONG_DIV_opcode:
- result = longDiv(s);
- break;
- case LONG_MUL_opcode:
- result = longMul(s);
- break;
- case LONG_NEG_opcode:
- result = longNeg(s);
- break;
- case LONG_NOT_opcode:
- result = longNot(s);
- break;
- case LONG_OR_opcode:
- result = longOr(s);
- break;
- case LONG_REM_opcode:
- result = longRem(s);
- break;
- case LONG_SHL_opcode:
- result = longShl(s);
- break;
- case LONG_SHR_opcode:
- result = longShr(s);
- break;
- case LONG_SUB_opcode:
- result = longSub(s);
- break;
- case LONG_USHR_opcode:
- result = longUshr(s);
- break;
- case LONG_XOR_opcode:
- result = longXor(s);
- break;
- // //////////////////
- // FLOAT ALU operations
- // //////////////////
- case FLOAT_ADD_opcode:
- result = floatAdd(s);
- break;
- case FLOAT_CMPG_opcode:
- result = floatCmpg(s);
- break;
- case FLOAT_CMPL_opcode:
- result = floatCmpl(s);
- break;
- case FLOAT_DIV_opcode:
- result = floatDiv(s);
- break;
- case FLOAT_MUL_opcode:
- result = floatMul(s);
- break;
- case FLOAT_NEG_opcode:
- result = floatNeg(s);
- break;
- case FLOAT_REM_opcode:
- result = floatRem(s);
- break;
- case FLOAT_SUB_opcode:
- result = floatSub(s);
- break;
- // //////////////////
- // DOUBLE ALU operations
- // //////////////////
- case DOUBLE_ADD_opcode:
- result = doubleAdd(s);
- break;
- case DOUBLE_CMPG_opcode:
- result = doubleCmpg(s);
- break;
- case DOUBLE_CMPL_opcode:
- result = doubleCmpl(s);
- break;
- case DOUBLE_DIV_opcode:
- result = doubleDiv(s);
- break;
- case DOUBLE_MUL_opcode:
- result = doubleMul(s);
- break;
- case DOUBLE_NEG_opcode:
- result = doubleNeg(s);
- break;
- case DOUBLE_REM_opcode:
- result = doubleRem(s);
- break;
- case DOUBLE_SUB_opcode:
- result = doubleSub(s);
- break;
- // //////////////////
- // CONVERSION operations
- // //////////////////
- case DOUBLE_2FLOAT_opcode:
- result = double2Float(s);
- break;
- case DOUBLE_2INT_opcode:
- result = double2Int(s);
- break;
- case DOUBLE_2LONG_opcode:
- result = double2Long(s);
- break;
- case DOUBLE_AS_LONG_BITS_opcode:
- result = doubleAsLongBits(s);
- break;
- case INT_2DOUBLE_opcode:
- result = int2Double(s);
- break;
- case INT_2BYTE_opcode:
- result = int2Byte(s);
- break;
- case INT_2USHORT_opcode:
- result = int2UShort(s);
- break;
- case INT_2FLOAT_opcode:
- result = int2Float(s);
- break;
- case INT_2LONG_opcode:
- result = int2Long(s);
- break;
- case INT_2ADDRSigExt_opcode:
- result = int2AddrSigExt(s);
- break;
- case INT_2ADDRZerExt_opcode:
- result = int2AddrZerExt(s);
- break;
- case LONG_2ADDR_opcode:
- result = long2Addr(s);
- break;
- case INT_2SHORT_opcode:
- result = int2Short(s);
- break;
- case INT_BITS_AS_FLOAT_opcode:
- result = intBitsAsFloat(s);
- break;
- case ADDR_2INT_opcode:
- result = addr2Int(s);
- break;
- case ADDR_2LONG_opcode:
- result = addr2Long(s);
- break;
- case FLOAT_2DOUBLE_opcode:
- result = float2Double(s);
- break;
- case FLOAT_2INT_opcode:
- result = float2Int(s);
- break;
- case FLOAT_2LONG_opcode:
- result = float2Long(s);
- break;
- case FLOAT_AS_INT_BITS_opcode:
- result = floatAsIntBits(s);
- break;
- case LONG_2FLOAT_opcode:
- result = long2Float(s);
- break;
- case LONG_2INT_opcode:
- result = long2Int(s);
- break;
- case LONG_2DOUBLE_opcode:
- result = long2Double(s);
- break;
- case LONG_BITS_AS_DOUBLE_opcode:
- result = longBitsAsDouble(s);
- break;
- // //////////////////
- // Field operations
- // //////////////////
- case ARRAYLENGTH_opcode:
- result = arrayLength(s);
- break;
- case BOUNDS_CHECK_opcode:
- result = boundsCheck(s);
- break;
- case CALL_opcode:
- result = call(s);
- break;
- case GETFIELD_opcode:
- result = getField(s);
- break;
- case GET_OBJ_TIB_opcode:
- result = getObjTib(s);
- break;
- case GET_CLASS_TIB_opcode:
- result = getClassTib(s);
- break;
- case GET_TYPE_FROM_TIB_opcode:
- result = getTypeFromTib(s);
- break;
- case GET_ARRAY_ELEMENT_TIB_FROM_TIB_opcode:
- result = getArrayElementTibFromTib(s);
- break;
- case GET_SUPERCLASS_IDS_FROM_TIB_opcode:
- result = getSuperclassIdsFromTib(s);
- break;
- case GET_DOES_IMPLEMENT_FROM_TIB_opcode:
- result = getDoesImplementFromTib(s);
- break;
- case REF_LOAD_opcode:
- result = refLoad(s);
- break;
- default:
- result = DefUseEffect.UNCHANGED;
- }
- if (VM.VerifyAssertions) {
- switch (result) {
- case MOVE_FOLDED:
- // Check move has constant RHS
- VM._assert(Move.conforms(s)
- && (Move.getVal(s) instanceof OPT_ConstantOperand), "RHS of move "
- + s + " should be constant during simplification of "
- + OPT_OperatorNames.operatorName[opcode]);
- break;
- case MOVE_REDUCED:
- // Check move has non-constant RHS
- VM._assert(Move.conforms(s)
- && !(Move.getVal(s) instanceof OPT_ConstantOperand), "RHS of move "
- + s + " shouldn't be constant during simplification of "
- + OPT_OperatorNames.operatorName[opcode]);
- break;
- default:
- // Nothing to check
- }
- }
- return result;
- }
-
- private static DefUseEffect guardCombine(OPT_Instruction s) {
- OPT_Operand op1 = Binary.getVal1(s);
- OPT_Operand op2 = Binary.getVal2(s);
- if (op1.similar(op2) || (op2 instanceof OPT_TrueGuardOperand)) {
- Move.mutate(s, GUARD_MOVE, Binary.getClearResult(s), op1);
- if (op1 instanceof OPT_TrueGuardOperand) {
- // BOTH true guards: FOLD
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS TrueGuard: MOVE REDUCE
- return DefUseEffect.MOVE_REDUCED;
- }
- } else if (op1 instanceof OPT_TrueGuardOperand) {
- // ONLY OP1 IS TrueGuard: MOVE REDUCE
- Move.mutate(s, GUARD_MOVE, Binary.getClearResult(s), op2);
- return DefUseEffect.MOVE_REDUCED;
- } else {
- return DefUseEffect.UNCHANGED;
- }
- }
-
- private static DefUseEffect trapIf(OPT_Instruction s) {
- {
- OPT_Operand op1 = TrapIf.getVal1(s);
- OPT_Operand op2 = TrapIf.getVal2(s);
- if (op1.isConstant()) {
- if (op2.isConstant()) {
- int willTrap = TrapIf.getCond(s).evaluate(op1, op2);
- if (willTrap == OPT_ConditionOperand.TRUE) {
- Trap.mutate(s, TRAP, TrapIf.getClearGuardResult(s), TrapIf
- .getClearTCode(s));
- return DefUseEffect.TRAP_REDUCED;
- } else if (willTrap == OPT_ConditionOperand.FALSE) {
- Move.mutate(s, GUARD_MOVE, TrapIf.getClearGuardResult(s), TG());
- return DefUseEffect.MOVE_FOLDED;
- }
- } else {
- // canonicalize
- TrapIf.mutate(s, TRAP_IF, TrapIf.getClearGuardResult(s), TrapIf
- .getClearVal2(s), TrapIf.getClearVal1(s), TrapIf.getClearCond(s)
- .flipOperands(), TrapIf.getClearTCode(s));
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect nullCheck(OPT_Instruction s) {
- OPT_Operand ref = NullCheck.getRef(s);
- if (ref.isNullConstant()
- || (ref.isAddressConstant() && ref.asAddressConstant().value.isZero())) {
- Trap.mutate(s, TRAP, NullCheck.getClearGuardResult(s),
- OPT_TrapCodeOperand.NullPtr());
- return DefUseEffect.TRAP_REDUCED;
- } else if (ref.isConstant()) {
- // object, string, class or non-null address constant
-
- // Make the slightly suspect assumption that all non-zero address
- // constants are actually valid pointers. Not necessarily true,
- // but unclear what else we can do.
- Move.mutate(s, GUARD_MOVE, NullCheck.getClearGuardResult(s), TG());
- return DefUseEffect.MOVE_FOLDED;
- } else {
- return DefUseEffect.UNCHANGED;
- }
- }
-
- private static DefUseEffect intZeroCheck(OPT_Instruction s) {
- {
- OPT_Operand op = ZeroCheck.getValue(s);
- if (op.isIntConstant()) {
- int val = op.asIntConstant().value;
- if (val == 0) {
- Trap.mutate(s, TRAP, ZeroCheck.getClearGuardResult(s),
- OPT_TrapCodeOperand.DivByZero());
- return DefUseEffect.TRAP_REDUCED;
- } else {
- Move.mutate(s, GUARD_MOVE, ZeroCheck.getClearGuardResult(s), TG());
- return DefUseEffect.MOVE_FOLDED;
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect longZeroCheck(OPT_Instruction s) {
- {
- OPT_Operand op = ZeroCheck.getValue(s);
- if (op.isLongConstant()) {
- long val = op.asLongConstant().value;
- if (val == 0L) {
- Trap.mutate(s, TRAP, ZeroCheck.getClearGuardResult(s),
- OPT_TrapCodeOperand.DivByZero());
- return DefUseEffect.TRAP_REDUCED;
- } else {
- Move.mutate(s, GUARD_MOVE, ZeroCheck.getClearGuardResult(s), TG());
- return DefUseEffect.MOVE_FOLDED;
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect checkcast(OPT_AbstractRegisterPool regpool,
- OPT_Instruction s) {
- OPT_Operand ref = TypeCheck.getRef(s);
- if (ref.isNullConstant()) {
- Empty.mutate(s, NOP);
- return DefUseEffect.REDUCED;
- } else if (ref.isConstant()) {
- s.operator = CHECKCAST_NOTNULL;
- return checkcastNotNull(s);
- } else {
- VM_TypeReference lhsType = TypeCheck.getType(s).getTypeRef();
- VM_TypeReference rhsType = ref.getType();
- byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType);
- if (ans == OPT_Constants.YES) {
- Empty.mutate(s, NOP);
- return DefUseEffect.REDUCED;
- } else {
- // NOTE: OPT_Constants.NO can't help us because (T)null always succeeds
- return DefUseEffect.UNCHANGED;
- }
- }
- }
-
- private static DefUseEffect checkcastNotNull(OPT_Instruction s) {
- OPT_Operand ref = TypeCheck.getRef(s);
- VM_TypeReference lhsType = TypeCheck.getType(s).getTypeRef();
- VM_TypeReference rhsType = ref.getType();
- byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType);
- if (ans == OPT_Constants.YES) {
- Empty.mutate(s, NOP);
- return DefUseEffect.REDUCED;
- } else if (ans == OPT_Constants.NO) {
- VM_Type rType = rhsType.peekResolvedType();
- if (rType != null && rType.isClassType() && rType.asClass().isFinal()) {
- // only final (or precise) rhs types can be optimized since rhsType may
- // be conservative
- Trap.mutate(s, TRAP, null, OPT_TrapCodeOperand.CheckCast());
- return DefUseEffect.TRAP_REDUCED;
- } else {
- return DefUseEffect.UNCHANGED;
- }
- } else {
- return DefUseEffect.UNCHANGED;
- }
- }
-
- private static DefUseEffect instanceOf(OPT_AbstractRegisterPool regpool,
- OPT_Instruction s) {
- OPT_Operand ref = InstanceOf.getRef(s);
- if (ref.isNullConstant()) {
- Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- } else if (ref.isConstant()) {
- s.operator = INSTANCEOF_NOTNULL;
- return instanceOfNotNull(s);
- } else {
- VM_TypeReference lhsType = InstanceOf.getType(s).getTypeRef();
- VM_TypeReference rhsType = ref.getType();
- byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType);
- // NOTE: OPT_Constants.YES doesn't help because ref may be null and null
- // instanceof T is false
- if (ans == OPT_Constants.NO) {
- VM_Type rType = rhsType.peekResolvedType();
- if (rType != null && rType.isClassType() && rType.asClass().isFinal()) {
- // only final (or precise) rhs types can be optimized since rhsType
- // may be conservative
- Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- return DefUseEffect.UNCHANGED;
- }
- } else {
- return DefUseEffect.UNCHANGED;
- }
- }
- }
-
- private static DefUseEffect instanceOfNotNull(OPT_Instruction s) {
- {
- OPT_Operand ref = InstanceOf.getRef(s);
- VM_TypeReference lhsType = InstanceOf.getType(s).getTypeRef();
- VM_TypeReference rhsType = ref.getType();
- byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType);
- if (ans == OPT_Constants.YES) {
- Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(1));
- return DefUseEffect.MOVE_FOLDED;
- } else if (ans == OPT_Constants.NO) {
- VM_Type rType = rhsType.peekResolvedType();
- if (rType != null && rType.isClassType() && rType.asClass().isFinal()) {
- // only final (or precise) rhs types can be optimized since rhsType
- // may be conservative
- Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect objarrayStoreCheck(OPT_Instruction s) {
- OPT_Operand val = StoreCheck.getVal(s);
- if (val.isNullConstant()) {
- // Writing null into an array is trivially safe
- Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck
- .getClearGuard(s));
- return DefUseEffect.MOVE_REDUCED;
- } else {
- OPT_Operand ref = StoreCheck.getRef(s);
- VM_TypeReference arrayTypeRef = ref.getType();
- VM_Type typeOfIMElem = arrayTypeRef.getInnermostElementType()
- .peekResolvedType();
- if (typeOfIMElem != null) {
- VM_Type typeOfVal = val.getType().peekResolvedType();
- if ((typeOfIMElem == typeOfVal)
- && (typeOfIMElem.isPrimitiveType() || typeOfIMElem.asClass()
- .isFinal())) {
- // Writing something of a final type to an array of that
- // final type is safe
- Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s),
- StoreCheck.getClearGuard(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- }
- if (ref.isConstant()
- && (arrayTypeRef == VM_TypeReference.JavaLangObjectArray)) {
- // We know this to be an array of objects so any store must
- // be safe
- Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s),
- StoreCheck.getClearGuard(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- if (val.isConstant() && ref.isConstant()) {
- // writing a constant value into a constant array
- byte ans = OPT_ClassLoaderProxy.includesType(arrayTypeRef
- .getArrayElementType(), val.getType());
- if (ans == OPT_Constants.YES) {
- // all stores should succeed
- Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s),
- StoreCheck.getClearGuard(s));
- return DefUseEffect.MOVE_REDUCED;
- } else if (ans == OPT_Constants.NO) {
- // all stores will fail
- Trap.mutate(s, TRAP, StoreCheck.getClearGuardResult(s),
- OPT_TrapCodeOperand.StoreCheck());
- return DefUseEffect.TRAP_REDUCED;
- }
- }
- return DefUseEffect.UNCHANGED;
- }
- }
-
- private static DefUseEffect objarrayStoreCheckNotNull(OPT_Instruction s) {
- OPT_Operand val = StoreCheck.getVal(s);
- OPT_Operand ref = StoreCheck.getRef(s);
- VM_TypeReference arrayTypeRef = ref.getType();
- VM_Type typeOfIMElem = arrayTypeRef.getInnermostElementType()
- .peekResolvedType();
- if (typeOfIMElem != null) {
- VM_Type typeOfVal = val.getType().peekResolvedType();
- if ((typeOfIMElem == typeOfVal)
- && (typeOfIMElem.isPrimitiveType() || typeOfIMElem.asClass()
- .isFinal())) {
- // Writing something of a final type to an array of that
- // final type is safe
- Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s),
- StoreCheck.getClearGuard(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- }
- if (ref.isConstant()
- && (arrayTypeRef == VM_TypeReference.JavaLangObjectArray)) {
- // We know this to be an array of objects so any store must
- // be safe
- Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck
- .getClearGuard(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- if (val.isConstant() && ref.isConstant()) {
- // writing a constant value into a constant array
- byte ans = OPT_ClassLoaderProxy.includesType(arrayTypeRef
- .getArrayElementType(), val.getType());
- if (ans == OPT_Constants.YES) {
- // all stores should succeed
- Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s),
- StoreCheck.getClearGuard(s));
- return DefUseEffect.MOVE_REDUCED;
- } else if (ans == OPT_Constants.NO) {
- // all stores will fail
- Trap.mutate(s, TRAP, StoreCheck.getClearGuardResult(s),
- OPT_TrapCodeOperand.StoreCheck());
- return DefUseEffect.TRAP_REDUCED;
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect mustImplementInterface(OPT_Instruction s) {
- OPT_Operand ref = TypeCheck.getRef(s);
- if (ref.isNullConstant()) {
- // Possible sitatution from constant propagation. This operation
- // is really a nop as a null_check should have happened already
- Trap.mutate(s, TRAP, null, OPT_TrapCodeOperand.NullPtr());
- return DefUseEffect.TRAP_REDUCED;
- } else {
- VM_TypeReference lhsType = TypeCheck.getType(s).getTypeRef(); // the
- // interface
- // that must
- // be
- // implemented
- VM_TypeReference rhsType = ref.getType(); // our type
- byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType);
- if (ans == OPT_Constants.YES) {
- Empty.mutate(s, NOP);
- return DefUseEffect.REDUCED;
- } else if (ans == OPT_Constants.NO) {
- VM_Type rType = rhsType.peekResolvedType();
- if (rType != null && rType.isClassType() && rType.asClass().isFinal()) {
- // only final (or precise) rhs types can be optimized since rhsType
- // may be conservative
- Trap.mutate(s, TRAP, null, OPT_TrapCodeOperand.MustImplement());
- return DefUseEffect.TRAP_REDUCED;
- }
- }
- return DefUseEffect.UNCHANGED;
- }
- }
-
- private static DefUseEffect intCondMove(OPT_Instruction s) {
- {
- OPT_Operand val1 = CondMove.getVal1(s);
- OPT_Operand val2 = CondMove.getVal2(s);
- int cond = CondMove.getCond(s).evaluate(val1, val2);
- if (cond != OPT_ConditionOperand.UNKNOWN) {
- // BOTH CONSTANTS OR SIMILAR: FOLD
- OPT_Operand val = (cond == OPT_ConditionOperand.TRUE) ? CondMove
- .getClearTrueValue(s) : CondMove.getClearFalseValue(s);
- Move.mutate(s, INT_MOVE, CondMove.getClearResult(s), val);
- return val.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- if (val1.isConstant() && !val2.isConstant()) {
- // Canonicalize by switching operands and fliping code.
- OPT_Operand tmp = CondMove.getClearVal1(s);
- CondMove.setVal1(s, CondMove.getClearVal2(s));
- CondMove.setVal2(s, tmp);
- CondMove.getCond(s).flipOperands();
- }
- OPT_Operand tv = CondMove.getTrueValue(s);
- OPT_Operand fv = CondMove.getFalseValue(s);
- if (tv.similar(fv)) {
- Move.mutate(s, INT_MOVE, CondMove.getClearResult(s), tv);
- return tv.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- if (tv.isIntConstant() && fv.isIntConstant()
- && !CondMove.getCond(s).isFLOATINGPOINT()) {
- int itv = tv.asIntConstant().value;
- int ifv = fv.asIntConstant().value;
- OPT_Operator op = null;
- if (val1.isLong()) {
- op = BOOLEAN_CMP_LONG;
- } else if (val1.isFloat()) {
- op = BOOLEAN_CMP_FLOAT;
- } else if (val1.isDouble()) {
- op = BOOLEAN_CMP_DOUBLE;
- } else {
- op = BOOLEAN_CMP_INT;
- }
- if (itv == 1 && ifv == 0) {
- BooleanCmp.mutate(s, op, CondMove.getClearResult(s), CondMove
- .getClearVal1(s), CondMove.getClearVal2(s), CondMove
- .getClearCond(s), new OPT_BranchProfileOperand());
- return DefUseEffect.REDUCED;
- }
- if (itv == 0 && ifv == 1) {
- BooleanCmp.mutate(s, op, CondMove.getClearResult(s), CondMove
- .getClearVal1(s), CondMove.getClearVal2(s), CondMove
- .getClearCond(s).flipCode(), new OPT_BranchProfileOperand());
- return DefUseEffect.REDUCED;
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect longCondMove(OPT_Instruction s) {
- {
- OPT_Operand val1 = CondMove.getVal1(s);
- OPT_Operand val2 = CondMove.getVal2(s);
- int cond = CondMove.getCond(s).evaluate(val1, val2);
- if (cond != OPT_ConditionOperand.UNKNOWN) {
- // BOTH CONSTANTS OR SIMILAR: FOLD
- OPT_Operand val = (cond == OPT_ConditionOperand.TRUE) ? CondMove
- .getClearTrueValue(s) : CondMove.getClearFalseValue(s);
- Move.mutate(s, LONG_MOVE, CondMove.getClearResult(s), val);
- return val.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- if (val1.isConstant() && !val2.isConstant()) {
- // Canonicalize by switching operands and fliping code.
- OPT_Operand tmp = CondMove.getClearVal1(s);
- CondMove.setVal1(s, CondMove.getClearVal2(s));
- CondMove.setVal2(s, tmp);
- CondMove.getCond(s).flipOperands();
- }
- OPT_Operand tv = CondMove.getTrueValue(s);
- OPT_Operand fv = CondMove.getFalseValue(s);
- if (tv.similar(fv)) {
- Move.mutate(s, LONG_MOVE, CondMove.getClearResult(s), tv);
- return tv.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- if (tv.isLongConstant() && fv.isLongConstant()
- && !CondMove.getCond(s).isFLOATINGPOINT()) {
- long itv = tv.asLongConstant().value;
- long ifv = fv.asLongConstant().value;
- OPT_Operator op = null;
- if (val1.isLong()) {
- op = BOOLEAN_CMP_LONG;
- } else if (val1.isFloat()) {
- op = BOOLEAN_CMP_FLOAT;
- } else if (val1.isDouble()) {
- op = BOOLEAN_CMP_DOUBLE;
- } else {
- op = BOOLEAN_CMP_INT;
- }
- if (itv == 1 && ifv == 0) {
- BooleanCmp.mutate(s, op, CondMove.getClearResult(s), CondMove
- .getClearVal1(s), CondMove.getClearVal2(s), CondMove
- .getClearCond(s), new OPT_BranchProfileOperand());
- return DefUseEffect.REDUCED;
- }
- if (itv == 0 && ifv == 1) {
- BooleanCmp.mutate(s, op, CondMove.getClearResult(s), CondMove
- .getClearVal1(s), CondMove.getClearVal2(s), CondMove
- .getClearCond(s).flipCode(), new OPT_BranchProfileOperand());
- return DefUseEffect.REDUCED;
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect floatCondMove(OPT_Instruction s) {
- {
- OPT_Operand val1 = CondMove.getVal1(s);
- OPT_Operand val2 = CondMove.getVal2(s);
- int cond = CondMove.getCond(s).evaluate(val1, val2);
- if (cond != OPT_ConditionOperand.UNKNOWN) {
- // BOTH CONSTANTS OR SIMILAR: FOLD
- OPT_Operand val = (cond == OPT_ConditionOperand.TRUE) ? CondMove
- .getClearTrueValue(s) : CondMove.getClearFalseValue(s);
- Move.mutate(s, FLOAT_MOVE, CondMove.getClearResult(s), val);
- return val.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- if (val1.isConstant() && !val2.isConstant()) {
- // Canonicalize by switching operands and fliping code.
- OPT_Operand tmp = CondMove.getClearVal1(s);
- CondMove.setVal1(s, CondMove.getClearVal2(s));
- CondMove.setVal2(s, tmp);
- CondMove.getCond(s).flipOperands();
- }
- OPT_Operand tv = CondMove.getTrueValue(s);
- OPT_Operand fv = CondMove.getFalseValue(s);
- if (tv.similar(fv)) {
- Move.mutate(s, FLOAT_MOVE, CondMove.getClearResult(s), tv);
- return tv.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect doubleCondMove(OPT_Instruction s) {
- {
- OPT_Operand val1 = CondMove.getVal1(s);
- OPT_Operand val2 = CondMove.getVal2(s);
- int cond = CondMove.getCond(s).evaluate(val1, val2);
- if (cond != OPT_ConditionOperand.UNKNOWN) {
- // BOTH CONSTANTS OR SIMILAR: FOLD
- OPT_Operand val = (cond == OPT_ConditionOperand.TRUE) ? CondMove
- .getClearTrueValue(s) : CondMove.getClearFalseValue(s);
- Move.mutate(s, DOUBLE_MOVE, CondMove.getClearResult(s), val);
- return val.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- if (val1.isConstant() && !val2.isConstant()) {
- // Canonicalize by switching operands and fliping code.
- OPT_Operand tmp = CondMove.getClearVal1(s);
- CondMove.setVal1(s, CondMove.getClearVal2(s));
- CondMove.setVal2(s, tmp);
- CondMove.getCond(s).flipOperands();
- }
- OPT_Operand tv = CondMove.getTrueValue(s);
- OPT_Operand fv = CondMove.getFalseValue(s);
- if (tv.similar(fv)) {
- Move.mutate(s, DOUBLE_MOVE, CondMove.getClearResult(s), tv);
- return tv.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect refCondMove(OPT_Instruction s) {
- {
- OPT_Operand val1 = CondMove.getVal1(s);
- if (val1.isConstant()) {
- OPT_Operand val2 = CondMove.getVal2(s);
- if (val2.isConstant()) {
- // BOTH CONSTANTS: FOLD
- int cond = CondMove.getCond(s).evaluate(val1, val2);
- if (cond != OPT_ConditionOperand.UNKNOWN) {
- OPT_Operand val = (cond == OPT_ConditionOperand.TRUE) ? CondMove
- .getClearTrueValue(s) : CondMove.getClearFalseValue(s);
- Move.mutate(s, REF_MOVE, CondMove.getClearResult(s), val);
- return val.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- } else {
- // Canonicalize by switching operands and fliping code.
- OPT_Operand tmp = CondMove.getClearVal1(s);
- CondMove.setVal1(s, CondMove.getClearVal2(s));
- CondMove.setVal2(s, tmp);
- CondMove.getCond(s).flipOperands();
- }
- }
- if (CondMove.getTrueValue(s).similar(CondMove.getFalseValue(s))) {
- OPT_Operand val = CondMove.getClearTrueValue(s);
- Move.mutate(s, REF_MOVE, CondMove.getClearResult(s), val);
- return val.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect guardCondMove(OPT_Instruction s) {
- {
- OPT_Operand val1 = CondMove.getVal1(s);
- if (val1.isConstant()) {
- OPT_Operand val2 = CondMove.getVal2(s);
- if (val2.isConstant()) {
- // BOTH CONSTANTS: FOLD
- int cond = CondMove.getCond(s).evaluate(val1, val2);
- if (cond == OPT_ConditionOperand.UNKNOWN) {
- OPT_Operand val = (cond == OPT_ConditionOperand.TRUE) ? CondMove
- .getClearTrueValue(s) : CondMove.getClearFalseValue(s);
- Move.mutate(s, GUARD_MOVE, CondMove.getClearResult(s), val);
- return val.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- } else {
- // Canonicalize by switching operands and fliping code.
- OPT_Operand tmp = CondMove.getClearVal1(s);
- CondMove.setVal1(s, CondMove.getClearVal2(s));
- CondMove.setVal2(s, tmp);
- CondMove.getCond(s).flipOperands();
- }
- }
- if (CondMove.getTrueValue(s).similar(CondMove.getFalseValue(s))) {
- OPT_Operand val = CondMove.getClearTrueValue(s);
- Move.mutate(s, GUARD_MOVE, CondMove.getClearResult(s), val);
- return val.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect booleanNot(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op = Unary.getVal(s);
- if (op.isIntConstant()) {
- // CONSTANT: FOLD
- int val = op.asIntConstant().value;
- if (val == 0) {
- Move.mutate(s, INT_MOVE, Unary.getClearResult(s), IC(1));
- } else {
- Move.mutate(s, INT_MOVE, Unary.getClearResult(s), IC(0));
- }
- return DefUseEffect.MOVE_FOLDED;
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect booleanCmpInt(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op1 = BooleanCmp.getVal1(s);
- OPT_Operand op2 = BooleanCmp.getVal2(s);
- if (op1.isConstant()) {
- if (op2.isConstant()) {
- // BOTH CONSTANTS: FOLD
- int cond = BooleanCmp.getCond(s).evaluate(op1, op2);
- if (cond != OPT_ConditionOperand.UNKNOWN) {
- Move.mutate(s, INT_MOVE, BooleanCmp.getResult(s),
- (cond == OPT_ConditionOperand.TRUE) ? IC(1) : IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- } else {
- // Canonicalize by switching operands and fliping code.
- OPT_Operand tmp = BooleanCmp.getClearVal1(s);
- BooleanCmp.setVal1(s, BooleanCmp.getClearVal2(s));
- BooleanCmp.setVal2(s, tmp);
- BooleanCmp.getCond(s).flipOperands();
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect booleanCmpAddr(OPT_Instruction s) {
- if (CF_ADDR) {
- OPT_Operand op1 = BooleanCmp.getVal1(s);
- OPT_Operand op2 = BooleanCmp.getVal2(s);
- if (op1.isConstant()) {
- if (op2.isConstant()) {
- // BOTH CONSTANTS: FOLD
- int cond = BooleanCmp.getCond(s).evaluate(op1, op2);
- if (cond != OPT_ConditionOperand.UNKNOWN) {
- Move.mutate(s, REF_MOVE, BooleanCmp.getResult(s),
- (cond == OPT_ConditionOperand.TRUE) ? IC(1) : IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- } else {
- // Canonicalize by switching operands and fliping code.
- OPT_Operand tmp = BooleanCmp.getClearVal1(s);
- BooleanCmp.setVal1(s, BooleanCmp.getClearVal2(s));
- BooleanCmp.setVal2(s, tmp);
- BooleanCmp.getCond(s).flipOperands();
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect booleanCmp2IntOr(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op1 = BooleanCmp2.getVal1(s);
- OPT_Operand op2 = BooleanCmp2.getVal2(s);
- if (op1.isConstant()) {
- if (op2.isConstant()) {
- // 1st 2 operands are constants, can fold if result is true
- int cond1 = BooleanCmp2.getCond1(s).evaluate(op1, op2);
- if (cond1 == OPT_ConditionOperand.TRUE) {
- Move.mutate(s, REF_MOVE, BooleanCmp2.getResult(s), IC(1));
- return DefUseEffect.MOVE_FOLDED;
- } else if (cond1 == OPT_ConditionOperand.FALSE) {
- BooleanCmp.mutate(s, BOOLEAN_CMP_INT, BooleanCmp2.getResult(s),
- BooleanCmp2.getVal3(s), BooleanCmp2.getVal4(s), BooleanCmp2
- .getCond2(s), BooleanCmp2.getBranchProfile2(s));
- DefUseEffect result = booleanCmpInt(s);
- return (result == DefUseEffect.UNCHANGED) ? DefUseEffect.REDUCED
- : result;
- }
- }
- }
- OPT_Operand op3 = BooleanCmp2.getVal3(s);
- OPT_Operand op4 = BooleanCmp2.getVal4(s);
- if (op3.isConstant()) {
- if (op4.isConstant()) {
- // 3rd and 4th operands are constants, can fold if result is true
- int cond2 = BooleanCmp2.getCond1(s).evaluate(op3, op4);
- if (cond2 == OPT_ConditionOperand.TRUE) {
- Move.mutate(s, REF_MOVE, BooleanCmp2.getResult(s), IC(1));
- return DefUseEffect.MOVE_FOLDED;
- } else if (cond2 == OPT_ConditionOperand.FALSE) {
- BooleanCmp.mutate(s, BOOLEAN_CMP_INT, BooleanCmp2.getResult(s),
- BooleanCmp2.getVal1(s), BooleanCmp2.getVal2(s), BooleanCmp2
- .getCond1(s), BooleanCmp2.getBranchProfile1(s));
- DefUseEffect result = booleanCmpInt(s);
- return (result == DefUseEffect.UNCHANGED) ? DefUseEffect.REDUCED
- : result;
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intAdd(OPT_Instruction s) {
- if (CF_INT) {
- canonicalizeCommutativeOperator(s);
- OPT_Operand op2 = Binary.getVal2(s);
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
- OPT_Operand op1 = Binary.getVal1(s);
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 + val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2 == 0) {
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intAnd(OPT_Instruction s) {
- if (CF_INT) {
- canonicalizeCommutativeOperator(s);
- OPT_Operand op1 = Binary.getVal1(s);
- OPT_Operand op2 = Binary.getVal2(s);
- if (op1.similar(op2)) {
- // THE SAME OPERAND: x & x == x
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return op1.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 & val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2 == 0) { // x & 0 == 0
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- if (val2 == -1) { // x & -1 == x & 0xffffffff == x
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intDiv(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op1 = GuardedBinary.getVal1(s);
- OPT_Operand op2 = GuardedBinary.getVal2(s);
- if (op1.similar(op2)) {
- // THE SAME OPERAND: x / x == 1
- Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), IC(1));
- return DefUseEffect.MOVE_FOLDED;
- }
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
- if (val2 == 0) {
- // TODO: This instruction is actually unreachable.
- // There will be an INT_ZERO_CHECK
- // guarding this instruction that will result in an
- // ArithmeticException. We
- // should probabbly just remove the INT_DIV as dead code.
- return DefUseEffect.UNCHANGED;
- }
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), IC(val1
- / val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2 == 1) { // x / 1 == x;
- Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s),
- GuardedBinary.getClearVal1(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- // x / c == x >> (log c) if c is power of 2
- int power = PowerOf2(val2);
- if (power != -1) {
- Binary.mutate(s, INT_SHR, GuardedBinary.getClearResult(s),
- GuardedBinary.getClearVal1(s), IC(power));
- return DefUseEffect.REDUCED;
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intMul(OPT_AbstractRegisterPool regpool,
- OPT_Instruction s) {
- if (CF_INT) {
- canonicalizeCommutativeOperator(s);
- OPT_Operand op2 = Binary.getVal2(s);
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
- OPT_Operand op1 = Binary.getVal1(s);
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 * val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2 == -1) { // x * -1 == -x
- Unary.mutate(s, INT_NEG, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.REDUCED;
- }
- if (val2 == 0) { // x * 0 == 0
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- if (val2 == 1) { // x * 1 == x
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- // try to reduce x*c into shift and adds, but only if cost is cheap
- if (s.getPrev() != null) {
- // don't attempt to reduce if this instruction isn't
- // part of a well-formed sequence
- int cost = 0;
- for (int i = 1; i < BITS_IN_INT; i++) {
- if ((val2 & (1 << i)) != 0) {
- // each 1 requires a shift and add
- cost++;
- }
- }
- if (cost < 5) {
- // generate shift and adds
- OPT_RegisterOperand val1Operand = Binary.getClearVal1(s)
- .asRegister();
- OPT_RegisterOperand resultOperand = regpool.makeTempInt();
- OPT_Instruction move;
- if ((val2 & 1) == 1) {
- // result = val1 * 1
- move = Move.create(INT_MOVE, resultOperand, val1Operand);
- } else {
- // result = 0
- move = Move.create(INT_MOVE, resultOperand, IC(0));
- }
- move.copyPosition(s);
- s.insertBefore(move);
- for (int i = 1; i < BITS_IN_INT; i++) {
- if ((val2 & (1 << i)) != 0) {
- OPT_RegisterOperand tempInt = regpool.makeTempInt();
- OPT_Instruction shift = Binary.create(INT_SHL, tempInt,
- val1Operand.copyRO(), IC(i));
- shift.copyPosition(s);
- s.insertBefore(shift);
- OPT_Instruction add = Binary.create(INT_ADD, resultOperand
- .copyRO(), resultOperand.copyRO(), tempInt.copyRO());
- add.copyPosition(s);
- s.insertBefore(add);
- }
- }
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), resultOperand
- .copyRO());
- return DefUseEffect.REDUCED;
- }
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intNeg(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op = Unary.getVal(s);
- if (op.isIntConstant()) {
- // CONSTANT: FOLD
- int val = op.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Unary.getClearResult(s), IC(-val));
- return DefUseEffect.MOVE_FOLDED;
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intNot(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op = Unary.getVal(s);
- if (op.isIntConstant()) {
- // CONSTANT: FOLD
- int val = op.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Unary.getClearResult(s), IC(~val));
- return DefUseEffect.MOVE_FOLDED;
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intOr(OPT_Instruction s) {
- if (CF_INT) {
- canonicalizeCommutativeOperator(s);
- OPT_Operand op1 = Binary.getVal1(s);
- OPT_Operand op2 = Binary.getVal2(s);
- if (op1.similar(op2)) {
- // THE SAME OPERAND: x | x == x
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return op1.isConstant() ? DefUseEffect.MOVE_FOLDED
- : DefUseEffect.MOVE_REDUCED;
- }
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 | val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2 == -1) { // x | -1 == x | 0xffffffff == 0xffffffff == -1
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(-1));
- return DefUseEffect.MOVE_FOLDED;
- }
- if (val2 == 0) { // x | 0 == x
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intRem(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op1 = GuardedBinary.getVal1(s);
- OPT_Operand op2 = GuardedBinary.getVal2(s);
- if (op1.similar(op2)) {
- // THE SAME OPERAND: x % x == 0
- Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
- if (val2 == 0) {
- // TODO: This instruction is actually unreachable.
- // There will be an INT_ZERO_CHECK
- // guarding this instruction that will result in an
- // ArithmeticException. We
- // should probabbly just remove the INT_REM as dead code.
- return DefUseEffect.UNCHANGED;
- }
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), IC(val1
- % val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if ((val2 == 1) || (val2 == -1)) { // x % 1 == 0
- Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intShl(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op2 = Binary.getVal2(s);
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
- OPT_Operand op1 = Binary.getVal1(s);
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 << val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2 == 0) { // x << 0 == x
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- if (val2 >= BITS_IN_INT) { // x << 32 == 0
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intShr(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op2 = Binary.getVal2(s);
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
- OPT_Operand op1 = Binary.getVal1(s);
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 >> val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2 == 0) { // x >> 0 == x
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intSub(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op1 = Binary.getVal1(s);
- OPT_Operand op2 = Binary.getVal2(s);
- if (op1.similar(op2)) {
- // THE SAME OPERAND: x - x == 0
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 - val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2 == 0) { // x - 0 == x
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- // x - c = x + -c
- // prefer adds, since some architectures have addi but not subi
- Binary.mutate(s, INT_ADD, Binary.getClearResult(s), Binary
- .getClearVal1(s), IC(-val2));
- return DefUseEffect.REDUCED;
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intUshr(OPT_Instruction s) {
- if (CF_INT) {
- OPT_Operand op2 = Binary.getVal2(s);
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
- OPT_Operand op1 = Binary.getVal1(s);
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 >>> val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2 == 0) { // x >>> 0 == x
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- if (val2 >= BITS_IN_INT) { // x >>> 32 == 0
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect intXor(OPT_Instruction s) {
- if (CF_INT) {
- canonicalizeCommutativeOperator(s);
- OPT_Operand op1 = Binary.getVal1(s);
- OPT_Operand op2 = Binary.getVal2(s);
- if (op1.similar(op2)) {
- // THE SAME OPERAND: x ^ x == 0
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0));
- return DefUseEffect.MOVE_FOLDED;
- }
- if (op2.isIntConstant()) {
- int val2 = op2.asIntConstant().value;
-
- if (op1.isIntConstant()) {
- // BOTH CONSTANTS: FOLD
- int val1 = op1.asIntConstant().value;
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 ^ val2));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2 == -1) { // x ^ -1 == x ^ 0xffffffff = ~x
- Unary.mutate(s, INT_NOT, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.REDUCED;
- }
- if (val2 == 0) { // x ^ 0 == x
- Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary
- .getClearVal1(s));
- return DefUseEffect.MOVE_REDUCED;
- }
- }
- }
- }
- return DefUseEffect.UNCHANGED;
- }
-
- private static DefUseEffect refAdd(OPT_Instruction s) {
- if (CF_ADDR) {
- canonicalizeCommutativeOperator(s);
- OPT_Operand op2 = Binary.getVal2(s);
- if (op2.isConstant() && !op2.isObjectConstant()) {
- Address val2 = getAddressValue(op2);
- OPT_Operand op1 = Binary.getVal1(s);
- if (op1.isConstant() && !op1.isObjectConstant()) {
- // BOTH CONSTANTS: FOLD
- Address val1 = getAddressValue(op1);
- Move.mutate(s, REF_MOVE, Binary.getClearResult(s), AC(val1.plus(val2
- .toWord().toOffset())));
- return DefUseEffect.MOVE_FOLDED;
- } else {
- // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS
- if (val2.isZero()) { // x + 0 == x
- if (op1.isIntLike()) {
- ...
[truncated message content] |
|
From: <mic...@us...> - 2007-08-06 10:19:14
|
Revision: 155
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=155&view=rev
Author: michael_baer
Date: 2007-08-06 02:37:44 -0700 (Mon, 06 Aug 2007)
Log Message:
-----------
Exchanged loop by system.arraycopy
Modified Paths:
--------------
src/org/binarytranslator/arch/x86/decoder/X86_FlagLaziness.java
Modified: src/org/binarytranslator/arch/x86/decoder/X86_FlagLaziness.java
===================================================================
--- src/org/binarytranslator/arch/x86/decoder/X86_FlagLaziness.java 2007-08-02 13:59:57 UTC (rev 154)
+++ src/org/binarytranslator/arch/x86/decoder/X86_FlagLaziness.java 2007-08-06 09:37:44 UTC (rev 155)
@@ -31,9 +31,7 @@
}
X86_FlagLaziness(byte[] flagLaziness) {
- for (int i = 0; i < this.flagLaziness.length; i++) {
- this.flagLaziness[i] = flagLaziness[i];
- }
+ System.arraycopy(flagLaziness, 0, this.flagLaziness, 0, flagLaziness.length);
}
public Object clone() {
@@ -91,9 +89,7 @@
Key(int pc, byte[] flagLaziness) {
this.pc = pc;
- for (int i = 0; i < flagLaziness.length; i++) {
- this.flagLaziness[i] = flagLaziness[i];
- }
+ System.arraycopy(flagLaziness, 0, this.flagLaziness, 0, flagLaziness.length);
}
public String toString() {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-02 13:59:59
|
Revision: 154
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=154&view=rev
Author: michael_baer
Date: 2007-08-02 06:59:57 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
- Corrected bug in staged emulation controller
- added javadoc
Modified Paths:
--------------
src/org/binarytranslator/DBT_Options.java
src/org/binarytranslator/Main.java
src/org/binarytranslator/generic/execution/InterpreterController.java
src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java
src/org/binarytranslator/generic/execution/StagedEmulationController.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-08-02 12:22:44 UTC (rev 153)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-02 13:59:57 UTC (rev 154)
@@ -90,6 +90,9 @@
/** GDB stub port */
public static int gdbStubPort = 1234;
+ /** Just a temporary variable for testing. It describes, when the staged emulation controller switches from interpretation to translation. */
+ public static int minTraceValue = 20;
+
/** Print debug information during the translation of instructions. */
public static boolean debugTranslation = true;
@@ -153,49 +156,52 @@
}
/** Parses a single argument into the options class. */
- private static void parseSingleArgument(String arg, String value) {
+ private static void parseSingleArgument(String key, String value) {
- if (!arg.startsWith("-X:dbt:")) {
+ if (!key.startsWith("-X:dbt:")) {
throw new Error("Invalid argument. Argument prefix '-X:dbt:' expected.");
}
- arg = arg.substring(7);
+ key = key.substring(7);
- if (arg.equalsIgnoreCase("debugInstr")) {
+ if (key.equalsIgnoreCase("debugInstr")) {
debugInstr = Boolean.parseBoolean(value);
- } else if (arg.equalsIgnoreCase("debugRuntime")) {
+ } else if (key.equalsIgnoreCase("debugRuntime")) {
debugRuntime = Boolean.parseBoolean(value);
- } else if (arg.equalsIgnoreCase("debugBranchResolution")) {
+ } else if (key.equalsIgnoreCase("debugBranchResolution")) {
debugBranchResolution = Boolean.parseBoolean(value);
- } else if (arg.equalsIgnoreCase("debugMemory")) {
+ } else if (key.equalsIgnoreCase("debugMemory")) {
debugMemory = Boolean.parseBoolean(value);
- } else if (arg.equalsIgnoreCase("debugSyscall")) {
+ } else if (key.equalsIgnoreCase("debugSyscall")) {
debugSyscall = Boolean.parseBoolean(value);
- } else if (arg.equalsIgnoreCase("debugSyscallMore")) {
+ } else if (key.equalsIgnoreCase("debugSyscallMore")) {
debugSyscallMore = Boolean.parseBoolean(value);
- } else if (arg.equalsIgnoreCase("instrOpt0")) {
+ } else if (key.equalsIgnoreCase("instrOpt0")) {
instrOpt0 = Integer.parseInt(value);
- } else if (arg.equalsIgnoreCase("instrOpt1")) {
+ } else if (key.equalsIgnoreCase("instrOpt1")) {
instrOpt1 = Integer.parseInt(value);
- } else if (arg.equalsIgnoreCase("instrOpt2")) {
+ } else if (key.equalsIgnoreCase("instrOpt2")) {
instrOpt2 = Integer.parseInt(value);
- } else if (arg.equalsIgnoreCase("singleInstrTranslation")) {
+ } else if (key.equalsIgnoreCase("singleInstrTranslation")) {
singleInstrTranslation = Boolean.parseBoolean(value);
- } else if (arg.equalsIgnoreCase("resolveDirectBranchesFirst")) {
+ } else if (key.equalsIgnoreCase("resolveDirectBranchesFirst")) {
resolveDirectBranchesFirst = Boolean.parseBoolean(value);
- } else if (arg.equalsIgnoreCase("gdbStub")) {
+ } else if (key.equalsIgnoreCase("gdbStub")) {
gdbStub = Boolean.parseBoolean(value);
- } else if (arg.equalsIgnoreCase("gdbStubPort")) {
+ } else if (key.equalsIgnoreCase("gdbStubPort")) {
gdbStubPort = Integer.parseInt(value);
- } else if (arg.equalsIgnoreCase("controller")) {
+ } else if (key.equalsIgnoreCase("controller")) {
executionController = ExecutionController.Type.valueOf(value);
- } else if (arg.equalsIgnoreCase("loadProfile")) {
- loadProfileFromFile = arg;
- } else if (arg.equalsIgnoreCase("saveProfile")) {
- saveProfileToFile = arg;
+ } else if (key.equalsIgnoreCase("loadProfile")) {
+ loadProfileFromFile = value;
+ } else if (key.equalsIgnoreCase("saveProfile")) {
+ saveProfileToFile = value;
+ } else if (key.equalsIgnoreCase("minTraceValue")) {
+ minTraceValue = Integer.parseInt(value);
}
+
else {
- throw new Error("Unknown DBT option: " + arg);
+ throw new Error("Unknown DBT option: " + key);
}
}
Modified: src/org/binarytranslator/Main.java
===================================================================
--- src/org/binarytranslator/Main.java 2007-08-02 12:22:44 UTC (rev 153)
+++ src/org/binarytranslator/Main.java 2007-08-02 13:59:57 UTC (rev 154)
@@ -105,7 +105,7 @@
//on SUN's VM, only the interpreter has been tested
if (DBT_Options.buildForSunVM) {
- DBT_Options.executionController = ExecutionController.Type.PredecodingInterpreter;
+ DBT_Options.executionController = ExecutionController.Type.StagedEmulation;
}
//load a previously saved branch profile from file, if the user requested it
Modified: src/org/binarytranslator/generic/execution/InterpreterController.java
===================================================================
--- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-08-02 12:22:44 UTC (rev 153)
+++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-08-02 13:59:57 UTC (rev 154)
@@ -1,9 +1,12 @@
package org.binarytranslator.generic.execution;
-import org.binarytranslator.DBT_Options;
import org.binarytranslator.generic.decoder.Interpreter;
import org.binarytranslator.generic.os.process.ProcessSpace;
+/**
+ * Implements straight-forward interpretation using the {@link Interpreter}
+ * and {@link Interpreter.Instruction} interfaces.
+ */
public class InterpreterController extends ExecutionController {
public InterpreterController(ProcessSpace ps) {
Modified: src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java
===================================================================
--- src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java 2007-08-02 12:22:44 UTC (rev 153)
+++ src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java 2007-08-02 13:59:57 UTC (rev 154)
@@ -3,6 +3,12 @@
import org.binarytranslator.generic.decoder.Interpreter;
import org.binarytranslator.generic.os.process.ProcessSpace;
+/**
+ * Implements straight-forward interpretation using the {@link Interpreter}
+ * and {@link Interpreter.Instruction} interfaces.
+ *
+ * Additionally, this controller performs profiling during the interpretation.
+ */
public class ProfilingInterpreterController extends ExecutionController {
public ProfilingInterpreterController(ProcessSpace ps) {
Modified: src/org/binarytranslator/generic/execution/StagedEmulationController.java
===================================================================
--- src/org/binarytranslator/generic/execution/StagedEmulationController.java 2007-08-02 12:22:44 UTC (rev 153)
+++ src/org/binarytranslator/generic/execution/StagedEmulationController.java 2007-08-02 13:59:57 UTC (rev 154)
@@ -13,24 +13,46 @@
import org.binarytranslator.vmInterface.DynamicCodeRunner;
import org.jikesrvm.ArchitectureSpecific.VM_CodeArray;
+/**
+ * This controller implements staged emulation, i.e. switching between interpretation
+ * and translation dynamically.
+ *
+ */
public class StagedEmulationController extends ExecutionController {
- private final class Trace {
- public final List<Interpreter.Instruction> instructions;
+ /** Represents a dynamic basic block of instructions. */
+ private final class DynamicBasicBlock {
+ /** The instructions within this dynamic basic block. */
+ public List<Interpreter.Instruction> instructions;
+
+ /** A value describing how "hot" the basic block is, i.e. how often it has been executed.*/
public int value;
+
+ /** A handle to the compiled version of this dynamic basic block or null, if there is none. */
public DBT_Trace compiledTrace;
- public Trace(List<Interpreter.Instruction> instructions) {
+ public DynamicBasicBlock(List<Interpreter.Instruction> instructions) {
this.instructions = instructions;
value = 0;
}
}
- private final HashMap<Integer, Trace> traceCache = new HashMap<Integer, Trace>();
+ /** Maps a dynamic basic block to the address of the first instruction within that block. */
+ private final HashMap<Integer, DynamicBasicBlock> traceCache = new HashMap<Integer, DynamicBasicBlock>();
+
+ /** The interpreter that is used to perform the actual execution of single instructions. */
private final Interpreter interpreter;
- private Trace getTrace(int pc) {
- Trace cachedTrace = traceCache.get(pc);
+ /**
+ * Returns the dynamic basic block starting at address <code>pc</code>.
+ *
+ * @param pc
+ * The starting address of a dynamic basic block.
+ * @return
+ * An object representation of the dynamic basic block.
+ */
+ private DynamicBasicBlock getBlock(int pc) {
+ DynamicBasicBlock cachedTrace = traceCache.get(pc);
if (cachedTrace != null)
return cachedTrace;
@@ -46,7 +68,7 @@
//is the successor to this instruction known?
if (pc == -1) {
//No, so stop and create a trace from the decoded instructions
- Trace newTrace = new Trace(instructions);
+ DynamicBasicBlock newTrace = new DynamicBasicBlock(instructions);
if (instructions.size() > 3) {
//add this trace to the trace cache, if it contains enough instructions
@@ -58,17 +80,34 @@
}
}
- private void compileTrace(Trace trace, int pc) {
+ /**
+ * Compiles a dynamic basic block into a trace.
+ *
+ * @param trace
+ * The dynamic basic block to compile.
+ * @param pc
+ * The address of the first instruction within the dynamic basic block.
+ */
+ private void compileBlock(DynamicBasicBlock trace, int pc) {
if (DBT.VerifyAssertions) DBT._assert(trace.compiledTrace == null);
trace.compiledTrace = new DBT_Trace(ps, pc);
trace.compiledTrace.compile();
+ trace.instructions = null;
}
- private void executeTrace(Trace trace, int pc) {
+ /**
+ * Executes the instructions within a dynamic basic block.
+ *
+ * @param trace
+ * The dynamic basic block whose instructions shall be executed.
+ * @param pc
+ * The address of the first instruction within that dynamic basic block.
+ */
+ private void executeBlock(DynamicBasicBlock trace, int pc) {
//check if the trace is being executed very frequently...
- if (trace.value > 20) {
+ if (trace.value > DBT_Options.minTraceValue) {
if (DBT_Options.debugTranslation)
System.out.println("Switching to interpretation at address 0x" + Integer.toHexString(pc));
@@ -76,13 +115,18 @@
//yes, so we should rather try to execute a translated version
if (trace.compiledTrace == null) {
//compile the trace, if necessary
- compileTrace(trace, pc);
+ compileBlock(trace, pc);
if (DBT.VerifyAssertions) DBT._assert(trace.compiledTrace != null);
}
//execute the trace
VM_CodeArray code = trace.compiledTrace.getCurrentCompiledMethod().getEntryCodeArray();
ps.setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, ps));
+
+ if (DBT_Options.debugTranslation)
+ System.out.println("Returning from interpretation at 0x" + Integer.toHexString(ps.getCurrentInstructionAddress()));
+
+ return;
}
else {
trace.value += trace.instructions.size();
@@ -102,6 +146,7 @@
}
}
+ /** Default constructor */
public StagedEmulationController(ProcessSpace ps) {
super(ps);
interpreter = ps.createInterpreter();
@@ -113,8 +158,8 @@
while (!ps.finished) {
- Trace trace = getTrace(pc);
- executeTrace(trace, pc);
+ DynamicBasicBlock trace = getBlock(pc);
+ executeBlock(trace, pc);
pc = ps.getCurrentInstructionAddress();
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-08-02 12:22:43
|
Revision: 153
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=153&view=rev
Author: michael_baer
Date: 2007-08-02 05:22:44 -0700 (Thu, 02 Aug 2007)
Log Message:
-----------
- Allowing to load/save branch profiles
- Added generic profiling to the Interpreter
- Added support for staged emulation
Modified Paths:
--------------
src/org/binarytranslator/DBT_Options.java
src/org/binarytranslator/Main.java
src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java
src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java
src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java
src/org/binarytranslator/generic/branchprofile/BranchProfile.java
src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java
src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java
src/org/binarytranslator/generic/execution/ExecutionController.java
src/org/binarytranslator/generic/execution/InterpreterController.java
src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java
Added Paths:
-----------
src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java
src/org/binarytranslator/generic/execution/StagedEmulationController.java
Modified: src/org/binarytranslator/DBT_Options.java
===================================================================
--- src/org/binarytranslator/DBT_Options.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/DBT_Options.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -49,7 +49,13 @@
/** Determines how the program will be run (i.e. interpreted, translated etc.) */
public static ExecutionController.Type executionController = ExecutionController.Type.Translator;
+
+ /** A filename to which the runtime profiling information shall be saved. */
+ public static String saveProfileToFile = null;
+ /** A filename from which the runtime profiling information shall be loaded. */
+ public static String loadProfileFromFile = null;
+
/**
* Favour backward branch optimization. Translate backward branch addresses
* before the next instructions (this is the manner of the 601's branch
@@ -183,7 +189,12 @@
gdbStubPort = Integer.parseInt(value);
} else if (arg.equalsIgnoreCase("controller")) {
executionController = ExecutionController.Type.valueOf(value);
- } else {
+ } else if (arg.equalsIgnoreCase("loadProfile")) {
+ loadProfileFromFile = arg;
+ } else if (arg.equalsIgnoreCase("saveProfile")) {
+ saveProfileToFile = arg;
+ }
+ else {
throw new Error("Unknown DBT option: " + arg);
}
}
Modified: src/org/binarytranslator/Main.java
===================================================================
--- src/org/binarytranslator/Main.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/Main.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -9,12 +9,14 @@
package org.binarytranslator;
import java.io.File;
-
import org.binarytranslator.generic.execution.PredecodingThreadedInterpreter;
import org.binarytranslator.generic.execution.DynamicTranslationController;
import org.binarytranslator.generic.execution.ExecutionController;
import org.binarytranslator.generic.execution.GdbController;
import org.binarytranslator.generic.execution.InterpreterController;
+import org.binarytranslator.generic.execution.ProfilingInterpreterController;
+import org.binarytranslator.generic.execution.ProfilingPredecodingInterpreter;
+import org.binarytranslator.generic.execution.StagedEmulationController;
import org.binarytranslator.generic.os.loader.Loader;
import org.binarytranslator.generic.os.process.ProcessSpace;
@@ -93,10 +95,6 @@
System.err.println("Error accesing file: " + args[0] + ". " + e.getMessage());
return;
}
- /*catch (Error e) {
- System.err.println(e.getMessage());
- return;
- }*/
report("Sucessfully created process.");
@@ -108,20 +106,35 @@
//on SUN's VM, only the interpreter has been tested
if (DBT_Options.buildForSunVM) {
DBT_Options.executionController = ExecutionController.Type.PredecodingInterpreter;
-
}
+ //load a previously saved branch profile from file, if the user requested it
+ try {
+ if (DBT_Options.loadProfileFromFile != null)
+ ps.branchInfo.loadFromXML(DBT_Options.loadProfileFromFile);
+ } catch (Exception e) {
+ System.err.println("Error loading branch profile from: " + DBT_Options.loadProfileFromFile);
+ e.printStackTrace();
+ return;
+ }
+
//Create an execution controller and pass execution on to it
ExecutionController controller = null;
switch (DBT_Options.executionController) {
+ case StagedEmulation:
+ controller = new StagedEmulationController(ps);
+ break;
+
case PredecodingInterpreter:
- controller = new PredecodingThreadedInterpreter(ps); //new PredecodingThreadedInterpreter(ps);
- break;
+ controller = DBT_Options.profileDuringInterpretation ?
+ new ProfilingPredecodingInterpreter(ps) : new PredecodingThreadedInterpreter(ps);
+ break;
case Interpreter:
- controller = new InterpreterController(ps);
+ controller = DBT_Options.profileDuringInterpretation ?
+ new ProfilingInterpreterController(ps) : new InterpreterController(ps);
break;
case Translator:
@@ -143,10 +156,11 @@
public static void onExit(int exitcode) {
System.out.println("\nProgram has finished. Exitcode: " + exitcode);
- /*try {
- //ps.branchInfo.saveAsXML("/tmp/profile.xml");
- } catch (IOException e) {
+ try {
+ if (DBT_Options.saveProfileToFile != null)
+ ps.branchInfo.saveAsXML(DBT_Options.saveProfileToFile);
+ } catch (Exception e) {
e.printStackTrace();
- }*/
+ }
}
}
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Disassembler.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -20,7 +20,6 @@
import org.binarytranslator.arch.arm.decoder.ARM_Instructions.UndefinedInstruction;
import org.binarytranslator.arch.arm.decoder.ARM_Instructions.Instruction.Condition;
import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace;
-import org.binarytranslator.generic.decoder.DisassembledInstruction;
import org.binarytranslator.generic.decoder.Disassembler;
/**
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -385,7 +385,7 @@
this.conditionalInstruction = i;
conditionTrueSuccessor = conditionalInstruction.getSuccessor(pc);
- boolean inThumbMode = (pc & 1) == 0;
+ boolean inThumbMode = (pc & 1) == 1;
if (conditionTrueSuccessor == pc + 4 && !inThumbMode)
successorInstruction = conditionTrueSuccessor; //ARM may have conditional instruction that are not jumps
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Translator.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -58,11 +58,10 @@
public int translateInstruction(int pc, ARM_Laziness lazy) {
this.pc = pc;
this.lazy = lazy;
- boolean thumb = (pc & 1) != 0;
int instruction;
try {
- if (thumb)
+ if (inThumb())
instruction = ps.memory.loadInstruction16(pc & 0xFFFFFFFE);
else
instruction = ps.memory.loadInstruction32(pc);
@@ -88,7 +87,7 @@
}
ARM_Instruction instr;
- if (thumb)
+ if (inThumb())
instr = ARM_InstructionDecoder.Thumb.decode((short)instruction, translatorFactory);
else
instr = ARM_InstructionDecoder.ARM32.decode(instruction, translatorFactory);
@@ -756,79 +755,99 @@
arm2ir.getCurrentBlock().insertOut(nextInstruction);
arm2ir.getCurrentBlock().insertOut(condBlock);
+ //Query the branch profile to get the probability that this instruction is going to get executed
+ float skipProbability = ps.branchInfo.getBranchProbability(pc, pc + (inThumb() ? 2 : 4));
+ OPT_BranchProfileOperand profileOperand;
+
+ if (skipProbability == -1 || skipProbability == 0.5f) {
+ profileOperand = new OPT_BranchProfileOperand();
+ }
+ else if (skipProbability > 0.8f) {
+ profileOperand = OPT_BranchProfileOperand.always();
+ }
+ else if (skipProbability > 0.5f) {
+ profileOperand = OPT_BranchProfileOperand.likely();
+ }
+ else if (skipProbability < 0.2f) {
+ profileOperand = OPT_BranchProfileOperand.never();
+ }
+ else {
+ profileOperand = OPT_BranchProfileOperand.unlikely();
+ }
+
switch (condition) {
case AL:
throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator.");
case CC:
//return !regs.isCarrySet();
- translateCondition(nextInstruction, arm2ir.getCarryFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getCarryFlag(), OPT_ConditionOperand.NOT_EQUAL());
break;
case CS:
//return regs.isCarrySet();
- translateCondition(nextInstruction, arm2ir.getCarryFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getCarryFlag(), OPT_ConditionOperand.EQUAL());
break;
case EQ:
//return regs.isZeroSet();
- translateCondition(nextInstruction, arm2ir.getZeroFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getZeroFlag(), OPT_ConditionOperand.EQUAL());
break;
case GE:
//return regs.isNegativeSet() == regs.isOverflowSet();
- translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL(), arm2ir.getOverflowFlag());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL(), arm2ir.getOverflowFlag());
break;
case GT:
- translateCondition_GT(nextInstruction);
+ translateCondition_GT(nextInstruction, profileOperand);
break;
case HI:
- translateCondition_HI(nextInstruction);
+ translateCondition_HI(nextInstruction, profileOperand);
break;
case LE:
- translateCondition_LE(nextInstruction);
+ translateCondition_LE(nextInstruction, profileOperand);
break;
case LS:
- translateCondition_LS(nextInstruction, condBlock);
+ translateCondition_LS(nextInstruction, profileOperand, condBlock);
break;
case LT:
//return regs.isNegativeSet() != regs.isOverflowSet();
- translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.getOverflowFlag());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL(), arm2ir.getOverflowFlag());
break;
case MI:
//return regs.isNegativeSet();
- translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.EQUAL());
break;
case NE:
//return !regs.isZeroSet();
- translateCondition(nextInstruction, arm2ir.getZeroFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getZeroFlag(), OPT_ConditionOperand.NOT_EQUAL());
break;
case NV:
//never execute this instruction
- translateCondition(nextInstruction, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction, profileOperand, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL());
break;
case PL:
//return !regs.isNegativeSet();
- translateCondition(nextInstruction, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getNegativeFlag(), OPT_ConditionOperand.NOT_EQUAL());
break;
case VC:
//return !regs.isOverflowSet();
- translateCondition(nextInstruction, arm2ir.getOverflowFlag(), OPT_ConditionOperand.NOT_EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getOverflowFlag(), OPT_ConditionOperand.NOT_EQUAL());
break;
case VS:
//return regs.isOverflowSet();
- translateCondition(nextInstruction, arm2ir.getOverflowFlag(), OPT_ConditionOperand.EQUAL());
+ translateCondition(nextInstruction, profileOperand, arm2ir.getOverflowFlag(), OPT_ConditionOperand.EQUAL());
break;
default:
@@ -839,17 +858,17 @@
conditionalInstruction.translate();
}
- 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_BranchProfileOperand skipProbability, OPT_Operand operand, OPT_ConditionOperand condition) {
+ translateCondition(nextInstruction, skipProbability, operand, condition, new OPT_IntConstantOperand(1));
}
- private void translateCondition(OPT_BasicBlock nextInstruction, OPT_Operand lhs, OPT_ConditionOperand condition, OPT_Operand rhs) {
+ private void translateCondition(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability, OPT_Operand lhs, OPT_ConditionOperand condition, OPT_Operand rhs) {
condition = condition.flipCode();
- arm2ir.appendInstruction(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(), skipProbability));
}
- private void translateCondition_HI(OPT_BasicBlock nextInstruction) {
+ private void translateCondition_HI(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return regs.isCarrySet() && !regs.isZeroSet();
OPT_Operand carry = arm2ir.getCarryFlag();
OPT_Operand zero = arm2ir.getZeroFlag();
@@ -858,10 +877,10 @@
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, carry,
new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), skipProbability));
}
- private void translateCondition_LS(OPT_BasicBlock nextInstruction, OPT_BasicBlock actualInstruction) {
+ private void translateCondition_LS(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability, OPT_BasicBlock actualInstruction) {
//return !regs.isCarrySet() || regs.isZeroSet();
OPT_Operand carry = arm2ir.getCarryFlag();
OPT_Operand zero = arm2ir.getZeroFlag();
@@ -869,7 +888,7 @@
OPT_RegisterOperand result = arm2ir.getTempInt(0);
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, carry, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), skipProbability));
/* cond1.deleteNormalOut();
cond1.insertOut(cond2);
@@ -885,7 +904,7 @@
cond2.insertOut(actualInstruction);*/
}
- private void translateCondition_GT(OPT_BasicBlock nextInstruction) {
+ private void translateCondition_GT(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return (regs.isNegativeSet() == regs.isOverflowSet()) && !regs.isZeroSet();
OPT_Operand negative = arm2ir.getNegativeFlag();
OPT_Operand overflow = arm2ir.getOverflowFlag();
@@ -895,10 +914,10 @@
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_OR, result, negative,
overflow, OPT_ConditionOperand.NOT_EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), skipProbability));
}
- private void translateCondition_LE(OPT_BasicBlock nextInstruction) {
+ private void translateCondition_LE(OPT_BasicBlock nextInstruction, OPT_BranchProfileOperand skipProbability) {
//return regs.isZeroSet() || (regs.isNegativeSet() != regs.isOverflowSet());
OPT_Operand negative = arm2ir.getNegativeFlag();
OPT_Operand overflow = arm2ir.getOverflowFlag();
@@ -908,7 +927,7 @@
arm2ir.appendInstruction(BooleanCmp2.create(BOOLEAN_CMP2_INT_AND, result, negative,
overflow, OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand(), zero, new OPT_IntConstantOperand(0), OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand()));
- arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), new OPT_BranchProfileOperand()));
+ arm2ir.appendInstruction(IfCmp.create(INT_IFCMP, arm2ir.getTempValidation(0), result.copy(), new OPT_IntConstantOperand(1), OPT_ConditionOperand.EQUAL(), nextInstruction.makeJumpTarget(), skipProbability));
}
@Override
Modified: src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/arch/arm/os/abi/semihosting/AngelSystemCalls.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -13,6 +13,7 @@
import org.binarytranslator.DBT;
import org.binarytranslator.DBT_Options;
+import org.binarytranslator.Main;
import org.binarytranslator.arch.arm.os.process.ARM_ProcessSpace;
/**
@@ -691,6 +692,7 @@
@Override
public void execute() {
ps.finished = true;
+ Main.onExit(0);
}
}
Modified: src/org/binarytranslator/generic/branchprofile/BranchProfile.java
===================================================================
--- src/org/binarytranslator/generic/branchprofile/BranchProfile.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/branchprofile/BranchProfile.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -121,7 +121,7 @@
throw new IOException("File is not a valid XML branch profile.");
int targetAddress = Integer.parseInt(((Element)target).getAttribute("address"));
- int branchCount = Integer.parseInt(((Element)target).getAttribute("address"));
+ int branchCount = Integer.parseInt(((Element)target).getAttribute("branchCount"));
targetsAndFrequencies.put(targetAddress, branchCount);
}
@@ -131,8 +131,6 @@
public void toXML(Document doc, Element parentNode) {
Element branchInfo = parentNode;
- Element targets = doc.createElement("targets");
-
for (Entry<Integer, Integer> branchTarget : destinationsAndFrequencies.entrySet()) {
int targetAddress = branchTarget.getKey();
int branchCount = branchTarget.getValue();
@@ -142,8 +140,6 @@
branchTargetElement.setAttribute("address", Integer.toString(targetAddress));
branchTargetElement.setAttribute("branchCount", Integer.toString(branchCount));
}
-
- branchInfo.appendChild(targets);
}
}
@@ -243,6 +239,33 @@
branchSites.put(origin, branch);
}
}
+
+ /**
+ * Returns the probability of a branch from <code>origin</code> to <code>target</code>.
+ *
+ * @param origin
+ * The address at which the branch is taking place.
+ * @param target
+ * The address to which the branch is taking place.
+ * @return
+ * The probability of the branch as a value between 0 and 1. The function returns -1, if the probability
+ * cannot be estimated.
+ */
+ public float getBranchProbability(int origin, int target) {
+ BranchInformation branch = branchSites.get(origin);
+
+ if (branch == null || branch.executionCount == 0) {
+ return -1f;
+ }
+
+ Integer branchesToTarget = branch.getTargetsAndFrequencies().get(target);
+
+ if (branchesToTarget == null) {
+ return 0f;
+ }
+
+ return branchesToTarget / (float)branch.executionCount;
+ }
/**
* Given an address within a procedure, returns the (most likely) procedure
@@ -271,7 +294,15 @@
* The address to which it took place.
*/
public void profileBranch(int origin, int target) {
- throw new RuntimeException("Not yet implemented.");
+
+ BranchInformation branch = branchSites.get(origin);
+
+ if (branch == null) {
+ branch = new BranchInformation();
+ branchSites.put(origin, branch);
+ }
+
+ branch.profile(target);
}
/**
@@ -288,8 +319,21 @@
return (branch == null) ? null : branch.getTargets();
}
+ /**
+ * Loads a branch profile from a file.
+ *
+ * @param filename
+ * The name of the file that the branch profile is loaded from.
+ * @throws IOException
+ * An exception that is thrown if an error occurs reading that file.
+ */
public void loadFromXML(String filename) throws IOException {
+ //clear previous profile data
+ procedures.clear();
+ branchSites.clear();
+
+ //create a XML document builder and an XML document
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
Document doc;
try {
@@ -303,34 +347,54 @@
if (DBT.VerifyAssertions) DBT._assert(doc != null);
+ //Check the root-name of the document
Element root = doc.getDocumentElement();
-
if (!root.getNodeName().equals("branch-profile"))
throw new IOException("File is not a valid XML branch profile.");
- Node branches = null;
-
+ //interate over the main document, parsing the different sections
for (int i = 0; i < root.getChildNodes().getLength(); i++) {
- Node node = root.getChildNodes().item(0);
+ Node node = root.getChildNodes().item(i);
+ String nodeName = node.getNodeName();
- if (node.getNodeName().equals("branches")) {
- branches = node;
- break;
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ continue;
}
- }
-
- if (branches == null)
- throw new IOException("File is not a valid XML branch profile.");
-
- for (int i = 0; i < branches.getChildNodes().getLength(); i++) {
- Node siteNode = branches.getChildNodes().item(i);
- if (!siteNode.getNodeName().equals("origin") || siteNode.getNodeType() != Node.ELEMENT_NODE)
- throw new IOException("File is not a valid XML branch profile.");
+ if (nodeName.equals("branches")) {
- int address = Integer.parseInt(((Element)siteNode).getAttribute("address"));
- BranchInformation branchInfo = BranchInformation.fromXML((Element)siteNode);
- branchSites.put(address, branchInfo);
+ //this is the section which contains the branch information.
+ for (int n = 0; n < node.getChildNodes().getLength(); n++) {
+ Node branchNode = node.getChildNodes().item(n);
+
+ if (branchNode.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ if (!branchNode.getNodeName().equals("branch"))
+ throw new IOException("File is not a valid XML branch profile.");
+
+ int address = Integer.parseInt(((Element)branchNode).getAttribute("address"));
+ BranchInformation branchInfo = BranchInformation.fromXML((Element)branchNode);
+ branchSites.put(address, branchInfo);
+ }
+ }
+ else
+ if (nodeName.equals("procedures")) {
+
+ //this is the section with procedure information
+ for (int n = 0; n < node.getChildNodes().getLength(); n++) {
+ Node procedureInfo = node.getChildNodes().item(n);
+
+ if (procedureInfo.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ ProcedureInformation pi = ProcedureInformation.fromXML((Element)procedureInfo);
+ procedures.put(pi.getEntryAddress(), pi);
+ }
+ }
+ else {
+ throw new IOException("This is not a valid XML branch profile.");
+ }
}
}
@@ -387,6 +451,15 @@
branchInfo.toXML(doc, branchSiteElement);
}
+ Element proceduresElement = doc.createElement("procedures");
+ root.appendChild(proceduresElement);
+
+ for (ProcedureInformation procedure : procedures.values()) {
+ Element procedureElement = doc.createElement("procedure");
+ proceduresElement.appendChild(procedureElement);
+ procedure.toXML(doc, procedureElement);
+ }
+
//Output the resulting XML document
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer;
@@ -395,6 +468,7 @@
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(outputStream);
transformer.transform(source, result);
+ outputStream.close();
} catch (Exception e) {
e.printStackTrace();
Modified: src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java
===================================================================
--- src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/branchprofile/CallAndReturnAddress.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -12,14 +12,11 @@
* Object for recording a call site and its corresponding return address
*/
class CallAndReturnAddress {
- /**
- * Call site address
- */
+
+ /** The address at which the call is taking place.*/
private int callSite;
- /**
- * Return address
- */
+ /** The address to which the call shall return. */
private int returnAddress;
/**
@@ -35,24 +32,29 @@
this.returnAddress = returnAddress;
}
- /**
- * Get call site address
- */
+ /** Get call site address */
int getCallSite() {
return callSite;
}
- /**
- * Get return address
- */
+ /** Get return address */
int getReturnAddress() {
return returnAddress;
}
+
+ @Override
+ public int hashCode() {
+ return callSite;
+ }
- /**
- * Are two call sites the same?
- */
+ @Override
public boolean equals(Object obj) {
- return ((CallAndReturnAddress) obj).callSite == callSite;
+
+ if (!(obj instanceof CallAndReturnAddress)) {
+ return false;
+ }
+
+ CallAndReturnAddress other = ((CallAndReturnAddress) obj);
+ return other.callSite == callSite && other.returnAddress == returnAddress;
}
}
Modified: src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java
===================================================================
--- src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -19,20 +19,15 @@
* Objects capturing information about what looks like a method
*/
class ProcedureInformation {
- /**
- * Entry point to the procedure
- */
+
+ /** Entry point to the procedure */
private final int entry;
- /**
- * Set of locations that call the procedure and the corressponding return
- * address
- */
+ /** Set of locations that call the procedure and the corressponding return
+ * address. */
private HashSet<CallAndReturnAddress> callSitesAndReturnAddresses;
- /**
- * Set of locations within the procedure that return
- */
+ /** Set of locations within the procedure that return */
private HashSet<Integer> returnSites;
/**
@@ -50,8 +45,15 @@
}
}
- private ProcedureInformation(int entry) {
+ /**
+ * Constructor
+ *
+ * @param entry
+ * starting address of the procedure
+ */
+ public ProcedureInformation(int entry) {
this.entry = entry;
+ callSitesAndReturnAddresses = new HashSet<CallAndReturnAddress>();
}
/**
@@ -64,23 +66,32 @@
* @param returnAddress
* the corresponding return address
*/
- ProcedureInformation(int entry, int callSite, int returnAddress) {
- this.entry = entry;
- callSitesAndReturnAddresses = new HashSet<CallAndReturnAddress>();
+ public ProcedureInformation(int entry, int callSite, int returnAddress) {
+ this(entry);
+
callSitesAndReturnAddresses.add(new CallAndReturnAddress(callSite,
returnAddress));
}
+
+ /**
+ * Returns the address at which this procedure starts.
+ * @return
+ * The address at which the procedure starts.
+ */
+ public int getEntryAddress() {
+ return entry;
+ }
/**
* Register a call (branch and link) instruction
*
- * @param pc
- * the address of the branch instruction
+ * @param atAddress
+ * the address of the call instruction
* @param ret
* the address that will be returned to
*/
- public void registerCall(int pc, int ret) {
- CallAndReturnAddress call_tuple = new CallAndReturnAddress(pc, ret);
+ public void registerCall(int atAddress, int ret) {
+ CallAndReturnAddress call_tuple = new CallAndReturnAddress(atAddress, ret);
if (!callSitesAndReturnAddresses.contains(call_tuple)) {
callSitesAndReturnAddresses.add(call_tuple);
}
@@ -89,15 +100,15 @@
/**
* Register a return (branch to link register) instruction
*
- * @param pc
+ * @param atAddress
* the address of the branch instruction
*/
- public void registerReturn(int pc) {
+ public void registerReturn(int atAddress) {
if (returnSites == null) {
returnSites = new HashSet<Integer>();
}
- returnSites.add(new Integer(pc));
+ returnSites.add(new Integer(atAddress));
}
/**
@@ -121,13 +132,17 @@
}
procedure.appendChild(callSites);
- Element returnSites = doc.createElement("returnsites");
- for (Integer returnSite : this.returnSites) {
- Element returnSiteNode = doc.createElement("return");
- returnSiteNode.setAttribute("at", returnSite.toString());
- returnSites.appendChild(returnSiteNode);
+ if (returnSites != null) {
+ Element returnSitesElement = doc.createElement("returnsites");
+ procedure.appendChild(returnSitesElement);
+
+ for (Integer returnSite : returnSites) {
+ Element returnSiteNode = doc.createElement("return");
+ returnSiteNode.setAttribute("at", returnSite.toString());
+ returnSitesElement.appendChild(returnSiteNode);
+ }
+
}
- procedure.appendChild(returnSites);
}
/**
@@ -156,7 +171,7 @@
if (callsite.getNodeType() != Node.ELEMENT_NODE)
continue;
- if (callsite.getNodeName().equals("call"))
+ if (!callsite.getNodeName().equals("call"))
throw new Error("The given XML node is not a valid ProcedureInformation entity.");
int callFrom = Integer.parseInt(((Element)callsite).getAttribute("from"));
@@ -166,6 +181,9 @@
}
}
else if (childNode.getNodeName().equals("returnsites")) {
+
+ pi.returnSites = new HashSet<Integer>();
+
//parse return sites
for (int n = 0; n < childNode.getChildNodes().getLength(); n++) {
Node callsite = childNode.getChildNodes().item(n);
@@ -174,7 +192,7 @@
if (callsite.getNodeType() != Node.ELEMENT_NODE)
continue;
- if (callsite.getNodeName().equals("return"))
+ if (!callsite.getNodeName().equals("return"))
throw new Error("The given XML node is not a valid ProcedureInformation entity.");
int returnAt = Integer.parseInt(((Element)callsite).getAttribute("at"));
Modified: src/org/binarytranslator/generic/execution/ExecutionController.java
===================================================================
--- src/org/binarytranslator/generic/execution/ExecutionController.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/execution/ExecutionController.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -9,6 +9,7 @@
Translator,
Interpreter,
PredecodingInterpreter,
+ StagedEmulation,
GDB
}
Modified: src/org/binarytranslator/generic/execution/InterpreterController.java
===================================================================
--- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -13,23 +13,16 @@
@Override
public void run() {
Interpreter interpreter = ps.createInterpreter();
-
int pc = ps.getCurrentInstructionAddress();
while (!ps.finished) {
- Interpreter.Instruction instruction = interpreter.decode(pc);
- //System.out.println(String.format("[0x%x] %s", pc, instruction.toString()));
-
+ Interpreter.Instruction instruction = interpreter.decode(pc);
instruction.execute();
- //System.out.println(ps.toString());
int nextInstruction = instruction.getSuccessor(pc);
if (nextInstruction == -1) {
nextInstruction = ps.getCurrentInstructionAddress();
-
- if (DBT_Options.profileDuringInterpretation)
- ps.branchInfo.profileBranch(pc, ps.getCurrentInstructionAddress());
}
else {
ps.setCurrentInstructionAddress(nextInstruction);
Modified: src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java
===================================================================
--- src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-29 13:13:16 UTC (rev 152)
+++ src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -8,10 +8,33 @@
import org.binarytranslator.generic.decoder.Interpreter;
import org.binarytranslator.generic.os.process.ProcessSpace;
+/**
+ * Execution controller that implements predecoding, threaded interpretation.
+ *
+ */
public class PredecodingThreadedInterpreter extends ExecutionController {
+ /** The controller keeps a cache of commonly used code traces. Each trace is essentially a dynamic basic block.
+ * This HashMap maps the address of a trace's first instruction to its dynamic basic block. */
private final HashMap<Integer, List<Interpreter.Instruction>> traceCache = new HashMap<Integer, List<Interpreter.Instruction>>();
+
+ /** The interpreter that is used to perform the actual execution of single instructions. */
private final Interpreter interpreter;
+ /** Default constructor. */
+ public PredecodingThreadedInterpreter(ProcessSpace ps) {
+ super(ps);
+ interpreter = ps.createInterpreter();
+ }
+
+ /**
+ * Returns the dynamic basic block of instructions, starting it at address <code>pc</code>.
+ * This function also manages the trace cache ({@link #traceCache}).
+ *
+ * @param pc
+ * The address at which the dynamic basic block starts.
+ * @return
+ * A list of instructions that form the dynamic basic block.
+ */
private List<Interpreter.Instruction> getTrace(int pc) {
List<Interpreter.Instruction> cachedTrace = traceCache.get(pc);
@@ -42,6 +65,14 @@
return newTrace;
}
+ /**
+ * Executes a list of instructions. It is assumed that the first instruction starts at address <code>pc</code>.
+ *
+ * @param trace
+ * The list of instructions that is to be executed.
+ * @param pc
+ * The address of the first instruction.
+ */
protected void executeTrace(List<Interpreter.Instruction> trace, int pc) {
Iterator<Interpreter.Instruction> instructions = trace.iterator();
@@ -57,11 +88,6 @@
break;
}
}
-
- public PredecodingThreadedInterpreter(ProcessSpace ps) {
- super(ps);
- interpreter = ps.createInterpreter();
- }
@Override
public final void run() {
Added: src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java
===================================================================
--- src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java (rev 0)
+++ src/org/binarytranslator/generic/execution/ProfilingInterpreterController.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -0,0 +1,36 @@
+package org.binarytranslator.generic.execution;
+
+import org.binarytranslator.generic.decoder.Interpreter;
+import org.binarytranslator.generic.os.process.ProcessSpace;
+
+public class ProfilingInterpreterController extends ExecutionController {
+
+ public ProfilingInterpreterController(ProcessSpace ps) {
+ super(ps);
+ }
+
+ @Override
+ public void run() {
+ Interpreter interpreter = ps.createInterpreter();
+
+ int pc = ps.getCurrentInstructionAddress();
+
+ while (!ps.finished) {
+ Interpreter.Instruction instruction = interpreter.decode(pc);
+
+ instruction.execute();
+ int nextInstruction = instruction.getSuccessor(pc);
+
+ if (nextInstruction == -1) {
+ nextInstruction = ps.getCurrentInstructionAddress();
+ ps.branchInfo.profileBranch(pc, ps.getCurrentInstructionAddress());
+ }
+ else {
+ ps.setCurrentInstructionAddress(nextInstruction);
+ }
+
+ pc = nextInstruction;
+ }
+ }
+
+}
Added: src/org/binarytranslator/generic/execution/StagedEmulationController.java
===================================================================
--- src/org/binarytranslator/generic/execution/StagedEmulationController.java (rev 0)
+++ src/org/binarytranslator/generic/execution/StagedEmulationController.java 2007-08-02 12:22:44 UTC (rev 153)
@@ -0,0 +1,121 @@
+package org.binarytranslator.generic.execution;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.binarytranslator.DBT;
+import org.binarytranslator.DBT_Options;
+import org.binarytranslator.generic.decoder.Interpreter;
+import org.binarytranslator.generic.os.process.ProcessSpace;
+import org.binarytranslator.vmInterface.DBT_Trace;
+import org.binarytranslator.vmInterface.DynamicCodeRunner;
+import org.jikesrvm.ArchitectureSpecific.VM_CodeArray;
+
+public class StagedEmulationController extends ExecutionController {
+
+ private final class Trace {
+ public final List<Interpreter.Instruction> instructions;
+ public int value;
+ public DBT_Trace compiledTrace;
+
+ public Trace(List<Interpreter.Instruction> instructions) {
+ this.instructions = instructions;
+ value = 0;
+ }
+ }
+
+ private final HashMap<Integer, Trace> traceCache = new HashMap<Integer, Trace>();
+ private final Interpreter interpreter;
+
+ private Trace getTrace(int pc) {
+ Trace cachedTrace = traceCache.get(pc);
+
+ if (cachedTrace != null)
+ return cachedTrace;
+
+ int traceStart = pc;
+ ArrayList<Interpreter.Instruction> instructions = new ArrayList<Interpreter.Instruction>(5);
+
+ while (true) {
+ Interpreter.Instruction instruction = interpreter.decode(pc);
+ pc = instruction.getSuccessor(pc);
+ instructions.add(instruction);
+
+ //is the successor to this instruction known?
+ if (pc == -1) {
+ //No, so stop and create a trace from the decoded instructions
+ Trace newTrace = new Trace(instructions);
+
+ if (instructions.size() > 3) {
+ //add this trace to the trace cache, if it contains enough instructions
+ traceCache.put(traceStart, newTrace);
+ }
+
+ return newTrace;
+ }
+ }
+ }
+
+ private void compileTrace(Trace trace, int pc) {
+ if (DBT.VerifyAssertions) DBT._assert(trace.compiledTrace == null);
+
+ trace.compiledTrace = new DBT_Trace(ps, pc);
+ trace.compiledTrace.compile();
+ }
+
+ private void executeTrace(Trace trace, int pc) {
+
+ //check if the trace is being executed very frequently...
+ if (trace.value > 20) {
+
+ if (DBT_Options.debugTranslation)
+ System.out.println("Switching to interpretation at address 0x" + Integer.toHexString(pc));
+
+ //yes, so we should rather try to execute a translated version
+ if (trace.compiledTrace == null) {
+ //compile the trace, if necessary
+ compileTrace(trace, pc);
+ if (DBT.VerifyAssertions) DBT._assert(trace.compiledTrace != null);
+ }
+
+ //execute the trace
+ VM_CodeArray code = trace.compiledTrace.getCurrentCompiledMethod().getEntryCodeArray();
+ ps.setCurrentInstructionAddress(DynamicCodeRunner.invokeCode(code, ps));
+ }
+ else {
+ trace.value += trace.instructions.size();
+ }
+
+ Iterator<Interpreter.Instruction> instructions = trace.instructions.iterator();
+ while (true) {
+ Interpreter.Instruction instr = instructions.next();
+ instr.execute();
+
+ if (instructions.hasNext()) {
+ pc = instr.getSuccessor(pc);
+ ps.setCurrentInstructionAddress(pc);
+ }
+ else
+ break;
+ }
+ }
+
+ public StagedEmulationController(ProcessSpace ps) {
+ super(ps);
+ interpreter = ps.createInterpreter();
+ }
+
+ @Override
+ public void run() {
+ int pc = ps.getCurrentInstructionAddress();
+
+ while (!ps.finished) {
+
+ Trace trace = getTrace(pc);
+ executeTrace(trace, pc);
+ pc = ps.getCurrentInstructionAddress();
+ }
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-07-29 13:13:15
|
Revision: 152
http://pearcolator.svn.sourceforge.net/pearcolator/?rev=152&view=rev
Author: michael_baer
Date: 2007-07-29 06:13:16 -0700 (Sun, 29 Jul 2007)
Log Message:
-----------
- Made profiling during interpretation a functionality provided by the ExecutionController
- Added new ExecutionController
- Restructured branch profiling slightly
Modified Paths:
--------------
src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java
src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java
src/org/binarytranslator/generic/branchprofile/BranchProfile.java
src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java
src/org/binarytranslator/generic/decoder/CodeTranslator.java
src/org/binarytranslator/generic/decoder/Interpreter.java
src/org/binarytranslator/generic/execution/InterpreterController.java
src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java
src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java
src/org/binarytranslator/generic/os/process/ProcessSpace.java
Added Paths:
-----------
src/org/binarytranslator/generic/decoder/Disassembler.java
src/org/binarytranslator/generic/execution/ProfilingPredecodingInterpreter.java
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Interpreter.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -9,7 +9,6 @@
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.branchprofile.BranchProfile.BranchType;
import org.binarytranslator.generic.decoder.Interpreter;
import org.binarytranslator.generic.decoder.Utils;
@@ -23,7 +22,7 @@
* @author Michael Baer
*/
public class ARM_Interpreter implements Interpreter {
-
+
/** The process space that we're interpreting.*/
protected final ARM_ProcessSpace ps;
@@ -31,7 +30,7 @@
protected final ARM_Registers regs;
/** The interpreter factory is creating the final instructions, which implement the Interpreter.Instruction interface. */
- protected final ARM_InstructionFactory<ARM_Instruction> instructionFactory;
+ protected final InterpreterFactory instructionFactory;
public ARM_Interpreter(ARM_ProcessSpace ps) {
this.ps = ps;
@@ -41,9 +40,11 @@
/** Decodes the instruction at the given address.*/
public Instruction decode(int pc) {
-
+
ARM_Instruction instruction;
+ instructionFactory.setInstructionAddress(pc);
+
if ((pc & 1) != 0) {
short binaryInstruction = (short)ps.memory.loadInstruction16(pc & 0xFFFFFFFE);
instruction = ARM_InstructionDecoder.Thumb.decode(binaryInstruction, instructionFactory);
@@ -54,7 +55,7 @@
}
if (instruction.getCondition() != Condition.AL) {
- return new ConditionalDecorator(instruction);
+ return new ConditionalDecorator(instruction, pc);
}
return instruction;
@@ -123,7 +124,7 @@
if (operand.getRegister() == ARM_Registers.PC)
value = regs.readPC();
else
- value =regs.get(operand.getRegister());
+ value = regs.get(operand.getRegister());
value += operand.getOffset();
return;
@@ -364,43 +365,66 @@
* instruction (or not). The instruction classes itself do not check any conditions. */
private final class ConditionalDecorator implements Interpreter.Instruction {
+ /** The conditional instruction. */
protected final ARM_Instruction conditionalInstruction;
- private final Condition condition;
+
+ /** The address of the successor of the conditional instruction. Can be -1, if it cannot be determined statically. */
+ private final int conditionTrueSuccessor;
+
+ /** The successor of this instruction, if the condition evaluates to false.*/
+ private final int conditionFalseSuccessor;
+
+ /** The address of the successor of this instrction if it is constant, otherwise -1. */
+ private final int successorInstruction;
+
+ /** The address of this instruction. */
+ private final int instructionAddress;
/** Decorates an ARM interpreter instruction, by making it execute conditionally. */
- protected ConditionalDecorator(ARM_Instruction i) {
- conditionalInstruction = i;
- this.condition = i.getCondition();
+ protected ConditionalDecorator(ARM_Instruction i, int pc) {
+ this.conditionalInstruction = i;
+
+ conditionTrueSuccessor = conditionalInstruction.getSuccessor(pc);
+ boolean inThumbMode = (pc & 1) == 0;
+
+ if (conditionTrueSuccessor == pc + 4 && !inThumbMode)
+ successorInstruction = conditionTrueSuccessor; //ARM may have conditional instruction that are not jumps
+ else
+ successorInstruction = -1;
+
+ conditionFalseSuccessor = pc + (inThumbMode ? 2 : 4);
+ instructionAddress = pc;
}
public void execute() {
+
if (isConditionTrue()) {
- int nextInstruction = conditionalInstruction.getSuccessor(ps.getCurrentInstructionAddress());
conditionalInstruction.execute();
- if (nextInstruction != -1)
- ps.setCurrentInstructionAddress(nextInstruction);
+ if (conditionTrueSuccessor != -1) {
+ ps.setCurrentInstructionAddress(conditionTrueSuccessor);
+ }
+
+ if (successorInstruction != -1) {
+ ps.branchInfo.profileBranch(instructionAddress, conditionTrueSuccessor);
+ }
}
else {
- ps.setCurrentInstructionAddress(ps.getCurrentInstructionAddress() + (regs.getThumbMode() ? 2 : 4));
+ ps.setCurrentInstructionAddress(conditionFalseSuccessor);
+
+ if (successorInstruction != -1) {
+ ps.branchInfo.profileBranch(instructionAddress, conditionFalseSuccessor);
+ }
}
}
public int getSuccessor(int pc) {
- //if this instruction is not a jump, then we can tell what the next instruction will be.
-
- int conditionalSuccessor = conditionalInstruction.getSuccessor(pc);
- boolean thumbMode = (pc & 0x1) == 1;
-
- if (conditionalSuccessor == pc + 4 && !thumbMode)
- return conditionalSuccessor; //ARM may have conditional non-jump instructions
- else
- return -1;
+ return successorInstruction;
}
/** Return true if the condition required by the conditional instruction is fulfilled, false otherwise.*/
private boolean isConditionTrue() {
- switch (condition) {
+ switch (conditionalInstruction.getCondition()) {
case AL:
throw new RuntimeException("ARM32 instructions with a condition of AL (always) should not be decorated with a ConditionalDecorator.");
@@ -450,7 +474,7 @@
return regs.isOverflowSet();
default:
- throw new RuntimeException("Unexpected condition code: " + condition);
+ throw new RuntimeException("Unexpected condition code: " + conditionalInstruction.getCondition());
}
}
@@ -514,10 +538,6 @@
if (i.Rd == ARM_Registers.PC) {
if (regs.getThumbMode())
result |= 1;
-
- if (DBT_Options.profileDuringInterpretation) {
- ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH);
- }
}
regs.set(i.Rd, result);
@@ -533,13 +553,8 @@
setFlagsForSub(lhs, rhs);
int result = lhs - rhs;
- if (i.Rd == ARM_Registers.PC) {
- if (regs.getThumbMode())
- result |= 1;
-
- if (DBT_Options.profileDuringInterpretation) {
- ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH);
- }
+ if (i.Rd == ARM_Registers.PC && regs.getThumbMode()) {
+ result |= 1;
}
regs.set(i.Rd, result);
@@ -595,8 +610,13 @@
* out value. The value of the barrel shifter is stored within this variable. */
protected boolean shifterCarryOut;
- protected DataProcessing_Logical(ARM_Instructions.DataProcessing instr) {
+ protected DataProcessing_Logical(ARM_Instructions.DataProcessing instr, int instructionAddress) {
super(instr);
+
+ if (DBT_Options.profileDuringInterpretation) {
+ if (i.getOpcode() == Opcode.MOV && i.operand2.getType() == OperandWrapper.Type.Register && i.operand2.getRegister() == ARM_Registers.LR)
+ ps.branchInfo.registerReturnSite(instructionAddress);
+ }
}
/** If the given OperandWrapper involves shifting a register, then this function will decoder the shift
@@ -622,13 +642,6 @@
if (regs.getThumbMode())
result |= 1;
-
- if (DBT_Options.profileDuringInterpretation) {
- if (i.getOpcode() == Opcode.MOV && i.operand2.getType() == OperandWrapper.Type.Register && i.operand2.getRegister() == ARM_Registers.LR)
- ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), result);
- else
- ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), result, BranchType.INDIRECT_BRANCH);
- }
}
regs.set(i.Rd, result);
@@ -651,8 +664,8 @@
/** Binary and. <code>Rd = op1 & op2 </code>.*/
private final class DataProcessing_And extends DataProcessing_Logical {
- protected DataProcessing_And(ARM_Instructions.DataProcessing instr) {
- super(instr);
+ protected DataProcessing_And(ARM_Instructions.DataProcessing instr, int instructionAddress) {
+ super(instr, instructionAddress);
}
@Override
@@ -665,8 +678,8 @@
/** Exclusive or. <code>Rd = op1 ^ op2 </code>.*/
private final class DataProcessing_Eor extends DataProcessing_Logical {
- protected DataProcessing_Eor(ARM_Instructions.DataProcessing instr) {
- super(instr);
+ protected DataProcessing_Eor(ARM_Instructions.DataProcessing instr, int instructionAddress) {
+ super(instr, instructionAddress);
}
@Override
@@ -804,8 +817,8 @@
* <code>Flags = op1 & op2</code>*/
private final class DataProcessing_Tst extends DataProcessing_Logical {
- protected DataProcessing_Tst(ARM_Instructions.DataProcessing instr) {
- super(instr);
+ protected DataProcessing_Tst(ARM_Instructions.DataProcessing instr, int instructionAddress) {
+ super(instr, instructionAddress);
}
@Override
@@ -818,8 +831,8 @@
* <code>Flags = op1 ^ op2</code> */
private final class DataProcessing_Teq extends DataProcessing_Logical {
- protected DataProcessing_Teq(ARM_Instructions.DataProcessing instr) {
- super(instr);
+ protected DataProcessing_Teq(ARM_Instructions.DataProcessing instr, int instructionAddress) {
+ super(instr, instructionAddress);
}
@Override
@@ -859,8 +872,8 @@
/** Binary or. <code>Rd = op1 | op2</code>. */
private final class DataProcessing_Orr extends DataProcessing_Logical {
- protected DataProcessing_Orr(ARM_Instructions.DataProcessing instr) {
- super(instr);
+ protected DataProcessing_Orr(ARM_Instructions.DataProcessing instr, int instructionAddress) {
+ super(instr, instructionAddress);
}
@Override
@@ -872,8 +885,8 @@
private final class DataProcessing_Mov extends DataProcessing_Logical {
- protected DataProcessing_Mov(ARM_Instructions.DataProcessing instr) {
- super(instr);
+ protected DataProcessing_Mov(ARM_Instructions.DataProcessing instr, int instructionAddress) {
+ super(instr, instructionAddress);
}
@Override
@@ -888,8 +901,8 @@
* <code>Rd = op1 & (~op2)</code>.*/
private final class DataProcessing_Bic extends DataProcessing_Logical {
- protected DataProcessing_Bic(ARM_Instructions.DataProcessing instr) {
- super(instr);
+ protected DataProcessing_Bic(ARM_Instructions.DataProcessing instr, int instructionAddress) {
+ super(instr, instructionAddress);
}
@Override
@@ -904,8 +917,8 @@
* <code>Rd = ~op2</code>.*/
private final class DataProcessing_Mvn extends DataProcessing_Logical {
- protected DataProcessing_Mvn(ARM_Instructions.DataProcessing instr) {
- super(instr);
+ protected DataProcessing_Mvn(ARM_Instructions.DataProcessing instr, int instructionAddress) {
+ super(instr, instructionAddress);
}
@Override
@@ -1000,22 +1013,26 @@
/** Should writeback be performed? */
private final boolean doWriteback;
- public BlockDataTransfer(ARM_Instructions.BlockDataTransfer instr) {
+ public BlockDataTransfer(ARM_Instructions.BlockDataTransfer instr, int instructionAddress) {
i = instr;
transferPC = i.transferRegister(ARM_Registers.PC);
int regCount = 0;
- for (int i = 0; i <= 14; i++)
+ for (int i = 0; i <= 14; i++) {
if (this.i.transferRegister(i)) {
registersToTransfer[regCount++] = i;
}
+ }
registersToTransfer[regCount] = -1;
if (transferPC)
regCount++;
+ if (DBT_Options.profileDuringInterpretation)
+ ps.branchInfo.registerReturnSite(instructionAddress);
+
if (!i.incrementBase) {
if (i.postIndexing) {
//post-indexing, backward reading
@@ -1095,9 +1112,6 @@
nextAddress += 4;
int newpc = ps.memory.load32(nextAddress);
- if (DBT_Options.profileDuringInterpretation)
- ps.branchInfo.registerReturn(regs.get(ARM_Registers.PC), newpc);
-
if (i.forceUser) {
//when we are transferring the PC with a forced-user transfer, then we also want to
//restore the CPSR from the SPSR.
@@ -1177,30 +1191,18 @@
public void execute() {
- int destination;
- BranchType branchType;
-
- if (i.offset.getType() != OperandWrapper.Type.Immediate) {
- branchType = BranchType.INDIRECT_BRANCH;
- }
- else {
- branchType = BranchType.DIRECT_BRANCH;
- }
-
+ int destination;
destination = regs.readPC() + ResolvedOperand.resolve(regs, i.offset);
- if (DBT_Options.profileDuringInterpretation) {
- if (i.link) {
- ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), destination, regs.get(ARM_Registers.PC) + i.size());
- }
- else {
- ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), destination, branchType);
- }
- }
-
//if we're supposed to link, then write the previous address into the link register
if (i.link) {
- regs.set(ARM_Registers.LR, regs.get(ARM_Registers.PC) + i.size());
+ int returnAddress = regs.get(ARM_Registers.PC) + i.size();
+
+ if (DBT_Options.profileDuringInterpretation) {
+ ps.branchInfo.registerCallSite(regs.get(ARM_Registers.PC), destination, returnAddress);
+ }
+
+ regs.set(ARM_Registers.LR, returnAddress);
}
if (regs.getThumbMode())
@@ -1273,12 +1275,13 @@
//if we're supposed to link, then write the previous address into the link register
if (i.link) {
- regs.set(ARM_Registers.LR, regs.readPC() - (regs.getThumbMode() ? 2 : 4));
- ps.branchInfo.registerCall(regs.get(ARM_Registers.PC), targetAddress, regs.get(ARM_Registers.PC) + i.size());
+ int returnAddress = regs.readPC() - i.size();
+ regs.set(ARM_Registers.LR, returnAddress);
+
+ if (DBT_Options.profileDuringInterpretation) {
+ ps.branchInfo.registerCallSite(regs.get(ARM_Registers.PC), targetAddress, returnAddress);
+ }
}
- else {
- ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), targetAddress, BranchType.DIRECT_BRANCH);
- }
//jump to the new address
regs.set(ARM_Registers.PC, targetAddress);
@@ -1372,8 +1375,8 @@
//get rid of the signs, if we're supposed to do unsigned multiplication
if (i.unsigned) {
- operand1 = operand1 & 0xFFFFFFFF;
- operand2 = operand2 & 0xFFFFFFFF;
+ operand1 &= 0xFFFFFFFF;
+ operand2 &= 0xFFFFFFFF;
}
// calculate the result
@@ -1634,11 +1637,6 @@
//finally, write the variable into a register
regs.set(i.Rd, value);
-
- if (DBT_Options.profileDuringInterpretation) {
- if (i.Rd == ARM_Registers.PC)
- ps.branchInfo.registerBranch(regs.get(ARM_Registers.PC), value, BranchType.INDIRECT_BRANCH);
- }
}
else {
//we are store a value from a register to memory.
@@ -1743,6 +1741,8 @@
* the ARM_InstructionDecoder, which uses an abstract factory pattern to decode an instruction. */
private class InterpreterFactory implements
ARM_InstructionFactory<ARM_Instruction> {
+
+ private int instructionAddress;
public ARM_Instruction createDataProcessing(int instr) {
ARM_Instructions.DataProcessing i = new ARM_Instructions.DataProcessing(instr);
@@ -1753,21 +1753,21 @@
case ADD:
return new DataProcessing_Add(i);
case AND:
- return new DataProcessing_And(i);
+ return new DataProcessing_And(i, instructionAddress);
case BIC:
- return new DataProcessing_Bic(i);
+ return new DataProcessing_Bic(i, instructionAddress);
case CMN:
return new DataProcessing_Cmn(i);
case CMP:
return new DataProcessing_Cmp(i);
case EOR:
- return new DataProcessing_Eor(i);
+ return new DataProcessing_Eor(i, instructionAddress);
case MOV:
- return new DataProcessing_Mov(i);
+ return new DataProcessing_Mov(i, instructionAddress);
case MVN:
- return new DataProcessing_Mvn(i);
+ return new DataProcessing_Mvn(i, instructionAddress);
case ORR:
- return new DataProcessing_Orr(i);
+ return new DataProcessing_Orr(i, instructionAddress);
case RSB:
return new DataProcessing_Rsb(i);
case RSC:
@@ -1777,9 +1777,9 @@
case SUB:
return new DataProcessing_Sub(i);
case TEQ:
- return new DataProcessing_Teq(i);
+ return new DataProcessing_Teq(i, instructionAddress);
case TST:
- return new DataProcessing_Tst(i);
+ return new DataProcessing_Tst(i, instructionAddress);
case CLZ:
return new DataProcessing_Clz(i);
@@ -1788,8 +1788,12 @@
}
}
+ public void setInstructionAddress(int pc) {
+ instructionAddress = pc;
+ }
+
public ARM_Instruction createBlockDataTransfer(int instr) {
- return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr));
+ return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr), instructionAddress);
}
public ARM_Instruction createBranch(int instr) {
@@ -1854,7 +1858,7 @@
}
public ARM_Instruction createBlockDataTransfer(short instr) {
- return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr));
+ return new BlockDataTransfer(new ARM_Instructions.BlockDataTransfer(instr), instructionAddress);
}
public ARM_Instruction createBranch(short instr) {
@@ -1874,21 +1878,21 @@
case ADD:
return new DataProcessing_Add(i);
case AND:
- return new DataProcessing_And(i);
+ return new DataProcessing_And(i, instructionAddress);
case BIC:
- return new DataProcessing_Bic(i);
+ return new DataProcessing_Bic(i, instructionAddress);
case CMN:
return new DataProcessing_Cmn(i);
case CMP:
return new DataProcessing_Cmp(i);
case EOR:
- return new DataProcessing_Eor(i);
+ return new DataProcessing_Eor(i, instructionAddress);
case MOV:
- return new DataProcessing_Mov(i);
+ return new DataProcessing_Mov(i, instructionAddress);
case MVN:
- return new DataProcessing_Mvn(i);
+ return new DataProcessing_Mvn(i, instructionAddress);
case ORR:
- return new DataProcessing_Orr(i);
+ return new DataProcessing_Orr(i, instructionAddress);
case RSB:
return new DataProcessing_Rsb(i);
case RSC:
@@ -1898,9 +1902,9 @@
case SUB:
return new DataProcessing_Sub(i);
case TEQ:
- return new DataProcessing_Teq(i);
+ return new DataProcessing_Teq(i, instructionAddress);
case TST:
- return new DataProcessing_Tst(i);
+ return new DataProcessing_Tst(i, instructionAddress);
case CLZ:
return new DataProcessing_Clz(i);
Modified: src/org/binarytranslator/arch/arm/decoder/ARM_Options.java
===================================================================
--- src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/arch/arm/decoder/ARM_Options.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -1,6 +1,5 @@
package org.binarytranslator.arch.arm.decoder;
public class ARM_Options {
- public final static boolean FLAG_LAZINESS = false;
public final static boolean DATAPROCESSING_DECODER_FASTPATH = false;
}
Modified: src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java
===================================================================
--- src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/arch/ppc/decoder/PPC_InstructionDecoder.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -3942,7 +3942,7 @@
int target_address = ps.lr;
if (LK != 0) {
ps.lr = ps.getCurrentInstructionAddress() + 4;
- ps.branchInfo.registerCall(ps.getCurrentInstructionAddress(), ps
+ ps.branchInfo.registerCallSite(ps.getCurrentInstructionAddress(), ps
.getCurrentInstructionAddress() + 4, target_address);
}
// decode BO
@@ -4593,7 +4593,7 @@
int target_address = ps.ctr;
if (LK != 0) {
ps.lr = ps.getCurrentInstructionAddress() + 4;
- ps.branchInfo.registerCall(ps.getCurrentInstructionAddress(), ps
+ ps.branchInfo.registerCallSite(ps.getCurrentInstructionAddress(), ps
.getCurrentInstructionAddress() + 4, target_address);
}
// decode BO
@@ -11618,7 +11618,7 @@
}
if (LK != 0) {
ps.lr = ps.getCurrentInstructionAddress() + 4;
- ps.branchInfo.registerCall(ps.getCurrentInstructionAddress(), ps
+ ps.branchInfo.registerCallSite(ps.getCurrentInstructionAddress(), ps
.getCurrentInstructionAddress() + 4, target_address);
}
// decode BO
@@ -11767,7 +11767,7 @@
}
if (lk != 0) {
ps.lr = ps.getCurrentInstructionAddress() + 4;
- ps.branchInfo.registerCall(ps.getCurrentInstructionAddress(), ps
+ ps.branchInfo.registerCallSite(ps.getCurrentInstructionAddress(), ps
.getCurrentInstructionAddress() + 4, target_address);
}
ps.setCurrentInstructionAddress(target_address);
Modified: src/org/binarytranslator/generic/branchprofile/BranchProfile.java
===================================================================
--- src/org/binarytranslator/generic/branchprofile/BranchProfile.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/generic/branchprofile/BranchProfile.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -12,10 +12,12 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
+import java.util.Map.Entry;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -49,10 +51,101 @@
private final SortedMap<Integer, ProcedureInformation> procedures;
/** A set of switch like branchs sites and their destinations */
- private final SortedMap<Integer, Set<Integer>> branchSitesAndDestinations;
+ private final SortedMap<Integer, BranchInformation> branchSites;
/** Global branch information */
private static BranchProfile global;
+
+ /**
+ * Stores information on a single branch location. */
+ private final static class BranchInformation {
+
+ /** How often the branch instruction has been executed. */
+ private int executionCount;
+
+ /** The target addresses of the branch and how often they have been branched to. */
+ private final Map<Integer, Integer> destinationsAndFrequencies;
+
+ public BranchInformation() {
+ this.destinationsAndFrequencies = new HashMap<Integer, Integer>();
+ }
+
+ public BranchInformation(HashMap<Integer, Integer> destinationsAndFrequencies) {
+ this.destinationsAndFrequencies = destinationsAndFrequencies;
+ executionCount = 0;
+
+ for (Entry<Integer, Integer> target : destinationsAndFrequencies.entrySet()) {
+ executionCount += target.getValue();
+ }
+ }
+
+ public void profile(int target) {
+ executionCount++;
+ Integer targetCount = destinationsAndFrequencies.get(target);
+
+ targetCount = (targetCount == null) ? 1 : targetCount + 1;
+ destinationsAndFrequencies.put(target, targetCount);
+ }
+
+ /** Returns a list of addresses that this branch jumps to. */
+ public Set<Integer> getTargets() {
+ return destinationsAndFrequencies.keySet();
+ }
+
+ public Map<Integer, Integer> getTargetsAndFrequencies() {
+ return destinationsAndFrequencies;
+ }
+
+ public void registerTargetSite(int target) {
+ if (destinationsAndFrequencies.get(target) == null)
+ destinationsAndFrequencies.put(target, 0);
+ }
+
+ /**
+ * Loads a {@link BranchInformation} object from an XML element, given that the object
+ * was previously persisted by {@link #toXML(Document, Element)}.
+ * @param node
+ * The XML element that had been provided to {@link #toXML(Document, Element)}.
+ * @throws IOException
+ */
+ public static BranchInformation fromXML(Element node) throws IOException {
+ HashMap<Integer, Integer> targetsAndFrequencies = new HashMap<Integer, Integer>();
+
+ for (int n = 0; n < node.getChildNodes().getLength(); n++) {
+ Node target = node.getChildNodes().item(n);
+
+ if (target.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ if (!target.getNodeName().equals("target"))
+ throw new IOException("File is not a valid XML branch profile.");
+
+ int targetAddress = Integer.parseInt(((Element)target).getAttribute("address"));
+ int branchCount = Integer.parseInt(((Element)target).getAttribute("address"));
+ targetsAndFrequencies.put(targetAddress, branchCount);
+ }
+
+ return new BranchInformation(targetsAndFrequencies);
+ }
+
+ public void toXML(Document doc, Element parentNode) {
+ Element branchInfo = parentNode;
+
+ Element targets = doc.createElement("targets");
+
+ for (Entry<Integer, Integer> branchTarget : destinationsAndFrequencies.entrySet()) {
+ int targetAddress = branchTarget.getKey();
+ int branchCount = branchTarget.getValue();
+
+ Element branchTargetElement = doc.createElement("target");
+ branchInfo.appendChild(branchTargetElement);
+ branchTargetElement.setAttribute("address", Integer.toString(targetAddress));
+ branchTargetElement.setAttribute("branchCount", Integer.toString(branchCount));
+ }
+
+ branchInfo.appendChild(targets);
+ }
+ }
/**
* Constructor has 2 functions: (1) when making a local trace we don't want to
@@ -62,10 +155,10 @@
public BranchProfile() {
if (global == null) {
global = this;
- branchSitesAndDestinations = new TreeMap<Integer, Set<Integer>>();
+ branchSites = new TreeMap<Integer, BranchInformation>();
}
else {
- branchSitesAndDestinations = global.branchSitesAndDestinations;
+ branchSites = global.branchSites;
}
procedures = new TreeMap<Integer, ProcedureInformation>();
}
@@ -80,7 +173,7 @@
* @param ret
* the address that will be returned to
*/
- public void registerCall(int pc, int dest, int ret) {
+ public void registerCallSite(int pc, int dest, int ret) {
ProcedureInformation procedure = procedures.get(dest);
if (procedure != null) {
@@ -90,27 +183,66 @@
procedures.put(dest, procedure);
}
- registerBranch(pc, dest);
+ registerDynamicBranchSite(pc, dest);
}
+
+ /**
+ * Register a function return.
+ *
+ * @param pc
+ * the address of the return instruction
+ */
+ public void registerReturnSite(int pc) {
+
+ ProcedureInformation procedure = getLikelyProcedure(pc);
+
+ if (procedure != null) {
+ procedure.registerReturn(pc);
+ }
+ }
/**
* Register a function return.
*
* @param pc
- * the address of the branch instruction
+ * the address of the return instruction
* @param lr
* the return address (value of the link register)
*/
- public void registerReturn(int pc, int lr) {
+ public void registerReturnSite(int pc, int lr) {
ProcedureInformation procedure = getLikelyProcedure(pc);
if (procedure != null) {
- procedure.registerReturn(pc, lr);
+ procedure.registerReturn(pc);
}
- registerBranch(pc, lr);
+ registerDynamicBranchSite(pc, lr);
}
+
+ /**
+ * Appends a branch from <code>origin</code> to <code>target</code> to the branch profile.
+ *
+ * @param origin
+ * The address that the branch is taking place from.
+ * @param target
+ * The branch target address.
+ */
+ public void registerDynamicBranchSite(int origin, int target) {
+ //Perform the general branch registration, too
+ BranchInformation branch = branchSites.get(origin);
+
+ if (branch != null) {
+ branch.registerTargetSite(target);
+ // This destination address is already registered
+ return;
+ }
+ else {
+ branch = new BranchInformation();
+ branch.registerTargetSite(target);
+ branchSites.put(origin, branch);
+ }
+ }
/**
* Given an address within a procedure, returns the (most likely) procedure
@@ -128,58 +260,19 @@
}
}
return null;
- }
-
+ }
+
/**
- * Registers a branch from the address <code>origin</code> to the address <code>target</code>.
- * The type of branch is determined by <code>type</code>, which is an ordinal from the
- * {@link BranchType} enum.
+ * Records that a branch from <code>origin</code> to <code>target</code> has been observed while the program is running.
*
* @param origin
- * The address from which the branch occurs.
+ * The address from which the branch took place.
* @param target
- * The address to which the program is branching.
- * @param type
- * The most likely type of the branch. This is taken from the {@link BranchType} enum.
+ * The address to which it took place.
*/
- public void registerBranch(int origin, int target, BranchType type) {
-
- switch (type) {
- case CALL:
- throw new RuntimeException("Use the more specific registerCall() for these cases.");
-
- case RETURN:
- registerReturn(origin, target);
- break;
-
- default:
- registerBranch(origin, target);
- }
+ public void profileBranch(int origin, int target) {
+ throw new RuntimeException("Not yet implemented.");
}
-
- /**
- * Appends a recorded branch from <code>origin</code> to <code>target</code> to the branch profile.
- *
- * @param origin
- * The address that the branch is taking place from.
- * @param target
- * The branch target address.
- */
- private void registerBranch(int origin, int target) {
- //Perform the general branch registration, too
- Set<Integer> dests = branchSitesAndDestinations.get(origin);
-
- if (dests != null && dests.contains(target)) {
- // This destination address is already registered
- return;
- }
- else {
- dests = new HashSet<Integer>();
- branchSitesAndDestinations.put(origin, dests);
- }
-
- dests.add(target);
- }
/**
* Returns a list of known branch targets for the branch at address <code>pc</code>.
@@ -191,7 +284,8 @@
* translated binary, if this list is not complete.
*/
public Set<Integer> getKnownBranchTargets(int pc) {
- return branchSitesAndDestinations.get(pc);
+ BranchInformation branch = branchSites.get(pc);
+ return (branch == null) ? null : branch.getTargets();
}
public void loadFromXML(String filename) throws IOException {
@@ -234,17 +328,9 @@
if (!siteNode.getNodeName().equals("origin") || siteNode.getNodeType() != Node.ELEMENT_NODE)
throw new IOException("File is not a valid XML branch profile.");
- int pc = Integer.parseInt(((Element)siteNode).getAttribute("address"));
-
- for (int n = 0; n < siteNode.getChildNodes().getLength(); n++) {
- Node target = siteNode.getChildNodes().item(n);
-
- if (!target.getNodeName().equals("target") || target.getNodeType() != Node.ELEMENT_NODE)
- throw new IOException("File is not a valid XML branch profile.");
-
- int targetAddress = Integer.parseInt(((Element)target).getAttribute("address"));
- registerBranch(pc, targetAddress);
- }
+ int address = Integer.parseInt(((Element)siteNode).getAttribute("address"));
+ BranchInformation branchInfo = BranchInformation.fromXML((Element)siteNode);
+ branchSites.put(address, branchInfo);
}
}
@@ -289,17 +375,16 @@
Element branchesElement = doc.createElement("branches");
root.appendChild(branchesElement);
-
- for (int pc : branchSitesAndDestinations.keySet()) {
- Element branchSiteElement = doc.createElement("origin");
+
+ for (Entry<Integer, BranchInformation> branch : branchSites.entrySet()) {
+
+ int address = branch.getKey();
+ BranchInformation branchInfo = branch.getValue();
+
+ Element branchSiteElement = doc.createElement("branch");
branchesElement.appendChild(branchSiteElement);
- branchSiteElement.setAttribute("address", Integer.toString(pc));
-
- for (int target : getKnownBranchTargets(pc)) {
- Element branchTargetElement = doc.createElement("target");
- branchSiteElement.appendChild(branchTargetElement);
- branchTargetElement.setAttribute("address", Integer.toString(target));
- }
+ branchSiteElement.setAttribute("address", Integer.toString(address));
+ branchInfo.toXML(doc, branchSiteElement);
}
//Output the resulting XML document
Modified: src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java
===================================================================
--- src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/generic/branchprofile/ProcedureInformation.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -91,13 +91,12 @@
*
* @param pc
* the address of the branch instruction
- * @param ret
- * the address that will be returned to
*/
- public void registerReturn(int pc, int ret) {
+ public void registerReturn(int pc) {
if (returnSites == null) {
returnSites = new HashSet<Integer>();
}
+
returnSites.add(new Integer(pc));
}
@@ -186,11 +185,7 @@
throw new Error("The given XML node is not a valid ProcedureInformation entity.");
}
}
-
-
-
-
-
+
return pi;
}
}
Modified: src/org/binarytranslator/generic/decoder/CodeTranslator.java
===================================================================
--- src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/generic/decoder/CodeTranslator.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -607,13 +607,15 @@
branch, (Laziness) targetLaziness.clone(), currentPC, targetPC, BranchType.CALL);
unresolvedDirectBranches.add(unresolvedJump);
- if (branchType == BranchType.CALL)
- ps.branchInfo.registerCall(currentPC, targetPC, retAddr);
- else
- if (branchType == BranchType.RETURN)
- ps.branchInfo.registerReturn(currentPC, targetPC);
- else
- ps.branchInfo.registerBranch(currentPC, targetPC, branchType);
+ switch (branchType) {
+ case CALL:
+ ps.branchInfo.registerCallSite(currentPC, targetPC, retAddr);
+ break;
+
+ case RETURN:
+ ps.branchInfo.registerReturnSite(currentPC, targetPC);
+ break;
+ }
}
/**
@@ -929,7 +931,7 @@
* the destination of the branch instruction
*/
public void registerBranchAndLink(int pc, int ret, int dest) {
- ps.branchInfo.registerCall(pc, ret, dest);
+ ps.branchInfo.registerCallSite(pc, ret, dest);
}
/**
Added: src/org/binarytranslator/generic/decoder/Disassembler.java
===================================================================
--- src/org/binarytranslator/generic/decoder/Disassembler.java (rev 0)
+++ src/org/binarytranslator/generic/decoder/Disassembler.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -0,0 +1,46 @@
+package org.binarytranslator.generic.decoder;
+
+public interface Disassembler {
+ /**
+ * Represents an instruction, after it has been decoded by a disassembler.
+ * The instruction should be printable in the format of the target system's assembly language.
+ *
+ * @author Michael Baer
+ */
+ public interface Instruction {
+ /**
+ * Shall return the address of the instruction following this one in <i>code order</i>, given that
+ * the current instruction has been decoded from address <code>pc</code>.
+ * @param pc
+ * The address from which this instruction has been decoded.
+ * @return
+ * The address of the instruction following this one in code order.
+ */
+ int getSuccessor(int pc);
+
+ /**
+ * Shall return a string representation of the disassembled instruction.
+ * We might have used toString() here, but I wanted it to be obvious if a dedicated implementation
+ * of this method is missing.
+ *
+ * @return
+ * A string representation of the disassembled instruction.
+ * For example:
+ * <code>
+ * ADD r0, r1, #15
+ * </code>
+ * for an ARM ADD instruction.
+ */
+ String asString();
+ }
+
+ /**
+ * Disassemble the instruction at address <code>pc</code> and return an appropriate object representation.
+ *
+ * @param pc
+ * The address at which the instruction resides.
+ * @return
+ * An object representation of the said instruction.
+ */
+ Instruction disassemble(int pc);
+}
Modified: src/org/binarytranslator/generic/decoder/Interpreter.java
===================================================================
--- src/org/binarytranslator/generic/decoder/Interpreter.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/generic/decoder/Interpreter.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -1,5 +1,9 @@
package org.binarytranslator.generic.decoder;
+/**
+ * TODO: Add comments for this interface.
+ *
+ */
public interface Interpreter {
public interface Instruction {
Modified: src/org/binarytranslator/generic/execution/InterpreterController.java
===================================================================
--- src/org/binarytranslator/generic/execution/InterpreterController.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/generic/execution/InterpreterController.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -1,5 +1,6 @@
package org.binarytranslator.generic.execution;
+import org.binarytranslator.DBT_Options;
import org.binarytranslator.generic.decoder.Interpreter;
import org.binarytranslator.generic.os.process.ProcessSpace;
@@ -22,12 +23,19 @@
instruction.execute();
//System.out.println(ps.toString());
- pc = instruction.getSuccessor(pc);
+ int nextInstruction = instruction.getSuccessor(pc);
- if (pc == -1)
- pc = ps.getCurrentInstructionAddress();
- else
- ps.setCurrentInstructionAddress(pc);
+ if (nextInstruction == -1) {
+ nextInstruction = ps.getCurrentInstructionAddress();
+
+ if (DBT_Options.profileDuringInterpretation)
+ ps.branchInfo.profileBranch(pc, ps.getCurrentInstructionAddress());
+ }
+ else {
+ ps.setCurrentInstructionAddress(nextInstruction);
+ }
+
+ pc = nextInstruction;
}
}
}
Modified: src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java
===================================================================
--- src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/generic/execution/PredecodingThreadedInterpreter.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -8,7 +8,7 @@
import org.binarytranslator.generic.decoder.Interpreter;
import org.binarytranslator.generic.os.process.ProcessSpace;
-public final class PredecodingThreadedInterpreter extends ExecutionController {
+public class PredecodingThreadedInterpreter extends ExecutionController {
private final HashMap<Integer, List<Interpreter.Instruction>> traceCache = new HashMap<Integer, List<Interpreter.Instruction>>();
private final Interpreter interpreter;
@@ -42,16 +42,19 @@
return newTrace;
}
- private void executeTrace(List<Interpreter.Instruction> trace, int pc) {
+ protected void executeTrace(List<Interpreter.Instruction> trace, int pc) {
Iterator<Interpreter.Instruction> instructions = trace.iterator();
- while (instructions.hasNext()) {
+ while (true) {
Interpreter.Instruction instr = instructions.next();
instr.execute();
- pc = instr.getSuccessor(pc);
- if (pc != -1)
+ if (instructions.hasNext()) {
+ pc = instr.getSuccessor(pc);
ps.setCurrentInstructionAddress(pc);
+ }
+ else
+ break;
}
}
@@ -61,7 +64,7 @@
}
@Override
- public void run() {
+ public final void run() {
int pc = ps.getCurrentInstructionAddress();
while (!ps.finished) {
Added: src/org/binarytranslator/generic/execution/ProfilingPredecodingInterpreter.java
===================================================================
--- src/org/binarytranslator/generic/execution/ProfilingPredecodingInterpreter.java (rev 0)
+++ src/org/binarytranslator/generic/execution/ProfilingPredecodingInterpreter.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -0,0 +1,40 @@
+package org.binarytranslator.generic.execution;
+
+import java.util.Iterator;
+import java.util.List;
+import org.binarytranslator.generic.decoder.Interpreter;
+import org.binarytranslator.generic.decoder.Interpreter.Instruction;
+import org.binarytranslator.generic.os.process.ProcessSpace;
+
+/**
+ * Adds runtime profiling capabilities to {@link PredecodingThreadedInterpreter}.
+ */
+public class ProfilingPredecodingInterpreter extends PredecodingThreadedInterpreter {
+
+ public ProfilingPredecodingInterpreter(ProcessSpace ps) {
+ super(ps);
+ }
+
+ @Override
+ protected void executeTrace(List<Instruction> trace, int pc) {
+ Iterator<Interpreter.Instruction> instructions = trace.iterator();
+ while (true) {
+ Interpreter.Instruction instr = instructions.next();
+
+ if (instructions.hasNext()) {
+ instr.execute();
+ pc = instr.getSuccessor(pc);
+ ps.setCurrentInstructionAddress(pc);
+
+ }
+ else {
+ int instructionAdddress = ps.getCurrentInstructionAddress();
+ instr.execute();
+ pc = ps.getCurrentInstructionAddress();
+ ps.branchInfo.profileBranch(instructionAdddress, pc);
+ break;
+ }
+ }
+ }
+
+}
Modified: src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java
===================================================================
--- src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -35,7 +35,7 @@
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>();;
+ protected final HashMap<String, String> libNames = new HashMap<String, String>();
public static class SharedObject {
/** The libary's name. */
Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java
===================================================================
--- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-07-11 16:34:25 UTC (rev 151)
+++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-07-29 13:13:16 UTC (rev 152)
@@ -155,15 +155,15 @@
switch (type) {
case CALL:
- branchInfo.registerCall(location, destination, returnAddress);
+ branchInfo.registerCallSite(location, destination, returnAddress);
return;
case RETURN:
- branchInfo.registerReturn(location, destination);
+ branchInfo.registerReturnSite(location, destination);
return;
default:
- branchInfo.registerBranch(location, destination, BranchType.values()[code]);
+ branchInfo.registerDynamicBranchSite(location, destination);
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-07-11 16:34:30
|
Revision: 151
http://svn.sourceforge.net/pearcolator/?rev=151&view=rev
Author: michael_baer
Date: 2007-07-11 09:34:25 -0700 (Wed, 11 Jul 2007)
Log Message:
-----------
- Make sure that the runtime linker does not return a local symbol when we're trying to resolve a global symbol.
Modified Paths:
--------------
src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java
src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java
Modified: src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java
===================================================================
--- src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java 2007-07-09 10:42:27 UTC (rev 150)
+++ src/org/binarytranslator/arch/arm/os/process/loader/ARM_RuntimeLinker.java 2007-07-11 16:34:25 UTC (rev 151)
@@ -70,7 +70,7 @@
if (symbol.isUndefined()) {
String symbolName = strTab.lookup(symbol.nameIdx);
- value = resolveSymbolAddress(symbolName);
+ value = resolveSymbolAddress(symbolName, lib);
if (value == -1) {
//we allow only weak symbols to be unresolved
Modified: src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java
===================================================================
--- src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-07-09 10:42:27 UTC (rev 150)
+++ src/org/binarytranslator/generic/os/loader/elf/JavaRuntimeLinker.java 2007-07-11 16:34:25 UTC (rev 151)
@@ -119,6 +119,7 @@
* This function is the main entry point into the dynamic linker and will steer the whole
* linking process.
*/
+ @Override
public final void link() throws IOException {
ELF_File.DynamicSection dynSection = file.getDynamicSection();
@@ -193,7 +194,7 @@
*/
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");
+ int dl_starting_up = resolveSymbolAddress("_dl_starting_up", null);
if (dl_starting_up != -1)
ps.memory.store32(dl_starting_up, 1);
@@ -392,10 +393,13 @@
*
* @param symbol
* The name of the symbol that is to be resolved.
+ * @param obj
+ * The shared object for which we are trying to resolve the symbol address. Local symbols from
+ * this object will be returned as a match as well.
* @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 {
+ protected final int resolveSymbolAddress(String symbol, SharedObject obj) throws IOException {
Iterator<SharedObject> libs = libraries.iterator();
//iterate over the symbol table of every library that we already loaded
@@ -406,8 +410,10 @@
//see if <symbol> is defined within this library
SymbolTable.Entry entry = hashTab.lookup(symbol);
- if (entry != null && !entry.isUndefined())
- return entry.value + lib.loadedAt;
+ if (entry != null && !entry.isUndefined() && entry.binding != SymbolTable.STB_LOCAL) {
+ if (entry.binding == SymbolTable.STB_GLOBAL || lib == obj)
+ return entry.value + lib.loadedAt;
+ }
}
return -1;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mic...@us...> - 2007-07-09 10:42:30
|
Revision: 150
http://svn.sourceforge.net/pearcolator/?rev=150&view=rev
Author: michael_baer
Date: 2007-07-09 03:42:27 -0700 (Mon, 09 Jul 2007)
Log Message:
-----------
- Added disassembler interface
Modified Paths:
--------------
src/org/binarytranslator/generic/os/process/ProcessSpace.java
Modified: src/org/binarytranslator/generic/os/process/ProcessSpace.java
===================================================================
--- src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-07-09 10:36:57 UTC (rev 149)
+++ src/org/binarytranslator/generic/os/process/ProcessSpace.java 2007-07-09 10:42:27 UTC (rev 150)
@@ -18,6 +18,7 @@
import org.binarytranslator.generic.branchprofile.BranchProfile.BranchType;
import org.binarytranslator.generic.decoder.CodeTranslator;
import org.binarytranslator.generic.decoder.CodeCache;
+import org.binarytranslator.generic.decoder.Disassembler;
import org.binarytranslator.generic.decoder.Interpreter;
import org.binarytranslator.generic.execution.GdbController.GdbTarget;
import org.binarytranslator.generic.memory.Memory;
@@ -80,9 +81,15 @@
throw new UnsupportedOperationException();
}
+ public Disassembler createDisassembler() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+
/** Return a string disassembly of the instuction at the given address*/
@Uninterruptible
- public abstract String disassembleInstruction(int pc) throws UnsupportedOperationException ;
+ public String disassembleInstruction(int pc) throws UnsupportedOperationException {
+ return createDisassembler().disassemble(pc).asString();
+ }
/**
* Given an ELF binary loader, create the appropriate process space
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|