-// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
+// Copyright 2000-2005 the Contributors, as shown in the revision logs.
+// Licensed under the Apache Public Source License 2.0 ("the License").
+// You may not use this file except in compliance with the License.
package org.ibex.nestedvm;
import org.ibex.nestedvm.util.*;
-// FEATURE: -d option for classfilecompiler (just like javac's -d)
-
public abstract class Compiler implements Registers {
/** The ELF binary being read */
- protected ELF elf;
+ ELF elf;
/** The name of the class beging generated */
- protected final String fullClassName;
+ final String fullClassName;
/** The name of the binary this class is begin generated from */
- protected String source = "unknown.mips.binary";
+ String source = "unknown.mips.binary";
public void setSource(String source) { this.source = source; }
/** Thrown when the compilation fails for some reason */
- protected static class Exn extends Exception { public Exn(String s) { super(s); } }
+ static class Exn extends Exception { public Exn(String s) { super(s); } }
// Set this to true to enable fast memory access
// When this is enabled a Java RuntimeException will be thrown when a page fault occures. When it is disabled
// a FaultException will be throw which is easier to catch and deal with, however. as the name implies, this is slower
- protected boolean fastMem = true;
+ boolean fastMem = true;
// This MUST be a power of two. If it is not horrible things will happen
// NOTE: This value can be much higher without breaking the classfile
// specs (around 1024) but Hotstop seems to do much better with smaller
// methods.
- protected int maxInsnPerMethod = 128;
+ int maxInsnPerMethod = 128;
// non-configurable
- protected int maxBytesPerMethod;
- protected int methodMask;
- protected int methodShift;
- protected void maxInsnPerMethodInit() throws Exn {
+ int maxBytesPerMethod;
+ int methodMask;
+ int methodShift;
+ void maxInsnPerMethodInit() throws Exn {
if((maxInsnPerMethod&(maxInsnPerMethod-1)) != 0) throw new Exn("maxBytesPerMethod is not a power of two");
maxBytesPerMethod = maxInsnPerMethod*4;
methodMask = ~(maxBytesPerMethod-1);
}
// True to try to determine which case statement are needed and only include them
- protected boolean pruneCases = true;
-
- protected boolean assumeTailCalls = true;
+ boolean pruneCases = true;
- protected boolean optimizedMemcpy = true;
+ boolean assumeTailCalls = true;
// True to insert some code in the output to help diagnore compiler problems
- protected boolean debugCompiler = false;
+ boolean debugCompiler = false;
// True to print various statistics about the compilation
- protected boolean printStats = false;
+ boolean printStats = false;
// True to generate runtime statistics that slow execution down significantly
- protected boolean runtimeStats = false;
+ boolean runtimeStats = false;
+
+ boolean supportCall = true;
- protected boolean supportCall = true;
+ boolean nullPointerCheck = false;
- protected boolean nullPointerCheck = false;
+ String runtimeClass = "org.ibex.nestedvm.Runtime";
- protected String runtimeClass = "org.ibex.nestedvm.Runtime";
+ String hashClass = "java.util.Hashtable";
- protected String hashClass = "java.util.Hashtable";
+ boolean unixRuntime;
- protected boolean unixRuntime;
+ boolean lessConstants;
- protected boolean lessConstants = false;
+ boolean singleFloat;
- protected int pageSize = 4096;
- protected int totalPages = 65536;
- protected int pageShift;
- protected boolean onePage;
+ int pageSize = 4096;
+ int totalPages = 65536;
+ int pageShift;
+ boolean onePage;
- protected void pageSizeInit() throws Exn {
+ void pageSizeInit() throws Exn {
if((pageSize&(pageSize-1)) != 0) throw new Exn("pageSize not a multiple of two");
if((totalPages&(totalPages-1)) != 0) throw new Exn("totalPages not a multiple of two");
while(pageSize>>>pageShift != 1) pageShift++;
}
- /** The address of the memcpy function in the binary (used for optimizedMemcpy) */
- protected int memcpy;
-
- /** The address of the memset function in the binary (used for optimizedMemcpy) */
- protected int memset;
-
/** A set of all addresses that can be jumped too (only available if pruneCases == true) */
- protected Set jumpableAddresses;
+ Hashtable jumpableAddresses;
/** Some important symbols */
ELF.Symbol userInfo, gp;
public static void main(String[] args) throws IOException {
String outfile = null;
+ String outdir = null;
String o = null;
String className = null;
String mipsBinaryFileName = null;
arg++;
if(arg==args.length) usage();
outfile = args[arg];
+ } else if(args[arg].equals("-d")) {
+ arg++;
+ if(arg==args.length) usage();
+ outdir = args[arg];
} else if(args[arg].equals("-outformat")) {
arg++;
if(arg==args.length) usage();
OutputStream os = null;
Compiler comp = null;
if(outformat == null || outformat.equals("class")) {
- if(outfile == null) {
+ if(outfile != null) {
+ os = new FileOutputStream(outfile);
+ comp = new ClassFileCompiler(mipsBinary,className,os);
+ } else if(outdir != null) {
+ File f = new File(outdir);
+ if(!f.isDirectory()) {
+ System.err.println(outdir + " doesn't exist or is not a directory");
+ System.exit(1);
+ }
+ comp = new ClassFileCompiler(mipsBinary,className,f);
+ } else {
System.err.println("Refusing to write a classfile to stdout - use -outfile foo.class");
System.exit(1);
}
- os = new FileOutputStream(outfile);
- comp = new ClassFileCompiler(mipsBinary,className,os);
} else if(outformat.equals("javasource") || outformat .equals("java")) {
w = outfile == null ? new OutputStreamWriter(System.out): new FileWriter(outfile);
comp = new JavaSourceCompiler(mipsBinary,className,w);
this.fullClassName = fullClassName;
elf = new ELF(binary);
- if(elf.header.type != ELF.ELFHeader.ET_EXEC) throw new IOException("Binary is not an executable");
- if(elf.header.machine != ELF.ELFHeader.EM_MIPS) throw new IOException("Binary is not for the MIPS I Architecture");
- if(elf.ident.data != ELF.ELFIdent.ELFDATA2MSB) throw new IOException("Binary is not big endian");
+ if(elf.header.type != ELF.ET_EXEC) throw new IOException("Binary is not an executable");
+ if(elf.header.machine != ELF.EM_MIPS) throw new IOException("Binary is not for the MIPS I Architecture");
+ if(elf.ident.data != ELF.ELFDATA2MSB) throw new IOException("Binary is not big endian");
}
- protected abstract void _go() throws Exn, IOException;
+ abstract void _go() throws Exn, IOException;
private boolean used;
public void go() throws Exn, IOException {
if(symtab == null) throw new Exn("Binary has no symtab (did you strip it?)");
ELF.Symbol sym;
- // Check for some functions we can override
- sym = symtab.getGlobalSymbol("memcpy");
- memcpy = sym == null ? -1 : sym.addr;
-
- sym = symtab.getGlobalSymbol("memset");
- memset = sym == null ? -1 : sym.addr;
-
userInfo = symtab.getGlobalSymbol("user_info");
gp = symtab.getGlobalSymbol("_gp");
if(gp == null) throw new Exn("no _gp symbol (did you strip the binary?)");
if(pruneCases) {
// Find all possible branches
- jumpableAddresses = new HashSet();
+ jumpableAddresses = new Hashtable();
- jumpableAddresses.add(new Integer(elf.header.entry));
+ jumpableAddresses.put(new Integer(elf.header.entry),Boolean.TRUE);
ELF.SHeader text = elf.sectionWithName(".text");
if(text == null) throw new Exn("No .text segment");
for(int i=0;i<elf.sheaders.length;i++) {
String name = elf.sheaders[i].name;
- if(elf.sheaders[i].addr != 0 && !(
+ if((elf.sheaders[i].flags & ELF.SHF_ALLOC) !=0 && !(
name.equals(".text")|| name.equals(".data") || name.equals(".sdata") || name.equals(".rodata") ||
name.equals(".ctors") || name.equals(".dtors") || name.equals(".bss") || name.equals(".sbss")))
throw new Exn("Unknown section: " + name);
_go();
}
- private void findBranchesInSymtab(ELF.Symtab symtab, Set jumps) {
+ private void findBranchesInSymtab(ELF.Symtab symtab, Hashtable jumps) {
ELF.Symbol[] symbols = symtab.symbols;
int n=0;
for(int i=0;i<symbols.length;i++) {
ELF.Symbol s = symbols[i];
if(s.type == ELF.Symbol.STT_FUNC) {
- if(jumps.add(new Integer(s.addr))) {
+ if(jumps.put(new Integer(s.addr),Boolean.TRUE) == null) {
//System.err.println("Adding symbol from symtab: " + s.name + " at " + toHex(s.addr));
n++;
}
if(printStats) System.err.println("Found " + n + " additional possible branch targets in Symtab");
}
- private void findBranchesInText(int base, DataInputStream dis, int size, Set jumps) throws IOException {
+ private void findBranchesInText(int base, DataInputStream dis, int size, Hashtable jumps) throws IOException {
int count = size/4;
int pc = base;
int n=0;
case 0:
switch(subcode) {
case 9: // JALR
- if(jumps.add(new Integer(pc+8))) n++; // return address
+ if(jumps.put(new Integer(pc+8),Boolean.TRUE) == null) n++; // return address
break;
case 12: // SYSCALL
- if(jumps.add(new Integer(pc+4))) n++;
+ if(jumps.put(new Integer(pc+4),Boolean.TRUE) == null) n++;
break;
}
break;
switch(rt) {
case 16: // BLTZAL
case 17: // BGTZAL
- if(jumps.add(new Integer(pc+8))) n++; // return address
+ if(jumps.put(new Integer(pc+8),Boolean.TRUE) == null) n++; // return address
// fall through
case 0: // BLTZ
case 1: // BGEZ
- if(jumps.add(new Integer(pc+branchTarget*4+4))) n++;
+ if(jumps.put(new Integer(pc+branchTarget*4+4),Boolean.TRUE) == null) n++;
break;
}
break;
case 3: // JAL
- if(jumps.add(new Integer(pc+8))) n++; // return address
+ if(jumps.put(new Integer(pc+8),Boolean.TRUE) == null) n++; // return address
// fall through
case 2: // J
- if(jumps.add(new Integer((pc&0xf0000000)|(jumpTarget << 2)))) n++;
+ if(jumps.put(new Integer((pc&0xf0000000)|(jumpTarget << 2)),Boolean.TRUE) == null) n++;
break;
case 4: // BEQ
case 5: // BNE
case 6: // BLEZ
case 7: // BGTZ
- if(jumps.add(new Integer(pc+branchTarget*4+4))) n++;
+ if(jumps.put(new Integer(pc+branchTarget*4+4),Boolean.TRUE) == null) n++;
break;
case 9: { // ADDIU
if(pc - lui_pc[rs] <= 4*32) {
int t = (lui_val[rs]<<16)+signedImmediate;
if((t&3)==0 && t >= base && t < base+size) {
- if(jumps.add(new Integer(t))) {
+ if(jumps.put(new Integer(t),Boolean.TRUE) == null) {
//System.err.println("Possible jump to " + toHex(t) + " (" + inter.sourceLine(t) + ") from " + toHex(pc) + " (" + inter.sourceLine(pc) + ")");
n++;
}
case 17: // FPU Instructions
switch(rs) {
case 8: // BC1F, BC1T
- if(jumps.add(new Integer(pc+branchTarget*4+4))) n++;
+ if(jumps.put(new Integer(pc+branchTarget*4+4),Boolean.TRUE) == null) n++;
break;
}
break;
if(printStats) System.err.println("Found " + n + " additional possible branch targets in Text segment");
}
- private void findBranchesInData(DataInputStream dis, int size, Set jumps, int textStart, int textEnd) throws IOException {
+ private void findBranchesInData(DataInputStream dis, int size, Hashtable jumps, int textStart, int textEnd) throws IOException {
int count = size/4;
int n=0;
for(int i=0;i<count;i++) {
int word = dis.readInt();
if((word&3)==0 && word >= textStart && word < textEnd) {
- if(jumps.add(new Integer(word))) {
+ if(jumps.put(new Integer(word),Boolean.TRUE) == null) {
//System.err.println("Added " + toHex(word) + " as possible branch target (fron data segment)");
n++;
}
}
// Helper functions for pretty output
- protected final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
- protected final static String toHex8(int n) {
+ final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
+ final static String toHex8(int n) {
String s = Long.toString(n & 0xffffffffL, 16);
StringBuffer sb = new StringBuffer("0x");
for(int i=8-s.length();i>0;i--) sb.append('0');
return sb.toString();
}
- protected final static String toOctal3(int n) {
+ final static String toOctal3(int n) {
char[] buf = new char[3];
for(int i=2;i>=0;i--) {
buf[i] = (char) ('0' + (n & 7));
public void set(Object val) {
if(field == null) return;
try {
- field.setAccessible(true);
+ /*field.setAccessible(true); NOT in JDK 1.1 */
field.set(Compiler.this,val);
} catch(IllegalAccessException e) {
System.err.println(e);
public Object get() {
if(field == null) return null;
try {
- field.setAccessible(true);
+ /*field.setAccessible(true); NOT in JDK 1.1 */
return field.get(Compiler.this);
} catch(IllegalAccessException e) {
System.err.println(e); return null;
"pageSize", "The page size (must be a power of two)",
"totalPages", "Total number of pages (total mem = pageSize*totalPages, must be a power of two)",
"onePage", "One page hack (FIXME: document this better)",
- "lessConstants", "Use less constants at the cost of speed (FIXME: document this better)"
+ "lessConstants", "Use less constants at the cost of speed (FIXME: document this better)",
+ "singleFloat", "Support single precision (32-bit) FP ops only"
};
private Option getOption(String name) {
// This ugliness is to work around a gcj static linking bug (Bug 12908)
// The best solution is to force gnu.java.locale.Calendar to be linked in but this'll do
- protected static String dateTime() {
+ static String dateTime() {
try {
return new Date().toString();
} catch(RuntimeException e) {