lessconstants support for classfilecompiler
[nestedvm.git] / src / org / ibex / nestedvm / ClassFileCompiler.java
index d1ea2bd..11ed4e4 100644 (file)
@@ -6,7 +6,7 @@ import org.ibex.nestedvm.util.*;
 import org.ibex.classgen.*;
 
 // FEATURE: Use IINC where possible
-// FEATURE: Use BCEL to do peephole optimization
+// FEATURE: Some kind of peephole optimization
 // FEATURE: Special mode to support single-precision only - regs are floats not ints
 
 /* FEATURE: Span large binaries across several classfiles
@@ -53,7 +53,15 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
     public void setWarnWriter(PrintStream warn) { this.warn = warn; }
         
     protected void _go() throws Exn, IOException {
-        if(lessConstants) throw new Exn("ClassFileCompiler doesn't support -o lessconstants");
+        try {
+            __go();
+        } catch(ClassGen.Exn e) {
+            e.printStackTrace();
+            throw new Exn("Class generation exception: " + e.toString());
+        }
+    }
+    
+    private void __go() throws Exn, IOException {
         if(!pruneCases) throw new Exn("-o prunecases MUST be enabled for ClassFileCompiler");
 
         // Class
@@ -156,9 +164,9 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
         int start = tramp.size();
         tramp.add(ALOAD_0);
         tramp.add(GETFIELD,new FieldRef(me,"state",Type.INT));
-        tramp.add(LDC,Runtime.RUNNING);
+        tramp.add(IFEQ,tramp.size()+2);
+        tramp.add(RETURN);
         
-        int stateCheck = tramp.add(IF_ICMPNE);
         tramp.add(ALOAD_0);
         tramp.add(ALOAD_0);
         tramp.add(GETFIELD,new FieldRef(me,"pc",Type.INT));
@@ -197,9 +205,6 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
         tramp.add(INVOKEVIRTUAL,new MethodRef(Type.STRINGBUFFER,"toString",Type.STRING,Type.NO_ARGS));
         tramp.add(INVOKESPECIAL,new MethodRef(new Type.Object("org.ibex.nestedvm.Runtime$ExecutionException"),"<init>",Type.VOID,new Type[]{Type.STRING}));
         tramp.add(ATHROW);
-        
-        tramp.setArg(stateCheck,tramp.size());
-        tramp.add(RETURN);
                 
         try {
             tramp.finish();
@@ -522,6 +527,21 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
     private void leaveMethod() {
         mg.add(GOTO,returnTarget);
     }
+    
+    private void link(int mypc) {
+        preSetReg(R+RA);
+        if(lessConstants){
+            int ref = (mypc+8 + 32768) & ~65535;
+            int diff = (mypc+8) - ref;
+            if(diff < -32768 || diff > 32767) throw new Error("should never happen " + diff);
+            mg.add(LDC,ref);
+            mg.add(LDC,diff);
+            mg.add(IADD);
+        } else {
+            mg.add(LDC,mypc+8);
+        }
+        setReg();
+    }
 
     private void branch(int pc, int target) {
         if((pc&methodMask) == (target&methodMask)) {
@@ -559,6 +579,7 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
             // add another copy and jump over
             
             int b = mg.add(GOTO);
+            insnTargets[(pc+4-startOfMethod)/4].setTarget(mg.size());
             emitInstruction(-1,nextInsn,01); // delay slot
             mg.setArg(b,mg.size());
             
@@ -651,13 +672,10 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
             case 9: // JALR
                 if(pc == -1) throw new Exn("pc modifying insn in delay slot");
                 emitInstruction(-1,nextInsn,-1);
+                link(pc);
                 preSetPC();
                 pushRegWZ(R+rs);
                 setPC();
-                
-                preSetReg(R+RA);
-                mg.add(LDC,pc+8);
-                setReg();
                 leaveMethod();
                 unreachable = true;
                 break;
@@ -666,6 +684,8 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
                 mg.add(LDC,pc);
                 setPC();
                 
+                // FEATURE: This is actually broken, but it happens to work for our code
+                // a func could theoretically jump back to here from a future point
                 restoreChangedRegs();
                 
                 preSetReg(R+V0);
@@ -682,9 +702,7 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
                 
                 mg.add(ALOAD_0);
                 mg.add(GETFIELD,new FieldRef(me,"state",Type.INT));
-                // FEATURE: Set Runtime.RUNNING to 0 and just use IFEQ here 
-                mg.add(LDC,Runtime.RUNNING);
-                b1 = mg.add(IF_ICMPEQ);
+                b1 = mg.add(IFEQ);
                 preSetPC();
                 mg.add(LDC,pc+4);
                 setPC();
@@ -948,9 +966,7 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
                 pushRegWZ(R+rs);
                 b1 = mg.add(IFGE);
                 emitInstruction(-1,nextInsn,-1);
-                preSetReg(R+RA);
-                mg.add(LDC,pc+8);
-                setReg();
+                link(pc);
                 branch(pc,pc+branchTarget*4+4);
                 mg.setArg(b1,mg.size());
                 break;
@@ -962,9 +978,7 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
                     b1 = mg.add(IFLT);
                 }
                 emitInstruction(-1,nextInsn,-1);
-                preSetReg(R+RA);
-                mg.add(LDC,pc+8);
-                setReg();
+                link(pc);
                 branch(pc,pc+branchTarget*4+4);
                 if(b1 != -1) mg.setArg(b1,mg.size());
                 if(b1 == -1) unreachable = true;
@@ -985,9 +999,7 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
             if(pc == -1) throw new Exn("pc modifying insn in delay slot");
             int target = (pc&0xf0000000)|(jumpTarget << 2);
             emitInstruction(-1,nextInsn,-1);
-            preSetReg(R+RA);
-            mg.add(LDC,pc+8);
-            setReg();
+            link(pc);
             branch(pc, target);
             unreachable = true;
             break;
@@ -1675,11 +1687,17 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
     private static final int FCSR = 66;
     private static final int REG_COUNT=67;
         
-    // FEATURE: Clean this up
     private int[] regLocalMapping = new int[REG_COUNT];  
     private int[] regLocalReadCount = new int[REG_COUNT];
     private int[] regLocalWriteCount = new int[REG_COUNT];
     private int nextAvailLocal; 
+    private int loadsStart;
+    private static final int MAX_LOCALS = 4;
+    private static final int LOAD_LENGTH = 3;
+    
+    private boolean doLocal(int reg) {
+        return reg == R+2 || reg == R+3 || reg == R+4 || reg == R+29;
+    }
     
     private int getLocalForReg(int reg) {
         if(regLocalMapping[reg] != 0) return regLocalMapping[reg];
@@ -1688,8 +1706,6 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
         return regLocalMapping[reg];
     }
     
-    
-    private int loadsStart;
     private void fixupRegsStart() {
         for(int i=0;i<REG_COUNT;i++)
             regLocalMapping[i] = regLocalReadCount[i] = regLocalWriteCount[i] = 0;
@@ -1715,12 +1731,6 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
         }
     }
         
-    private static final int MAX_LOCALS = 4;
-    private static final int LOAD_LENGTH = 3;
-    private boolean doLocal(int reg) {
-        return reg == R+2 || reg == R+3 || reg == R+4 || reg == R+29;
-    }
-        
     private void restoreChangedRegs() {
         for(int i=0;i<REG_COUNT;i++) {
             if(regLocalWriteCount[i] > 0) {
@@ -1756,7 +1766,7 @@ public class ClassFileCompiler extends Compiler implements CGConst  {
     }
     
     private int pushRegZ(int reg) {
-        if(reg == R+0) return mg.add(LDC,0);
+        if(reg == R+0) return mg.add(ICONST_0);
         else return pushReg(reg);
     }