verify problem in lookupSymbol
[nestedvm.git] / src / org / ibex / nestedvm / ClassFileCompiler.java
index 0c4dd67..f0b9153 100644 (file)
@@ -1,6 +1,8 @@
 package org.ibex.nestedvm;
 
 import java.io.*;
+import java.util.Hashtable;
+
 import org.ibex.nestedvm.util.*;
 
 import org.apache.bcel.generic.*;
@@ -45,7 +47,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
     
     // Handy wrappers around the BCEL functions
     private InstructionList insnList;
-    private void selectMethod(MethodGen m) { insnList = m.getInstructionList();    }
+    private void selectMethod(MethodGen m) { insnList = m.getInstructionList(); }
     private void selectList(InstructionList l) { insnList = l; }
     private InstructionHandle a(Instruction i) { return insnList.append(i); }
     private BranchHandle a(BranchInstruction i) { return insnList.append(i); }
@@ -148,7 +150,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
         a(InstructionConstants.IUSHR);
         
         int beg = text.addr >>> methodShift;
-        int end = ((text.addr + text.size) >>> methodShift);
+        int end = ((text.addr + text.size + maxBytesPerMethod - 1) >>> methodShift);
 
         // This data is redundant but BCEL wants it
         int[] matches = new int[end-beg];
@@ -263,8 +265,9 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
             a(fac.createCheckCast(new ObjectType("java.lang.Integer")));
             a(fac.createInvoke("java.lang.Integer","intValue",Type.INT,Type.NO_ARGS,INVOKEVIRTUAL));
             a(InstructionConstants.IRETURN);
-            bh.setTarget(a(InstructionConstants.ICONST_M1));
-            a(InstructionConstants.IRETURN);     
+            bh.setTarget(a(InstructionConstants.POP));
+            a(InstructionConstants.ICONST_M1);
+            a(InstructionConstants.IRETURN);
             lookupSymbol.setMaxLocals();
             lookupSymbol.setMaxStack();
             cl.addMethod(lookupSymbol.getMethod());
@@ -360,12 +363,20 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
         cl.addMethod(getCPUState.getMethod());
 
 
-        // FEATURE: Catch RuntimeException and turn it into a fault exception
         MethodGen execute = newMethod(ACC_PROTECTED,Type.VOID,Type.NO_ARGS,"_execute");
         selectMethod(execute);
-        a(InstructionConstants.ALOAD_0);
-        a(fac.createInvoke(fullClassName,"trampoline",Type.VOID,Type.NO_ARGS,INVOKESPECIAL));
+        InstructionHandle tryStart = a(InstructionConstants.ALOAD_0);
+        InstructionHandle tryEnd = a(fac.createInvoke(fullClassName,"trampoline",Type.VOID,Type.NO_ARGS,INVOKESPECIAL));
         a(InstructionConstants.RETURN);
+        
+        InstructionHandle catchInsn = a(InstructionConstants.ASTORE_1);
+        a(fac.createNew("org.ibex.nestedvm.Runtime$FaultException"));
+        a(InstructionConstants.DUP);
+        a(InstructionConstants.ALOAD_1);
+        a(fac.createInvoke("org.ibex.nestedvm.Runtime$FaultException","<init>",Type.VOID,new Type[]{new ObjectType("java.lang.RuntimeException")},INVOKESPECIAL));
+        a(InstructionConstants.ATHROW);
+        
+        execute.addExceptionHandler(tryStart,tryEnd,catchInsn,new ObjectType("java.lang.RuntimeException"));
         execute.setMaxLocals();
         execute.setMaxStack();
         cl.addMethod(execute.getMethod());
@@ -380,21 +391,23 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
         a(InstructionConstants.ALOAD_0);
         if(unixRuntime)
             a(fac.createInvoke("org.ibex.nestedvm.UnixRuntime","runAndExec",Type.INT,
-                    new Type[]{Type.getType("Lorg/ibex/nestedvm/UnixRuntime;"),Type.STRING,new ArrayType(Type.STRING,1)},
-                    INVOKESTATIC));
+                new Type[]{Type.getType("Lorg/ibex/nestedvm/UnixRuntime;"),Type.STRING,new ArrayType(Type.STRING,1)},
+                INVOKESTATIC));
         else
