2003/11/16 08:28:10
[org.ibex.core.git] / src / org / xwt / mips / Interpreter.java
index a957297..9b0f11b 100644 (file)
@@ -1,21 +1,19 @@
-// 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)
@@ -25,9 +23,6 @@ public class Interpreter extends VM {
     
     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 */ }
@@ -41,19 +36,14 @@ public class Interpreter extends VM {
     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(;;) {
@@ -96,15 +86,14 @@ public class Interpreter extends VM {
                     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;
@@ -120,7 +109,7 @@ public class Interpreter extends VM {
                         }
                         break;
                     case 13: // BREAK
-                        throw new EmulationException("Break");
+                        throw new ExecutionException("Break");
                     case 16: // MFHI
                         r[rd] = hi;
                         break;
@@ -154,14 +143,18 @@ public class Interpreter extends VM {
                         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;
@@ -184,7 +177,7 @@ public class Interpreter extends VM {
                         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;
             }
@@ -215,7 +208,7 @@ public class Interpreter extends VM {
                         }
                         break;
                     default:
-                        throw new EmulationException("Illegal Instruction");
+                        throw new ExecutionException("Illegal Instruction");
                 }
                 break;
             }
@@ -278,29 +271,29 @@ public class Interpreter extends VM {
                 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
@@ -330,7 +323,7 @@ public class Interpreter extends VM {
                                 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));
@@ -344,12 +337,12 @@ public class Interpreter extends VM {
                                 }
                                 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;
                     }
@@ -378,7 +371,7 @@ public class Interpreter extends VM {
                                 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));
@@ -394,7 +387,7 @@ public class Interpreter extends VM {
                                 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));
@@ -402,7 +395,7 @@ public class Interpreter extends VM {
                             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;
                     }
@@ -411,21 +404,21 @@ public class Interpreter extends VM {
                             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);
                 }
@@ -442,7 +435,7 @@ public class Interpreter extends VM {
             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);
                 }
@@ -457,7 +450,7 @@ public class Interpreter extends VM {
             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);
                 }
@@ -472,7 +465,7 @@ public class Interpreter extends VM {
             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);
                 }
@@ -480,7 +473,7 @@ public class Interpreter extends VM {
             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);
                 }
@@ -495,7 +488,7 @@ public class Interpreter extends VM {
             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);
                 }
@@ -508,7 +501,7 @@ public class Interpreter extends VM {
             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);
                 }
@@ -523,7 +516,7 @@ public class Interpreter extends VM {
             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);
                 }
@@ -534,7 +527,7 @@ public class Interpreter extends VM {
                     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);
                 }
@@ -543,7 +536,7 @@ public class Interpreter extends VM {
             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);
                 }
@@ -552,7 +545,7 @@ public class Interpreter extends VM {
                     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);
                 }
@@ -568,7 +561,7 @@ public class Interpreter extends VM {
                     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);
                 }
@@ -577,7 +570,7 @@ public class Interpreter extends VM {
             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]);
                 }
@@ -601,12 +594,12 @@ public class Interpreter extends VM {
                 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;
     }
@@ -615,9 +608,7 @@ public class Interpreter extends VM {
     
     // 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)
@@ -653,41 +644,25 @@ public class Interpreter extends VM {
                 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");
         }
     }
 
@@ -695,7 +670,7 @@ public class Interpreter extends VM {
         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++) {
@@ -711,5 +686,3 @@ public class Interpreter extends VM {
         System.exit(status);
     }
 }
-
-