-// Copyright 2003 Adam Megacz
-// Author Brian Alliet
-// Based on org.xwt.mips.Compiler by Adam Megacz
-
+// Copyright 2003 Brian Alliet
+// Based on org.xwt.imp.MIPS by Adam Megacz
+// Portions Copyright 2003 Adam Megacz
package org.xwt.mips;
-import java.io.*;
-public class Interpreter extends VM {
+import java.io.*;
+public class Interpreter extends Runtime {
// Registers
private int[] registers = new int[32];
private int hi,lo;
// Floating Point Registers
private int[] fpregs = new int[32];
-
// 24-31 - unused
- // 23 - conditional bit
+ // 23 - conditional bit
// 18-22 - unused
// 12-17 - cause bits (unimplemented)
// 7-11 - enables bits (unimplemented)
private int nextPC;
- // The filename if the binary we're running
- private Object image;
-
// Register Operations
private final void setFC(boolean b) { fcsr = (fcsr&~0x800000) | (b ? 0x800000 : 0x000000); }
private final int roundingMode() { return fcsr & 3; /* bits 0-1 */ }
private final float getFloat(int r) { return Float.intBitsToFloat(fpregs[r]); }
private final void setFloat(int r, float f) { fpregs[r] = Float.floatToRawIntBits(f); }
- // Main run loop
- public void execute() throws EmulationException {
- int[] r = registers;
- if(state == PAUSED) state = RUNNING;
- if(state != RUNNING) throw new IllegalStateException("execute() called in inappropriate state");
- runSome(nextPC);
- }
+ protected void _execute() throws ExecutionException { runSome(); }
- // Main interpretor (also used for compilation)
+ // Main interpretor
// the return value is meaningless, its just to catch people typing "return" by accident
- private int runSome(int pc) throws FaultException,EmulationException {
+ private final int runSome() throws FaultException,ExecutionException {
int[] r = registers;
int[] f = fpregs;
+ int pc = nextPC;
int nextPC = pc + 4;
try {
OUTER: for(;;) {
case 3: // SRA
r[rd] = r[rt] >> shamt;
break;
- // FIXME: Do we need % 32 on the r[rs] ?
case 4: // SLLV
- r[rd] = r[rt] << r[rs];
+ r[rd] = r[rt] << (r[rs]&0x1f);
break;
case 6: // SRLV
- r[rd] = r[rt] >>> r[rs];
+ r[rd] = r[rt] >>> (r[rs]&0x1f);
break;
case 7: // SRAV
- r[rd] = r[rt] >> r[rs];
+ r[rd] = r[rt] >> (r[rs]&0x1f);
break;
case 8: // JR
tmp = r[rs]; pc += 4; nextPC = tmp;
}
break;
case 13: // BREAK
- throw new EmulationException("Break");
+ throw new ExecutionException("Break");
case 16: // MFHI
r[rd] = hi;
break;
lo = (int)((r[rs] & 0xffffffffL) / (r[rt] & 0xffffffffL));
break;
case 32: // ADD
- r[rd] = r[rs] + r[rt]; // FIXME: Trap on overflow
- break;
+ throw new ExecutionException("ADD (add with oveflow trap) not suported");
+ /*This must trap on overflow
+ r[rd] = r[rs] + r[rt];
+ break;*/
case 33: // ADDU
r[rd] = r[rs] + r[rt];
break;
case 34: // SUB
- r[rd] = r[rs] - r[rt]; // FIXME: Trap on overflow
- break;
+ throw new ExecutionException("SUB (sub with oveflow trap) not suported");
+ /*This must trap on overflow
+ r[rd] = r[rs] - r[rt];
+ break;*/
case 35: // SUBU
r[rd] = r[rs] - r[rt];
break;
r[rd] = ((r[rs] & 0xffffffffL) < (r[rt] & 0xffffffffL)) ? 1 : 0;
break;
default:
- throw new EmulationException("Illegal instruction 0/" + subcode);
+ throw new ExecutionException("Illegal instruction 0/" + subcode);
}
break;
}
}
break;
default:
- throw new EmulationException("Illegal Instruction");
+ throw new ExecutionException("Illegal Instruction");
}
break;
}
r[rt] = unsignedImmediate << 16;
break;
case 16:
- throw new EmulationException("TLB/Exception support not implemented");
+ throw new ExecutionException("TLB/Exception support not implemented");
case 17: { // FPU
boolean debug = false;
- String line = debug ? sourceLine(pc) : "";
+ String line = "";
boolean debugon = debug && (line.indexOf("dtoa.c:51") >= 0 || line.indexOf("dtoa.c:52") >= 0 || line.indexOf("test.c") >= 0);
if(rs > 8 && debugon)
System.out.println(" FP Op: " + op + "/" + rs + "/" + subcode + " " + line);
- // FIXME: This could probably be removed. I don't think gcc will ever generate code that does this
+ // FEATURE: This could probably be removed. I don't think gcc will ever generate code that does this
if(roundingMode() != 0 && rs != 6 /*CTC.1*/ && !((rs==16 || rs==17) && subcode == 36 /* CVT.W.Z */))
- throw new EmulationException("Non-cvt.w.z operation attempted with roundingMode != round to nearest");
+ throw new ExecutionException("Non-cvt.w.z operation attempted with roundingMode != round to nearest");
switch(rs) {
case 0: // MFC.1
r[rt] = f[rd];
break;
case 2: // CFC.1
- if(fs != 31) throw new EmulationException("FCR " + fs + " unavailable");
+ if(fs != 31) throw new ExecutionException("FCR " + fs + " unavailable");
r[rt] = fcsr;
break;
case 4: // MTC.1
f[rd] = r[rt];
break;
case 6: // CTC.1
- if(fs != 31) throw new EmulationException("FCR " + fs + " unavailable");
+ if(fs != 31) throw new ExecutionException("FCR " + fs + " unavailable");
fcsr = r[rt];
break;
case 8: // BC1F, BC1T
f[fd] = f[fs];
break;
case 7: // NEG.S
- setFloat(fd,-getFloat(fs)); // FIXME: just flip the sign bit
+ setFloat(fd,-getFloat(fs)); // FEATURE: just flip the sign bit
break;
case 33: // CVT.D.S
setDouble(fd,getFloat(fs));
}
break;
case -50: // C.EQ.S
- setFC(getFloat(fs) == getFloat(ft)); // FIXME: just compare the ints, be sure things are normalized
+ setFC(getFloat(fs) == getFloat(ft)); // FEATURE: just compare the ints, be sure things are normalized
break;
case 60: // C.LT.S
setFC(getFloat(fs) < getFloat(ft));
break;
- default: throw new EmulationException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc));
+ default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode);
}
break;
}
f[fd+1] = f[fs+1];
break;
case 7: // NEG.D
- setDouble(fd,-getDouble(fs)); // FIXME: just flip the sign bit
+ setDouble(fd,-getDouble(fs)); // FEATURE: just flip the sign bit
break;
case 32: // CVT.S.D
setFloat(fd,(float)getDouble(fs));
if(debugon) System.out.println("CVT.W.D: f" + fd + ":" + f[fd]);
break;
case 50: // C.EQ.D
- setFC(getDouble(fs) == getDouble(ft)); // FIXME: just compare the ints, be sure things are normalized
+ setFC(getDouble(fs) == getDouble(ft)); // FEATURE: just compare the ints, be sure things are normalized
break;
case 60: // C.LT.D
setFC(getDouble(fs) < getDouble(ft));
case 62: // C.LE.D
setFC(getDouble(fs) <= getDouble(ft));
break;
- default: throw new EmulationException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc));
+ default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode);
}
break;
}
case 33: // CVT.D.W
setDouble(fd,(double)f[fs]);
break;
- default: throw new EmulationException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc));
+ default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode);
}
break;
}
default:
- throw new EmulationException("Invalid Instruction 17/" + rs);
+ throw new ExecutionException("Invalid Instruction 17/" + rs);
}
break;
}
case 18: case 19:
- throw new EmulationException("No coprocessor installed");
+ throw new ExecutionException("No coprocessor installed");
case 32: { // LB
addr = r[rs] + signedImmediate;
try {
- tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
+ tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
} catch(RuntimeException e) {
tmp = memRead(addr&~3);
}
case 33: { // LH
addr = r[rs] + signedImmediate;
try {
- tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
+ tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
} catch(RuntimeException e) {
tmp = memRead(addr&~3);
}
case 34: { // LWL;
addr = r[rs] + signedImmediate;
try {
- tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
+ tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
} catch(RuntimeException e) {
tmp = memRead(addr&~3);
}
case 35: // LW
addr = r[rs] + signedImmediate;
try {
- r[rt] = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
+ r[rt] = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
} catch(RuntimeException e) {
r[rt] = memRead(addr);
}
case 36: { // LBU
addr = r[rs] + signedImmediate;
try {
- tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
+ tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
} catch(RuntimeException e) {
tmp = memRead(addr);
}
case 37: { // LHU
addr = r[rs] + signedImmediate;
try {
- tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
+ tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
} catch(RuntimeException e) {
tmp = memRead(addr&~3);
}
case 38: { // LWR
addr = r[rs] + signedImmediate;
try {
- tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
+ tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
} catch(RuntimeException e) {
tmp = memRead(addr&~3);
}
case 40: { // SB
addr = r[rs] + signedImmediate;
try {
- tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
+ tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
} catch(RuntimeException e) {
tmp = memRead(addr&~3);
}
case 3: tmp = (tmp&0xffffff00) | ((r[rt]&0xff)<< 0); break;
}
try {
- writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = tmp;
+ writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp;
} catch(RuntimeException e) {
memWrite(addr&~3,tmp);
}
case 41: { // SH
addr = r[rs] + signedImmediate;
try {
- tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
+ tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)];
} catch(RuntimeException e) {
tmp = memRead(addr&~3);
}
case 2: tmp = (tmp&0xffff0000) | ((r[rt]&0xffff)<< 0); break;
}
try {
- writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = tmp;
+ writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp;
} catch(RuntimeException e) {
memWrite(addr&~3,tmp);
}
case 3: tmp=(tmp&0xffffff00)|(r[rt]>>>24); break;
}
try {
- writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = tmp;
+ writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp;
} catch(RuntimeException e) {
memWrite(addr&~3,tmp);
}
case 43: // SW
addr = r[rs] + signedImmediate;
try {
- writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = r[rt];
+ writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = r[rt];
} catch(RuntimeException e) {
memWrite(addr&~3,r[rt]);
}
memWrite(r[rs] + signedImmediate,f[rt]);
break;
default:
- throw new EmulationException("Invalid Instruction: " + op);
+ throw new ExecutionException("Invalid Instruction: " + op);
}
pc = nextPC;
nextPC = pc + 4;
} // for(;;)
- } catch(EmulationException e) {
+ } catch(ExecutionException e) {
this.nextPC = pc;
throw e;
}
// Image loading function
void loadImage(Object file) throws IOException {
- ELF elf = null;
- if (file instanceof String) elf = new ELF(new RandomAccessFile((String)file,"r"));
- else if (file instanceof byte[]) elf = new ELF((byte[])file);
+ ELF elf = new ELF(file);
if(elf.header.type != ELF.ELFHeader.ET_EXEC)
throw new IOException("Binary is not an executable");
if(elf.header.machine != ELF.ELFHeader.EM_MIPS)
dis.close();
}
}
- image = file;
state = INITIALIZED;
}
protected void _start(int pc) {
+ registers[K0] = STUFF_BASE;
+ registers[K1] = PAGE_SIZE;
registers[SP] = INITIAL_SP;
registers[RA] = 0xdeadbeef;
nextPC = pc;
}
- public Interpreter() { }
- public Interpreter(String image) throws IOException { loadImage(image); }
- public Interpreter(byte[] image) throws IOException { loadImage(image); }
-
- // Debug functions
- // NOTE: This probably requires a jdk > 1.1, however, it is only used for debugging
- public String sourceLine(int pc) {
- final String addr2line = "mips-unknown-elf-addr2line";
- String line;
- if(image==null) return null;
- try {
- Process p = Runtime.getRuntime().exec(new String[]{addr2line,"-e",image.toString(),toHex(pc)});
- line = new BufferedReader(new InputStreamReader(p.getInputStream())).readLine();
- if(line == null) return null;
- while(line.startsWith("../")) line = line.substring(3);
- return line;
- } catch(IOException e) {
- return null;
- }
- }
+ public Interpreter() { super(true); /* allow empty pages */ }
+ public Interpreter(String filename) throws IOException { loadImage(filename); }
+ public Interpreter(byte[] bytes) throws IOException { loadImage(bytes); }
public class DebugShutdownHook implements Runnable {
public void run() {
int pc = nextPC;
if(getState() == RUNNING)
- System.err.print("\nCPU Executing " + toHex(pc) + ": " + sourceLine(pc) + "\n");
+ System.err.print("\nCPU Executing " + toHex(pc) + "\n");
}
}
String image = argv[0];
Interpreter emu = new Interpreter();
emu.loadImage(image);
- Runtime.getRuntime().addShutdownHook(new Thread(emu.new DebugShutdownHook()));
+ java.lang.Runtime.getRuntime().addShutdownHook(new Thread(emu.new DebugShutdownHook()));
// User data
int addr = emu.sbrk(PAGE_SIZE);
for(int i=0;i<10;i++) {
System.exit(status);
}
}
-
-