-                   a(fac.createInvoke(fullClassName,"run",Type.INT,new Type[]{Type.STRING,new ArrayType(Type.STRING,1)},INVOKEVIRTUAL));
+            a(fac.createInvoke(fullClassName,"run",Type.INT,new Type[]{Type.STRING,new ArrayType(Type.STRING,1)},INVOKEVIRTUAL));
         a(fac.createInvoke("java.lang.System","exit",Type.VOID,new Type[]{Type.INT},INVOKESTATIC));
         a(InstructionConstants.RETURN);
         main.setMaxLocals();
         main.setMaxStack();
         cl.addMethod(main.getMethod());
         
+        if(printStats)
+            System.out.println("Constant Pool Size: " + cp.getSize());
         cl.getJavaClass().dump(os);
     }
     
     private void addConstReturnMethod(String name, int val) {
-           MethodGen method = newMethod(ACC_PROTECTED,Type.INT, Type.NO_ARGS,name);
+        MethodGen method = newMethod(ACC_PROTECTED,Type.INT, Type.NO_ARGS,name);
         selectMethod(method);
         pushConst(val);
         a(InstructionConstants.IRETURN);
@@ -896,7 +909,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
             case 32: // ADD
                 throw new Exn("ADD (add with oveflow trap) not suported");
             case 33: // ADDU
-                   preSetReg(R+rd);
+                preSetReg(R+rd);
                 if(rt != 0 && rs != 0) {
                     pushReg(R+rs);
                     pushReg(R+rt);
@@ -1007,7 +1020,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
                 setReg();
                 break;
             default:
-                throw new RuntimeException("Illegal instruction 0/" + subcode);
+                throw new Exn("Illegal instruction 0/" + subcode);
             }
             break;
         }
@@ -1048,7 +1061,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
                 if(b1 == null) unreachable = true;
                 break;
             default:
-                throw new RuntimeException("Illegal Instruction 1/" + rt);
+                throw new Exn("Illegal Instruction 1/" + rt);
             }
             break;
         }
@@ -1063,22 +1076,10 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
             if(pc == -1) throw new Exn("pc modifying insn in delay slot");
             int target = (pc&0xf0000000)|(jumpTarget << 2);
             emitInstruction(-1,nextInsn,-1);
-            if(optimizedMemcpy && (target == memcpy || target == memset)) {
-                a(InstructionConstants.ALOAD_0);
-                pushRegZ(R+4);
-                pushRegZ(R+5);
-                pushRegZ(R+6);
-                a(fac.createInvoke(fullClassName,target==memcpy ? "memcpy" : "memset", Type.VOID, new Type[]{Type.INT,Type.INT,Type.INT},INVOKEVIRTUAL));
-                preSetReg(R+2);
-                pushReg(R+4);
-                setReg();
-                branch(pc,pc+8);
-            } else {
-                preSetReg(R+RA);
-                pushConst(pc+8);
-                setReg();
-                branch(pc, target);
-            }
+            preSetReg(R+RA);
+            pushConst(pc+8);
+            setReg();
+            branch(pc, target);
             unreachable = true;
             break;
         }
@@ -1138,7 +1139,8 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
             a(InstructionConstants.I2L);
             pushConst(0xffffffffL);
             a(InstructionConstants.LAND);
-            pushConst((long)unsignedImmediate);
+            // Yes, this is correct, you have to sign extend the immediate then do an UNSIGNED comparison
+            pushConst(signedImmediate&0xffffffffL);
             a(InstructionConstants.LCMP);
             
             b1 = a(InstructionFactory.createBranchInstruction(IFLT,null));
@@ -1233,7 +1235,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
                     pushDouble(F+fs,d);
                     pushDouble(F+ft,d);
                     a(d ? InstructionConstants.DSUB : InstructionConstants.FSUB);
-                    setDouble(d);                    
+                    setDouble(d);
                     break;
                 case 2: // MUL.X
                     preSetDouble(F+fd,d);
@@ -1276,26 +1278,28 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
                     pushReg(F+fs);
                     setReg();
                     
-                    preSetReg(F+fd+1);
-                    pushReg(F+fs+1);
-                    setReg();
+                    if(d) {
+                        preSetReg(F+fd+1);
+                        pushReg(F+fs+1);
+                        setReg();
+                    }
                     
                     break;
                 case 7: // NEG.X
                     preSetDouble(F+fd,d);
                     pushDouble(F+fs,d);
                     a(d ? InstructionConstants.DNEG : InstructionConstants.FNEG);
-                    setDouble(d);                    
+                    setDouble(d);
                     break;
                 case 32: // CVT.S.X
                     preSetFloat(F+fd);
-                    pushDouble(F+fd,d);
+                    pushDouble(F+fs,d);
                     if(d) a(InstructionConstants.D2F);
                     setFloat();
                     break;
                 case 33: // CVT.D.X
                     preSetDouble(F+fd);
-                    pushDouble(F+fd,d);
+                    pushDouble(F+fs,d);
                     if(!d) a(InstructionConstants.F2D);
                     setDouble();
                     break;
@@ -1355,7 +1359,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
                         case 62: b1 = a(InstructionFactory.createBranchInstruction(IFLE,null)); break;
                         default: b1 = null;
                     }
-                    
+                    // FIXME: We probably don't need to pushConst(0x00000)
                     pushConst(0x000000);
                     b2 = a(InstructionFactory.createBranchInstruction(GOTO,null));
                     b1.setTarget(pushConst(0x800000));
@@ -1720,7 +1724,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
             memWrite();
             break;
         }
-        // FEATURE: This need to be atomic if we ever support threads (see SWC0/SC)
+        // This need to be atomic if we ever support threads (see SWC0/SC)
         case 48: // LWC0/LL
             preSetReg(R+rt);
             memRead(R+rs,signedImmediate);
@@ -1733,7 +1737,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
             setReg();
             break;
         
-        /* FEATURE: This needs to fail (set rt to 0) if the memory location was modified
+        /* This needs to fail (set rt to 0) if the memory location was modified
          * between the LL and SC if we every support threads.
          */
         case 56: // SWC0/SC
@@ -1809,18 +1813,34 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
         }
     }
     
-    private String regField(int reg) {
-        String field;
+    private static final String[] regField = {
+            "r0","r1","r2","r3","r4","r5","r6","r7",
+            "r8","r9","r10","r11","r12","r13","r14","r15",
+            "r16","r17","r18","r19","r20","r21","r22","r23",
+            "r24","r25","r26","r27","r28","r29","r30","r31",
+            
+            "f0","f1","f2","f3","f4","f5","f6","f7",
+            "f8","f9","f10","f11","f12","f13","f14","f15",
+            "f16","f17","f18","f19","f20","f21","f22","f23",
+            "f24","f25","f26","f27","f28","f29","f30","f31",
+            
+            "hi","lo","fcsr"
+    };
+    
+    private static String regField(int reg) {
+        return regField[reg];
+                                   
+        /*String field;
         switch(reg) {
             case HI: field = "hi"; break;
             case LO: field = "lo"; break;
             case FCSR: field = "fcsr"; break;
             default:
-                if(reg > R && reg < R+32) field="r"+(reg-R);
-                else if(reg >= F && reg < F+32) field="f"+(reg-F);
+                if(reg > R && reg < R+32) regFieldR[reg-R];
+                else if(reg >= F && reg < F+32) return regFieldF[
                 else throw new IllegalArgumentException(""+reg);
         }
-        return field;
+        return field;*/
     }
     
     private boolean doLocal(int reg) {
@@ -1942,9 +1962,12 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
         return h;
     }
         
+    private Hashtable intCache = new Hashtable();
+    
     private InstructionHandle pushConst(int n) {
-        if(n >= 0 && n <= 5) {
+        if(n >= -1 && n <= 5) {
             switch(n) {
+                case -1: return a(InstructionConstants.ICONST_M1);
                 case 0: return a(InstructionConstants.ICONST_0);
                 case 1: return a(InstructionConstants.ICONST_1);
                 case 2: return a(InstructionConstants.ICONST_2);
@@ -1953,8 +1976,6 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const
                 case 5: return a(InstructionConstants.ICONST_5);
                 default: return null;
             }
-        } else if(n == -1) {
-            return a(InstructionConstants.ICONST_M1);
         } else if(n >= -128 && n <= 127) {
             return a(new BIPUSH((byte) n));
         } else if(n >= -32768 && n <= 32767) {