X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fnestedvm%2FClassFileCompiler.java;h=70ff235585c1b2fb2a4f491ed678491764465209;hp=1f6ecd49052467afbf688dbfeea2bf30392a76f9;hb=b11e7c6c29f2b5f7b0828bf93eb741c4a30ec411;hpb=3dd4a2b74bbc1248f66482f06b14d7fffcf7ac47;ds=sidebyside diff --git a/src/org/ibex/nestedvm/ClassFileCompiler.java b/src/org/ibex/nestedvm/ClassFileCompiler.java index 1f6ecd4..70ff235 100644 --- a/src/org/ibex/nestedvm/ClassFileCompiler.java +++ b/src/org/ibex/nestedvm/ClassFileCompiler.java @@ -1,14 +1,16 @@ +// Copyright 2000-2005 the Contributors, as shown in the revision logs. +// Licensed under the Apache License 2.0 ("the License"). +// You may not use this file except in compliance with the License. + package org.ibex.nestedvm; import java.io.*; -import java.util.Hashtable; import org.ibex.nestedvm.util.*; +import org.ibex.classgen.*; -import org.apache.bcel.generic.*; - -// FEATURE: Use BCEL to do peephole optimization -// FEATURE: Special mode to support single-precision only - regs are floats not ints +// FEATURE: Eliminate unnecessary use of SWAP +// FEATURE: Put regs in low (<=3) local vars, small classfile size /* FEATURE: Span large binaries across several classfiles * We should be able to do this with no performance penalty @@ -34,82 +36,113 @@ import org.apache.bcel.generic.*; */ -public class ClassFileCompiler extends Compiler implements org.apache.bcel.Constants { +public class ClassFileCompiler extends Compiler implements CGConst { + private static final boolean OPTIMIZE_CP = true; + /** The stream to write the compiled output to */ private OutputStream os; + private File outDir; private PrintStream warn = System.err; + + private final Type.Class me; - private ClassGen cl; - private ConstantPoolGen cp; - private InstructionList clinitExtras = new InstructionList(); - private InstructionList initExtras = new InstructionList(); - private InstructionFactory fac; - - // Handy wrappers around the BCEL functions - private InstructionList insnList; - 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); } - private InstructionHandle a(InstructionList l) { return insnList.append(l); } - private InstructionHandle a(CompoundInstruction c) { return insnList.append(c); } - - // This works around a bug in InstructionList - // FEATURE: fix this in bcel, send them a patch, etc - private static class FixedInstructionList extends InstructionList { - public void move(InstructionHandle start, InstructionHandle end, InstructionHandle target) { - InstructionHandle extra = target != null && target == getEnd() ? append(InstructionConstants.NOP) : null; - super.move(start,end,target); - if(extra != null) try { delete(extra); } catch (TargetLostException e) { /* won't happen */ } - } - } - - private MethodGen newMethod(int flags, Type ret, Type[] args, String name) { - return new MethodGen(flags,ret,args,null,name,fullClassName,new FixedInstructionList(),cp); - } + private ClassFile cg; + private MethodGen clinit, init; public ClassFileCompiler(String path, String className, OutputStream os) throws IOException { this(new Seekable.File(path),className,os); } public ClassFileCompiler(Seekable binary, String className, OutputStream os) throws IOException { - super(binary,className); + this(binary,className); + if(os == null) throw new NullPointerException(); this.os = os; } + public ClassFileCompiler(Seekable binary, String className, File outDir) throws IOException { + this(binary,className); + if(outDir == null) throw new NullPointerException(); + this.outDir = outDir; + } + private ClassFileCompiler(Seekable binary, String className) throws IOException { + super(binary,className); + me = Type.Class.instance(fullClassName); + } 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(ClassFile.Exn e) { + e.printStackTrace(warn); + 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 - cl = new ClassGen(fullClassName,runtimeClass,source,ACC_SUPER|ACC_PUBLIC|ACC_FINAL,null); - cp = cl.getConstantPool(); - fac = new InstructionFactory(cl,cp); + Type.Class superClass = Type.Class.instance(runtimeClass); + cg = new ClassFile(me,superClass,PUBLIC|FINAL|SUPER); + if(source != null) cg.setSourceFile(source); // Fields - cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"pc",cp).getField()); - for(int i=1;i<32;i++) - cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"r"+i,cp).getField()); - for(int i=0;i<32;i++) - cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"f"+i,cp).getField()); + cg.addField("pc",Type.INT,PRIVATE); + cg.addField("hi",Type.INT,PRIVATE); + cg.addField("lo",Type.INT,PRIVATE); + cg.addField("fcsr",Type.INT,PRIVATE); + for(int i=1;i<32;i++) cg.addField("r" + i,Type.INT,PRIVATE); + for(int i=0;i<32;i++) cg.addField("f" + i,singleFloat ? Type.FLOAT : Type.INT,PRIVATE); + + // + clinit = cg.addMethod("",Type.VOID,Type.NO_ARGS,PRIVATE|STATIC); + + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.UnixRuntime. - cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"hi",cp).getField()); - cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"lo",cp).getField()); - cl.addField(new FieldGen(ACC_PRIVATE,Type.INT,"fcsr",cp).getField()); + // + init = cg.addMethod("",Type.VOID,Type.NO_ARGS,PUBLIC); + init.add(ALOAD_0); + init.add(LDC,pageSize); + init.add(LDC,totalPages); + init.add(INVOKESPECIAL,me.method("",Type.VOID,new Type[]{Type.INT,Type.INT})); + init.add(RETURN); + + // (Z) + init = cg.addMethod("",Type.VOID,new Type[]{Type.BOOLEAN},PUBLIC); + init.add(ALOAD_0); + init.add(LDC,pageSize); + init.add(LDC,totalPages); + init.add(ILOAD_1); + init.add(INVOKESPECIAL,me.method("",Type.VOID,new Type[]{Type.INT,Type.INT,Type.BOOLEAN})); + init.add(RETURN); + + // (II) + init = cg.addMethod("",Type.VOID,new Type[]{Type.INT,Type.INT},PUBLIC); + init.add(ALOAD_0); + init.add(ILOAD_1); + init.add(ILOAD_2); + init.add(ICONST_0); + init.add(INVOKESPECIAL,me.method("",Type.VOID,new Type[]{Type.INT,Type.INT,Type.BOOLEAN})); + init.add(RETURN); + + // (IIZ) + init = cg.addMethod("",Type.VOID,new Type[]{Type.INT,Type.INT,Type.BOOLEAN},PUBLIC); + init.add(ALOAD_0); + init.add(ILOAD_1); + init.add(ILOAD_2); + init.add(ILOAD_3); + init.add(INVOKESPECIAL,superClass.method("",Type.VOID,new Type[]{Type.INT,Type.INT,Type.BOOLEAN})); if(onePage) { - cl.addField(new FieldGen(ACC_PRIVATE|ACC_FINAL,new ArrayType(Type.INT,1),"page",cp).getField()); - - selectList(initExtras); - a(InstructionConstants.ALOAD_0); - a(InstructionConstants.DUP); - a(fac.createFieldAccess(fullClassName,"readPages",new ArrayType(Type.INT, 2), GETFIELD)); - pushConst(0); - a(InstructionConstants.AALOAD); - a(fac.createFieldAccess(fullClassName,"page",new ArrayType(Type.INT,1), PUTFIELD)); + cg.addField("page",Type.INT.makeArray(),PRIVATE|FINAL); + init.add(ALOAD_0); + init.add(DUP); + init.add(GETFIELD,me.field("readPages",Type.INT.makeArray(2))); + init.add(LDC,0); + init.add(AALOAD); + init.add(PUTFIELD,me.field("page",Type.INT.makeArray())); } if(supportCall) - cl.addField(new FieldGen(ACC_PRIVATE|ACC_STATIC|ACC_FINAL,Type.getType("L"+hashClass.replace('.','/')+";"),"symbols",cp).getField()); + cg.addField("symbols",Type.Class.instance(hashClass),PRIVATE|STATIC|FINAL); int highestAddr = 0; @@ -131,69 +164,86 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const throw new Exn("Unknown segment: " + name); } + // Finish init + init.add(RETURN); + + // Finish clinit + if(supportCall) { + Type.Class hash = Type.Class.instance(hashClass); + clinit.add(NEW,hash); + clinit.add(DUP); + clinit.add(DUP); + clinit.add(INVOKESPECIAL,hash.method("",Type.VOID,Type.NO_ARGS)); + clinit.add(PUTSTATIC,me.field("symbols",hash)); + ELF.Symbol[] symbols = elf.getSymtab().symbols; + for(int i=0;i",Type.VOID,new Type[]{Type.INT})); + clinit.add(INVOKEVIRTUAL,hash.method("put",Type.OBJECT,new Type[]{Type.OBJECT,Type.OBJECT})); + clinit.add(POP); + } + } + clinit.add(POP); + } + + clinit.add(RETURN); + ELF.SHeader text = elf.sectionWithName(".text"); // Trampoline - MethodGen tramp = newMethod(ACC_PRIVATE,Type.VOID, Type.NO_ARGS, "trampoline"); - tramp.addException("org.ibex.nestedvm.Runtime$ExecutionException"); - selectMethod(tramp); + MethodGen tramp = cg.addMethod("trampoline",Type.VOID,Type.NO_ARGS,PRIVATE); - InstructionHandle start = a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"state",Type.INT, GETFIELD)); - pushConst(Runtime.RUNNING); - BranchInstruction stateCheck = InstructionFactory.createBranchInstruction(IF_ICMPNE,null); - a(stateCheck); - a(InstructionConstants.ALOAD_0); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD)); - pushConst(methodShift); - a(InstructionConstants.IUSHR); + int start = tramp.size(); + tramp.add(ALOAD_0); + tramp.add(GETFIELD,me.field("state",Type.INT)); + tramp.add(IFEQ,tramp.size()+2); + tramp.add(RETURN); + + tramp.add(ALOAD_0); + tramp.add(ALOAD_0); + tramp.add(GETFIELD,me.field("pc",Type.INT)); + tramp.add(LDC,methodShift); + tramp.add(IUSHR); int beg = text.addr >>> methodShift; int end = ((text.addr + text.size + maxBytesPerMethod - 1) >>> methodShift); - // This data is redundant but BCEL wants it - int[] matches = new int[end-beg]; - for(int i=beg;i",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"r2",Type.INT, GETFIELD)); - a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.INT},INVOKEVIRTUAL)); - a(new PUSH(cp," pc:")); - a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.STRING},INVOKEVIRTUAL)); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD)); - a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.INT},INVOKEVIRTUAL)); - a(new PUSH(cp,')')); - a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.CHAR},INVOKEVIRTUAL)); - a(fac.createInvoke("java.lang.StringBuffer","toString",Type.STRING,Type.NO_ARGS,INVOKEVIRTUAL)); - a(fac.createInvoke("org.ibex.nestedvm.Runtime$ExecutionException","",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); - a(InstructionConstants.ATHROW); - - stateCheck.setTarget(a(InstructionConstants.RETURN)); - - tramp.setMaxStack(); - tramp.setMaxLocals(); - try { - cl.addMethod(tramp.getMethod()); - } catch(ClassGenException e) { - e.printStackTrace(warn); - throw new Exn("Generation of the trampoline method failed. Try increasing maxInsnPerMethod"); - } + tramp.add(POP); + tramp.add(NEW,Type.Class.instance("org.ibex.nestedvm.Runtime$ExecutionException")); + tramp.add(DUP); + tramp.add(NEW, Type.STRINGBUFFER); + tramp.add(DUP); + tramp.add(LDC,"Jumped to invalid address in trampoline (r2: "); + tramp.add(INVOKESPECIAL,Type.STRINGBUFFER.method("",Type.VOID,new Type[]{Type.STRING})); + tramp.add(ALOAD_0); + tramp.add(GETFIELD, me.field("r2",Type.INT)); + tramp.add(INVOKEVIRTUAL,Type.STRINGBUFFER.method("append",Type.STRINGBUFFER,new Type[]{Type.INT})); + tramp.add(LDC," pc: "); + tramp.add(INVOKEVIRTUAL,Type.STRINGBUFFER.method("append",Type.STRINGBUFFER,new Type[]{Type.STRING})); + tramp.add(ALOAD_0); + tramp.add(GETFIELD, me.field("pc",Type.INT)); + tramp.add(INVOKEVIRTUAL,Type.STRINGBUFFER.method("append",Type.STRINGBUFFER,new Type[]{Type.INT})); + tramp.add(LDC,")"); + tramp.add(INVOKEVIRTUAL,Type.STRINGBUFFER.method("append",Type.STRINGBUFFER,new Type[]{Type.STRING})); + tramp.add(INVOKEVIRTUAL,Type.STRINGBUFFER.method("toString",Type.STRING,Type.NO_ARGS)); + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime$ExecutionException. + tramp.add(INVOKESPECIAL,Type.Class.instance("org.ibex.nestedvm.Runtime$ExecutionException").method("",Type.VOID,new Type[]{Type.STRING})); + tramp.add(ATHROW); addConstReturnMethod("gp",gp.addr); addConstReturnMethod("entryPoint",elf.header.entry); @@ -204,216 +254,137 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const addConstReturnMethod("userInfoSize",userInfo.size); } - // FEATURE: Allow specification of memory size at runtime (numpages) - // Constructor - MethodGen init = newMethod(ACC_PUBLIC,Type.VOID, Type.NO_ARGS, ""); - selectMethod(init); - a(InstructionConstants.ALOAD_0); - pushConst(pageSize); - pushConst(totalPages); - a(fac.createInvoke(runtimeClass,"",Type.VOID,new Type[]{Type.INT,Type.INT},INVOKESPECIAL)); - - a(initExtras); - - a(InstructionConstants.RETURN); - - init.setMaxLocals(); - init.setMaxStack(); - cl.addMethod(init.getMethod()); - - - MethodGen clinit = newMethod(ACC_PRIVATE|ACC_STATIC,Type.VOID, Type.NO_ARGS, ""); - selectMethod(clinit); - a(clinitExtras); - if(supportCall) { - a(fac.createNew(hashClass)); - a(InstructionConstants.DUP); - a(InstructionConstants.DUP); - a(fac.createInvoke(hashClass,"",Type.VOID,Type.NO_ARGS,INVOKESPECIAL)); - a(fac.createFieldAccess(fullClassName,"symbols",Type.getType("L"+hashClass.replace('.','/')+";"), PUTSTATIC)); - ELF.Symbol[] symbols = elf.getSymtab().symbols; - for(int i=0;i",Type.VOID,new Type[]{Type.INT},INVOKESPECIAL)); - a(fac.createInvoke(hashClass,"put",Type.OBJECT,new Type[]{Type.OBJECT,Type.OBJECT},INVOKEVIRTUAL)); - a(InstructionConstants.POP); - } - } - a(InstructionConstants.POP); + Type.Class hashClassType = Type.Class.instance(hashClass); + MethodGen ls = cg.addMethod("lookupSymbol",Type.INT,new Type[]{Type.STRING},PROTECTED); + ls.add(GETSTATIC,me.field("symbols",hashClassType)); + ls.add(ALOAD_1); + ls.add(INVOKEVIRTUAL,hashClassType.method("get",Type.OBJECT,new Type[]{Type.OBJECT})); + ls.add(DUP); + int b = ls.add(IFNULL); + ls.add(CHECKCAST,Type.INTEGER_OBJECT); + ls.add(INVOKEVIRTUAL,Type.INTEGER_OBJECT.method("intValue",Type.INT,Type.NO_ARGS)); + ls.add(IRETURN); + ls.setArg(b,ls.size()); + ls.add(POP); + ls.add(ICONST_M1); + ls.add(IRETURN); } - a(InstructionConstants.RETURN); - clinit.setMaxLocals(); - clinit.setMaxStack(); - cl.addMethod(clinit.getMethod()); + // Kind of a hack, referencing dup() gets us all the fields for free + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime$CPUState.dup + Type.Class cpuStateType = Type.Class.instance("org.ibex.nestedvm.Runtime$CPUState"); + MethodGen setCPUState = cg.addMethod("setCPUState",Type.VOID,new Type[]{cpuStateType},PROTECTED); + MethodGen getCPUState = cg.addMethod("getCPUState",Type.VOID,new Type[]{cpuStateType},PROTECTED); - if(supportCall) { - MethodGen lookupSymbol = newMethod(ACC_PROTECTED,Type.INT,new Type[]{Type.STRING},"lookupSymbol"); - selectMethod(lookupSymbol); - a(fac.createFieldAccess(fullClassName,"symbols",Type.getType("L"+hashClass.replace('.','/')+";"), GETSTATIC)); - a(InstructionConstants.ALOAD_1); - a(fac.createInvoke(hashClass,"get",Type.OBJECT,new Type[]{Type.OBJECT},INVOKEVIRTUAL)); - a(InstructionConstants.DUP); - BranchHandle bh = a(InstructionFactory.createBranchInstruction(IFNULL,null)); - 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.POP)); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IRETURN); - lookupSymbol.setMaxLocals(); - lookupSymbol.setMaxStack(); - cl.addMethod(lookupSymbol.getMethod()); - } + setCPUState.add(ALOAD_1); + getCPUState.add(ALOAD_1); + setCPUState.add(GETFIELD,cpuStateType.field("r",Type.INT.makeArray())); + getCPUState.add(GETFIELD,cpuStateType.field("r",Type.INT.makeArray())); + setCPUState.add(ASTORE_2); + getCPUState.add(ASTORE_2); - MethodGen setCPUState = newMethod(ACC_PROTECTED,Type.VOID,new Type[]{Type.getType("Lorg/ibex/nestedvm/Runtime$CPUState;")},"setCPUState"); - selectMethod(setCPUState); - a(InstructionConstants.ALOAD_1); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","r",new ArrayType(Type.INT,1),GETFIELD)); - a(InstructionConstants.ASTORE_2); for(int i=1;i<32;i++) { - a(InstructionConstants.ALOAD_0); - a(InstructionConstants.ALOAD_2); - pushConst(i); - a(InstructionConstants.IALOAD); - a(fac.createFieldAccess(fullClassName,"r"+i,Type.INT, PUTFIELD)); - } - a(InstructionConstants.ALOAD_1); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","f",new ArrayType(Type.INT,1),GETFIELD)); - a(InstructionConstants.ASTORE_2); - for(int i=0;i<32;i++) { - a(InstructionConstants.ALOAD_0); - a(InstructionConstants.ALOAD_2); - pushConst(i); - a(InstructionConstants.IALOAD); - a(fac.createFieldAccess(fullClassName,"f"+i,Type.INT, PUTFIELD)); + setCPUState.add(ALOAD_0); + setCPUState.add(ALOAD_2); + setCPUState.add(LDC,i); + setCPUState.add(IALOAD); + setCPUState.add(PUTFIELD,me.field("r"+i,Type.INT)); + + getCPUState.add(ALOAD_2); + getCPUState.add(LDC,i); + getCPUState.add(ALOAD_0); + getCPUState.add(GETFIELD,me.field("r"+i,Type.INT)); + getCPUState.add(IASTORE); } - a(InstructionConstants.ALOAD_0); - a(InstructionConstants.ALOAD_1); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","hi",Type.INT,GETFIELD)); - a(fac.createFieldAccess(fullClassName,"hi",Type.INT, PUTFIELD)); - a(InstructionConstants.ALOAD_0); - a(InstructionConstants.ALOAD_1); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","lo",Type.INT,GETFIELD)); - a(fac.createFieldAccess(fullClassName,"lo",Type.INT, PUTFIELD)); - a(InstructionConstants.ALOAD_0); - a(InstructionConstants.ALOAD_1); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","fcsr",Type.INT,GETFIELD)); - a(fac.createFieldAccess(fullClassName,"fcsr",Type.INT, PUTFIELD)); - a(InstructionConstants.ALOAD_0); - a(InstructionConstants.ALOAD_1); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","pc",Type.INT,GETFIELD)); - a(fac.createFieldAccess(fullClassName,"pc",Type.INT, PUTFIELD)); - a(InstructionConstants.RETURN); - setCPUState.setMaxLocals(); - setCPUState.setMaxStack(); - cl.addMethod(setCPUState.getMethod()); - - MethodGen getCPUState = newMethod(ACC_PROTECTED,Type.VOID,new Type[]{Type.getType("Lorg/ibex/nestedvm/Runtime$CPUState;")},"getCPUState"); - selectMethod(getCPUState); - a(InstructionConstants.ALOAD_1); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","r",new ArrayType(Type.INT,1),GETFIELD)); - a(InstructionConstants.ASTORE_2); - for(int i=1;i<32;i++) { - a(InstructionConstants.ALOAD_2); - pushConst(i); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"r"+i,Type.INT, GETFIELD)); - a(InstructionConstants.IASTORE); - } + setCPUState.add(ALOAD_1); + getCPUState.add(ALOAD_1); + setCPUState.add(GETFIELD,cpuStateType.field("f",Type.INT.makeArray())); + getCPUState.add(GETFIELD,cpuStateType.field("f",Type.INT.makeArray())); + setCPUState.add(ASTORE_2); + getCPUState.add(ASTORE_2); - a(InstructionConstants.ALOAD_1); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","f",new ArrayType(Type.INT,1),GETFIELD)); - a(InstructionConstants.ASTORE_2); for(int i=0;i<32;i++) { - a(InstructionConstants.ALOAD_2); - pushConst(i); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"f"+i,Type.INT, GETFIELD)); - a(InstructionConstants.IASTORE); + setCPUState.add(ALOAD_0); + setCPUState.add(ALOAD_2); + setCPUState.add(LDC,i); + setCPUState.add(IALOAD); + if(singleFloat) setCPUState.add(INVOKESTATIC,Type.FLOAT_OBJECT.method("intBitsToFloat",Type.FLOAT,new Type[]{Type.INT})); + setCPUState.add(PUTFIELD,me.field("f"+i,singleFloat ? Type.FLOAT : Type.INT)); + + getCPUState.add(ALOAD_2); + getCPUState.add(LDC,i); + getCPUState.add(ALOAD_0); + getCPUState.add(GETFIELD,me.field("f"+i,singleFloat ? Type.FLOAT: Type.INT)); + if(singleFloat) getCPUState.add(INVOKESTATIC,Type.FLOAT_OBJECT.method("floatToIntBits",Type.INT,new Type[]{Type.FLOAT})); + getCPUState.add(IASTORE); } - a(InstructionConstants.ALOAD_1); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"hi",Type.INT, GETFIELD)); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","hi",Type.INT,PUTFIELD)); - a(InstructionConstants.ALOAD_1); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"lo",Type.INT, GETFIELD)); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","lo",Type.INT,PUTFIELD)); - a(InstructionConstants.ALOAD_1); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"fcsr",Type.INT, GETFIELD)); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","fcsr",Type.INT,PUTFIELD)); - a(InstructionConstants.ALOAD_1); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD)); - a(fac.createFieldAccess("org.ibex.nestedvm.Runtime$CPUState","pc",Type.INT,PUTFIELD)); - a(InstructionConstants.RETURN); - getCPUState.setMaxLocals(); - getCPUState.setMaxStack(); - cl.addMethod(getCPUState.getMethod()); + String[] each = new String[] { "hi","lo","fcsr","pc" }; + for(int i=0;i",Type.VOID,new Type[]{new ObjectType("java.lang.RuntimeException")},INVOKESPECIAL)); - a(InstructionConstants.ATHROW); + getCPUState.add(ALOAD_1); + getCPUState.add(ALOAD_0); + getCPUState.add(GETFIELD,me.field(each[i],Type.INT)); + getCPUState.add(PUTFIELD,cpuStateType.field(each[i],Type.INT)); + } + setCPUState.add(RETURN); + getCPUState.add(RETURN); - execute.addExceptionHandler(tryStart,tryEnd,catchInsn,new ObjectType("java.lang.RuntimeException")); - execute.setMaxLocals(); - execute.setMaxStack(); - cl.addMethod(execute.getMethod()); + + MethodGen execute = cg.addMethod("_execute",Type.VOID,Type.NO_ARGS,PROTECTED); + int tryStart = execute.size(); + execute.add(ALOAD_0); + execute.add(INVOKESPECIAL,me.method("trampoline",Type.VOID,Type.NO_ARGS)); + int tryEnd = execute.size(); + execute.add(RETURN); + int catchInsn = execute.size(); + execute.add(ASTORE_1); + execute.add(NEW, Type.Class.instance("org.ibex.nestedvm.Runtime$FaultException")); + execute.add(DUP); + execute.add(ALOAD_1); + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime$FaultException. + execute.add(INVOKESPECIAL,Type.Class.instance("org.ibex.nestedvm.Runtime$FaultException").method("",Type.VOID,new Type[]{Type.Class.instance("java.lang.RuntimeException")})); + execute.add(ATHROW); - MethodGen main = newMethod(ACC_STATIC|ACC_PUBLIC,Type.VOID,new Type[]{new ArrayType(Type.STRING,1)},"main"); - selectMethod(main); - a(fac.createNew(fullClassName)); - a(InstructionConstants.DUP); - a(fac.createInvoke(fullClassName,"",Type.VOID,Type.NO_ARGS,INVOKESPECIAL)); - a(new PUSH(cp,fullClassName)); - 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)); - else - 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()); + execute.addExceptionHandler(tryStart,tryEnd,catchInsn,Type.Class.instance("java.lang.RuntimeException")); + execute.addThrow(Type.Class.instance("org.ibex.nestedvm.Runtime$ExecutionException")); + + MethodGen main = cg.addMethod("main",Type.VOID,new Type[]{Type.STRING.makeArray()},STATIC|PUBLIC); + main.add(NEW,me); + main.add(DUP); + main.add(INVOKESPECIAL,me.method("",Type.VOID,Type.NO_ARGS)); + main.add(LDC,fullClassName); + main.add(ALOAD_0); + if(unixRuntime) { + Type.Class ur = Type.Class.instance("org.ibex.nestedvm.UnixRuntime"); + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime.runAndExec + main.add(INVOKESTATIC,ur.method("runAndExec",Type.INT,new Type[]{ur,Type.STRING,Type.STRING.makeArray()})); + } else { + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime.run + main.add(INVOKEVIRTUAL,me.method("run",Type.INT,new Type[]{Type.STRING,Type.STRING.makeArray()})); + } + main.add(INVOKESTATIC,Type.Class.instance("java.lang.System").method("exit",Type.VOID,new Type[]{Type.INT})); + main.add(RETURN); - if(printStats) - System.out.println("Constant Pool Size: " + cp.getSize()); - cl.getJavaClass().dump(os); + if(outDir != null) { + if(!outDir.isDirectory()) throw new IOException("" + outDir + " isn't a directory"); + cg.dump(outDir); + } else { + cg.dump(os); + } } private void addConstReturnMethod(String name, int val) { - MethodGen method = newMethod(ACC_PROTECTED,Type.INT, Type.NO_ARGS,name); - selectMethod(method); - pushConst(val); - a(InstructionConstants.IRETURN); - method.setMaxLocals(); - method.setMaxStack(); - cl.addMethod(method.getMethod()); + MethodGen m = cg.addMethod(name,Type.INT,Type.NO_ARGS,PROTECTED); + m.add(LDC,val); + m.add(IRETURN); } private static int initDataCount; @@ -434,20 +405,19 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const sb.append((char) ((l>>>(7*(7-j)))&0x7f)); } String fieldname = "_data" + (++initDataCount); - cl.addField(new FieldGen(ACC_PRIVATE|ACC_STATIC|ACC_FINAL,new ArrayType(Type.INT,1),fieldname,cp).getField()); - - selectList(clinitExtras); - a(new PUSH(cp,sb.toString())); - a(new PUSH(cp,segSize/4)); - a(fac.createInvoke("org.ibex.nestedvm.Runtime","decodeData",new ArrayType(Type.INT,1),new Type[]{Type.STRING,Type.INT},INVOKESTATIC)); - a(fac.createPutStatic(fullClassName,fieldname,new ArrayType(Type.INT,1))); - - selectList(initExtras); - a(InstructionConstants.ALOAD_0); - a(fac.createGetStatic(fullClassName,fieldname,new ArrayType(Type.INT,1))); - a(new PUSH(cp,addr)); - a(new PUSH(cp,readOnly)); - a(fac.createInvoke(fullClassName,"initPages",Type.VOID,new Type[]{new ArrayType(Type.INT,1),Type.INT,Type.BOOLEAN},INVOKEVIRTUAL)); + cg.addField(fieldname,Type.INT.makeArray(),PRIVATE|STATIC|FINAL); + + clinit.add(LDC,sb.toString()); + clinit.add(LDC,segSize/4); + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime.decodeData + clinit.add(INVOKESTATIC,Type.Class.instance("org.ibex.nestedvm.Runtime").method("decodeData",Type.INT.makeArray(),new Type[]{Type.STRING,Type.INT})); + clinit.add(PUTSTATIC,me.field(fieldname,Type.INT.makeArray())); + init.add(ALOAD_0); + init.add(GETSTATIC,me.field(fieldname,Type.INT.makeArray())); + init.add(LDC,addr); + init.add(LDC,readOnly ? 1 : 0); + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime.initPages + init.add(INVOKEVIRTUAL,me.method("initPages",Type.VOID,new Type[]{Type.INT.makeArray(),Type.INT,Type.BOOLEAN})); addr += segSize; size -= segSize; @@ -459,26 +429,29 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if((addr&3)!=0) throw new Exn("BSS section on weird boundaries"); size = (size+3)&~3; int count = size/4; - selectList(initExtras); - a(InstructionConstants.ALOAD_0); - a(new PUSH(cp,addr)); - a(new PUSH(cp,count)); - a(fac.createInvoke(fullClassName,"clearPages",Type.VOID,new Type[]{Type.INT,Type.INT},INVOKEVIRTUAL)); + + init.add(ALOAD_0); + init.add(LDC,addr); + init.add(LDC,count); + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime.clearPages + init.add(INVOKEVIRTUAL,me.method("clearPages",Type.VOID,new Type[]{Type.INT,Type.INT})); } - // method state info - private boolean textDone; - private int startOfMethod = 0; - private int endOfMethod = 0; - private boolean unreachable = false; - private InstructionHandle[] jumpHandles; - private InstructionHandle defaultHandle; - private InstructionHandle returnHandle; - private InstructionHandle realStart; - private MethodGen curMethod; + // Method state info + private int startOfMethod = 0; // the start of this method (not necessarily the first instruction) + private int endOfMethod = 0; // the maximum end of this method (could end before it is full) + + private MethodGen.PhantomTarget returnTarget; // where to jump when exiting the method + private MethodGen.PhantomTarget defaultTarget; // the default switch target (throws exn) + private MethodGen.PhantomTarget[] insnTargets; // the targets for each jumpable instruction + private MethodGen mg; // the method itself - private boolean jumpable(int addr) { return jumpableAddresses.contains(new Integer(addr)); } + private boolean jumpable(int addr) { return jumpableAddresses.get(new Integer(addr)) != null; } + private static final int UNREACHABLE = 1; + private static final int SKIP_NEXT = 2; + + private boolean textDone; // a text segment was already processed private void emitText(int addr, DataInputStream dis, int size) throws Exn,IOException { if(textDone) throw new Exn("Multiple text segments"); textDone = true; @@ -486,187 +459,200 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if((addr&3)!=0 || (size&3)!=0) throw new Exn("Section on weird boundaries"); int count = size/4; int insn,nextInsn=-1; + boolean skipNext = true; + boolean unreachable = false; for(int i=0;i= endOfMethod) { endMethod(addr); startMethod(addr); } - if(jumpHandles[(addr-startOfMethod)/4] != null) { - // Move the fake jump target to the current location - insnList.move(jumpHandles[(addr-startOfMethod)/4],insnList.getEnd()); + if(addr >= endOfMethod) { endMethod(addr,unreachable); startMethod(addr); } + if(insnTargets[i%maxInsnPerMethod] != null) { + insnTargets[i%maxInsnPerMethod].setTarget(mg.size()); unreachable = false; } else if(unreachable) { continue; } try { - skipNext = emitInstruction(addr,insn,nextInsn); + int ret = emitInstruction(addr,insn,nextInsn); + unreachable = (ret & UNREACHABLE) != 0; + skipNext = (ret & SKIP_NEXT) != 0; + } catch(Exn e) { + e.printStackTrace(warn); + warn.println("Exception at " + toHex(addr)); + throw e; } catch(RuntimeException e) { warn.println("Exception at " + toHex(addr)); throw e; } if(skipNext) { addr+=4; i++; } } - endMethod(0); + endMethod(0,unreachable); dis.close(); } private void startMethod(int first) { startOfMethod = first & methodMask; endOfMethod = startOfMethod + maxBytesPerMethod; - curMethod = newMethod(ACC_PRIVATE,Type.VOID,Type.NO_ARGS,"run_" + toHex(startOfMethod)); - selectMethod(curMethod); + + mg = cg.addMethod("run_" + toHex(startOfMethod),Type.VOID,Type.NO_ARGS,PRIVATE|FINAL); + if(onePage) { + mg.add(ALOAD_0); + mg.add(GETFIELD,me.field("page",Type.INT.makeArray())); + mg.add(ASTORE_2); + } else { + mg.add(ALOAD_0); + mg.add(GETFIELD,me.field("readPages",Type.INT.makeArray(2))); + mg.add(ASTORE_2); + mg.add(ALOAD_0); + mg.add(GETFIELD,me.field("writePages",Type.INT.makeArray(2))); + mg.add(ASTORE_3); + } + + returnTarget = new MethodGen.PhantomTarget(); + insnTargets = new MethodGen.PhantomTarget[maxBytesPerMethod/4]; int[] buf = new int[maxBytesPerMethod/4]; - jumpHandles = new InstructionHandle[maxBytesPerMethod/4]; - int n=0; + Object[] targetBuf = new Object[maxBytesPerMethod/4]; + int n = 0; for(int addr=first;addr",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"pc",Type.INT, GETFIELD)); - a(fac.createInvoke("java.lang.StringBuffer","append",Type.STRINGBUFFER,new Type[]{Type.INT},INVOKEVIRTUAL)); - a(fac.createInvoke("java.lang.StringBuffer","toString",Type.STRING,Type.NO_ARGS,INVOKEVIRTUAL)); - a(fac.createInvoke("org.ibex.nestedvm.Runtime$ExecutionException","",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); - a(InstructionConstants.ATHROW); + mg.add(NEW,Type.Class.instance("org.ibex.nestedvm.Runtime$ExecutionException")); + mg.add(DUP); + mg.add(NEW,Type.STRINGBUFFER); + mg.add(DUP); + mg.add(LDC,"Jumped to invalid address: "); + mg.add(INVOKESPECIAL,Type.STRINGBUFFER.method("",Type.VOID,new Type[]{Type.STRING})); + mg.add(ALOAD_0); + mg.add(GETFIELD,me.field("pc",Type.INT)); + mg.add(INVOKEVIRTUAL,Type.STRINGBUFFER.method("append",Type.STRINGBUFFER,new Type[]{Type.INT})); + mg.add(INVOKEVIRTUAL,Type.STRINGBUFFER.method("toString",Type.STRING,Type.NO_ARGS)); + mg.add(INVOKESPECIAL,Type.Class.instance("org.ibex.nestedvm.Runtime$ExecutionException").method("",Type.VOID,new Type[]{Type.STRING})); + mg.add(ATHROW); } else { - a(fac.createNew("org.ibex.nestedvm.Runtime$ExecutionException")); - a(InstructionConstants.DUP); - a(new PUSH(cp,"Jumped to invalid address")); - a(fac.createInvoke("org.ibex.nestedvm.Runtime$ExecutionException","",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); - a(InstructionConstants.ATHROW); + mg.add(NEW,Type.Class.instance("org.ibex.nestedvm.Runtime$ExecutionException")); + mg.add(DUP); + mg.add(LDC,"Jumped to invalid address"); + mg.add(INVOKESPECIAL,Type.Class.instance("org.ibex.nestedvm.Runtime$ExecutionException").method("",Type.VOID,new Type[]{Type.STRING})); + mg.add(ATHROW); } - - if(insnList.getStart() != realStart) { - System.err.println(insnList); - throw new Error("A jumpHandle wasn't moved into place"); - } - - curMethod.removeNOPs(); - curMethod.setMaxLocals(); - curMethod.setMaxStack(); - - cl.addMethod(curMethod.getMethod()); endOfMethod = startOfMethod = 0; } private void leaveMethod() { - a(InstructionFactory.createBranchInstruction(GOTO,returnHandle)); + 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)) { - a(InstructionFactory.createBranchInstruction(GOTO,jumpHandles[(target-startOfMethod)/4])); + mg.add(GOTO,insnTargets[(target-startOfMethod)/4]); } else { preSetPC(); - pushConst(target); + mg.add(LDC,target); setPC(); leaveMethod(); } } // This assumes everything needed by ifInsn is already on the stack - private boolean doIfInstruction(short op, int pc, int target, int nextInsn) throws Exn { + private int doIfInstruction(byte op, int pc, int target, int nextInsn) throws Exn { emitInstruction(-1,nextInsn,-1); // delay slot - BranchHandle h; - IfInstruction ifInsn = (IfInstruction) InstructionFactory.createBranchInstruction(op,null); if((target&methodMask) == (pc&methodMask)) { - h = a(ifInsn); - h.setTarget(jumpHandles[(target-startOfMethod)/4]); + mg.add(op,insnTargets[(target-startOfMethod)/4]); } else { - h = a(ifInsn.negate()); + int h = mg.add(MethodGen.negate(op)); branch(pc,target); - h.setTarget(a(InstructionConstants.NOP)); + mg.setArg(h,mg.size()); } - if(!jumpable(pc+4)) return true; // done - skip it + if(!jumpable(pc+4)) return SKIP_NEXT; // done - skip it //System.err.println("Delay slot is jumpable - This code is untested + " + toHex(nextInsn)); if(pc+4==endOfMethod) { // the delay slot is at the start of the next method - jumpableAddresses.add(new Integer(pc+8)); // make the 2nd insn of the next method jumpable + jumpableAddresses.put(new Integer(pc+8),Boolean.TRUE); // make the 2nd insn of the next method jumpable branch(pc,pc+8); // jump over it - //System.err.println("delay slot: " + toHex(pc+8)); - unreachable = true; - return false; // we still need to output it + //System.err.println("delay slot: " + toHex(pc+8)); */ + //unreachable = true; + //return false; // we still need to output it + return UNREACHABLE; } else { //System.err.println("jumped over delay slot: " + toHex(pc+4)); // add another copy and jump over - h = a(InstructionFactory.createBranchInstruction(GOTO,null)); - insnList.move(jumpHandles[(pc+4-startOfMethod)/4],insnList.getEnd()); - emitInstruction(-1,nextInsn,-1); // delay slot - h.setTarget(a(InstructionConstants.NOP)); - return true; + + int b = mg.add(GOTO); + insnTargets[(pc+4-startOfMethod)/4].setTarget(mg.size()); + emitInstruction(-1,nextInsn,01); // delay slot + mg.setArg(b,mg.size()); + + return SKIP_NEXT; } } - private boolean emitInstruction(int pc, int insn, int nextInsn) throws Exn { + private static final Float POINT_5_F = new Float(0.5f); + private static final Double POINT_5_D = new Double(0.5f); + private static final Long FFFFFFFF = new Long(0xffffffffL); + + private int emitInstruction(int pc, int insn, int nextInsn) throws Exn { + MethodGen mg = this.mg; // smaller bytecode if(insn == -1) throw new Exn("insn is -1"); + int ret = 0; + int op = (insn >>> 26) & 0xff; // bits 26-31 int rs = (insn >>> 21) & 0x1f; // bits 21-25 int rt = (insn >>> 16) & 0x1f; // bits 16-20 @@ -677,14 +663,14 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const int fd = (insn >>> 6) & 0x1f; int subcode = insn & 0x3f; // bits 0-5 int breakCode = (insn >>> 6) & 0xfffff; // bits 6-20 - + int jumpTarget = (insn & 0x03ffffff); // bits 0-25 int unsignedImmediate = insn & 0xffff; int signedImmediate = (insn << 16) >> 16; int branchTarget = signedImmediate; - + // temporaries - BranchHandle b1,b2; + int b1,b2; switch(op) { case 0: { @@ -693,43 +679,43 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if(insn == 0) break; preSetReg(R+rd); pushRegWZ(R+rt); - pushConst(shamt); - a(InstructionConstants.ISHL); + mg.add(LDC,shamt); + mg.add(ISHL); setReg(); break; case 2: // SRL preSetReg(R+rd); pushRegWZ(R+rt); - pushConst(shamt); - a(InstructionConstants.IUSHR); + mg.add(LDC,shamt); + mg.add(IUSHR); setReg(); break; case 3: // SRA preSetReg(R+rd); pushRegWZ(R+rt); - pushConst(shamt); - a(InstructionConstants.ISHR); + mg.add(LDC,shamt); + mg.add(ISHR); setReg(); break; case 4: // SLLV preSetReg(R+rd); pushRegWZ(R+rt); pushRegWZ(R+rs); - a(InstructionConstants.ISHL); + mg.add(ISHL); setReg(); break; case 6: // SRLV preSetReg(R+rd); pushRegWZ(R+rt); pushRegWZ(R+rs); - a(InstructionConstants.IUSHR); + mg.add(IUSHR); setReg(); break; case 7: // SRAV preSetReg(R+rd); pushRegWZ(R+rt); pushRegWZ(R+rs); - a(InstructionConstants.ISHR); + mg.add(ISHR); setReg(); break; case 8: // JR @@ -739,56 +725,56 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const pushRegWZ(R+rs); setPC(); leaveMethod(); - unreachable = true; + ret |= UNREACHABLE; break; 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); - pushConst(pc+8); - setReg(); leaveMethod(); - unreachable = true; + ret |= UNREACHABLE; break; case 12: // SYSCALL preSetPC(); - pushConst(pc); + 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); - a(InstructionConstants.ALOAD_0); + mg.add(ALOAD_0); pushRegZ(R+V0); pushRegZ(R+A0); pushRegZ(R+A1); pushRegZ(R+A2); pushRegZ(R+A3); - a(fac.createInvoke(fullClassName,"syscall",Type.INT,new Type[]{Type.INT,Type.INT,Type.INT,Type.INT,Type.INT},INVOKEVIRTUAL)); + pushRegZ(R+T0); + pushRegZ(R+T1); + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime.syscall + mg.add(INVOKEVIRTUAL,me.method("syscall",Type.INT,new Type[]{Type.INT,Type.INT,Type.INT,Type.INT,Type.INT,Type.INT,Type.INT})); setReg(); - a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,"state",Type.INT, GETFIELD)); - pushConst(Runtime.RUNNING); - b1 = a(InstructionFactory.createBranchInstruction(IF_ICMPEQ,null)); + mg.add(ALOAD_0); + mg.add(GETFIELD,me.field("state",Type.INT)); + b1 = mg.add(IFEQ); preSetPC(); - pushConst(pc+4); + mg.add(LDC,pc+4); setPC(); leaveMethod(); - b1.setTarget(a(InstructionConstants.NOP)); - + mg.setArg(b1,mg.size()); break; case 13: // BREAK - a(fac.createNew("org.ibex.nestedvm.Runtime$ExecutionException")); - a(InstructionConstants.DUP); - a(new PUSH(cp,"BREAK Code " + toHex(breakCode))); - a(fac.createInvoke("org.ibex.nestedvm.Runtime$ExecutionException","",Type.VOID,new Type[]{Type.STRING},INVOKESPECIAL)); - a(InstructionConstants.ATHROW); - unreachable = true; + mg.add(NEW,Type.Class.instance("org.ibex.nestedvm.Runtime$ExecutionException")); + mg.add(DUP); + mg.add(LDC,"BREAK Code " + toHex(breakCode)); + mg.add(INVOKESPECIAL,Type.Class.instance("org.ibex.nestedvm.Runtime$ExecutionException").method("",Type.VOID,new Type[]{Type.STRING})); + mg.add(ATHROW); + ret |= UNREACHABLE; break; case 16: // MFHI preSetReg(R+rd); @@ -812,97 +798,97 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const break; case 24: // MULT pushRegWZ(R+rs); - a(InstructionConstants.I2L); + mg.add(I2L); pushRegWZ(R+rt); - a(InstructionConstants.I2L); - a(InstructionConstants.LMUL); - a(InstructionConstants.DUP2); + mg.add(I2L); + mg.add(LMUL); + mg.add(DUP2); - a(InstructionConstants.L2I); + mg.add(L2I); if(preSetReg(LO)) - a(InstructionConstants.SWAP); + mg.add(SWAP); //a(InstructionConstants.SWAP); setReg(); - pushConst(32); - a(InstructionConstants.LUSHR); - a(InstructionConstants.L2I); + mg.add(LDC,32); + mg.add(LUSHR); + mg.add(L2I); if(preSetReg(HI)) - a(InstructionConstants.SWAP); + mg.add(SWAP); //a(InstructionConstants.SWAP); setReg(); break; case 25: // MULTU pushRegWZ(R+rs); - a(InstructionConstants.I2L); - pushConst(0xffffffffL); - a(InstructionConstants.LAND); + mg.add(I2L); + mg.add(LDC,FFFFFFFF); + mg.add(LAND); pushRegWZ(R+rt); - a(InstructionConstants.I2L); - pushConst(0xffffffffL); - a(InstructionConstants.LAND); - a(InstructionConstants.LMUL); - a(InstructionConstants.DUP2); + mg.add(I2L); + mg.add(LDC,FFFFFFFF); + mg.add(LAND); + mg.add(LMUL); + mg.add(DUP2); - a(InstructionConstants.L2I); + mg.add(L2I); if(preSetReg(LO)) - a(InstructionConstants.SWAP); + mg.add(SWAP); setReg(); - pushConst(32); - a(InstructionConstants.LUSHR); - a(InstructionConstants.L2I); + mg.add(LDC,32); + mg.add(LUSHR); + mg.add(L2I); if(preSetReg(HI)) - a(InstructionConstants.SWAP); + mg.add(SWAP); setReg(); break; case 26: // DIV pushRegWZ(R+rs); pushRegWZ(R+rt); - a(InstructionConstants.DUP2); + mg.add(DUP2); - a(InstructionConstants.IDIV); + mg.add(IDIV); if(preSetReg(LO)) - a(InstructionConstants.SWAP); + mg.add(SWAP); setReg(); - a(InstructionConstants.IREM); + mg.add(IREM); if(preSetReg(HI)) - a(InstructionConstants.SWAP); + mg.add(SWAP); setReg(); break; case 27: { // DIVU pushRegWZ(R+rt); - a(InstructionConstants.DUP); + mg.add(DUP); setTmp(); - b1 = a(InstructionFactory.createBranchInstruction(IFEQ,null)); + b1 = mg.add(IFEQ); pushRegWZ(R+rs); - a(InstructionConstants.I2L); - pushConst(0xffffffffL); - a(InstructionConstants.LAND); - a(InstructionConstants.DUP2); + mg.add(I2L); + mg.add(LDC,FFFFFFFF); + mg.add(LAND); + mg.add(DUP2); pushTmp(); - a(InstructionConstants.I2L); - pushConst(0xffffffffL); + mg.add(I2L); + mg.add(LDC,FFFFFFFF); - a(InstructionConstants.LAND); - a(InstructionConstants.DUP2_X2); - a(InstructionConstants.LDIV); + mg.add(LAND); + mg.add(DUP2_X2); + mg.add(LDIV); - a(InstructionConstants.L2I); + mg.add(L2I); if(preSetReg(LO)) - a(InstructionConstants.SWAP); + mg.add(SWAP); setReg(); - a(InstructionConstants.LREM); - a(InstructionConstants.L2I); + mg.add(LREM); + mg.add(L2I); if(preSetReg(HI)) - a(InstructionConstants.SWAP); + mg.add(SWAP); setReg(); - b1.setTarget(a(InstructionConstants.NOP)); + mg.setArg(b1,mg.size()); break; } @@ -913,7 +899,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if(rt != 0 && rs != 0) { pushReg(R+rs); pushReg(R+rt); - a(InstructionConstants.IADD); + mg.add(IADD); } else if(rs != 0) { pushReg(R+rs); } else { @@ -928,10 +914,10 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if(rt != 0 && rs != 0) { pushReg(R+rs); pushReg(R+rt); - a(InstructionConstants.ISUB); + mg.add(ISUB); } else if(rt != 0) { pushReg(R+rt); - a(InstructionConstants.INEG); + mg.add(INEG); } else { pushRegZ(R+rs); } @@ -941,21 +927,21 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const preSetReg(R+rd); pushRegWZ(R+rs); pushRegWZ(R+rt); - a(InstructionConstants.IAND); + mg.add(IAND); setReg(); break; case 37: // OR preSetReg(R+rd); pushRegWZ(R+rs); pushRegWZ(R+rt); - a(InstructionConstants.IOR); + mg.add(IOR); setReg(); break; case 38: // XOR preSetReg(R+rd); pushRegWZ(R+rs); pushRegWZ(R+rt); - a(InstructionConstants.IXOR); + mg.add(IXOR); setReg(); break; case 39: // NOR @@ -964,16 +950,16 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if(rs != 0 && rt != 0) { pushReg(R+rs); pushReg(R+rt); - a(InstructionConstants.IOR); + mg.add(IOR); } else if(rs != 0) { pushReg(R+rs); } else { pushReg(R+rt); } - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); + mg.add(ICONST_M1); + mg.add(IXOR); } else { - pushConst(-1); + mg.add(LDC,-1); } setReg(); break; @@ -982,13 +968,13 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if(rs != rt) { pushRegZ(R+rs); pushRegZ(R+rt); - b1 = a(InstructionFactory.createBranchInstruction(IF_ICMPLT,null)); - a(InstructionConstants.ICONST_0); - b2 = a(InstructionFactory.createBranchInstruction(GOTO,null)); - b1.setTarget(a(InstructionConstants.ICONST_1)); - b2.setTarget(a(InstructionConstants.NOP)); + b1 = mg.add(IF_ICMPLT); + mg.add(ICONST_0); + b2 = mg.add(GOTO); + mg.setArg(b1,mg.add(ICONST_1)); + mg.setArg(b2,mg.size()); } else { - pushConst(0); + mg.add(LDC,0); } setReg(); break; @@ -997,25 +983,25 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if(rs != rt) { if(rs != 0) { pushReg(R+rs); - a(InstructionConstants.I2L); - pushConst(0xffffffffL); - a(InstructionConstants.LAND); + mg.add(I2L); + mg.add(LDC,FFFFFFFF); + mg.add(LAND); pushReg(R+rt); - a(InstructionConstants.I2L); - pushConst(0xffffffffL); - a(InstructionConstants.LAND); - a(InstructionConstants.LCMP); - b1 = a(InstructionFactory.createBranchInstruction(IFLT,null)); + mg.add(I2L); + mg.add(LDC,FFFFFFFF); + mg.add(LAND); + mg.add(LCMP); + b1 = mg.add(IFLT); } else { pushReg(R+rt); - b1 = a(InstructionFactory.createBranchInstruction(IFNE,null)); + b1 = mg.add(IFNE); } - a(InstructionConstants.ICONST_0); - b2 = a(InstructionFactory.createBranchInstruction(GOTO,null)); - b1.setTarget(a(InstructionConstants.ICONST_1)); - b2.setTarget(a(InstructionConstants.NOP)); + mg.add(ICONST_0); + b2 = mg.add(GOTO); + mg.setArg(b1,mg.add(ICONST_1)); + mg.setArg(b2,mg.size()); } else { - pushConst(0); + mg.add(LDC,0); } setReg(); break; @@ -1037,28 +1023,24 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const case 16: // BLTZAL if(pc == -1) throw new Exn("pc modifying insn in delay slot"); pushRegWZ(R+rs); - b1 = a(InstructionFactory.createBranchInstruction(IFGE,null)); + b1 = mg.add(IFGE); emitInstruction(-1,nextInsn,-1); - preSetReg(R+RA); - pushConst(pc+8); - setReg(); + link(pc); branch(pc,pc+branchTarget*4+4); - b1.setTarget(a(InstructionConstants.NOP)); + mg.setArg(b1,mg.size()); break; case 17: // BGEZAL if(pc == -1) throw new Exn("pc modifying insn in delay slot"); - b1 = null; + b1 = -1; if(rs != 0) { // r0 is always >= 0 pushRegWZ(R+rs); - b1 = a(InstructionFactory.createBranchInstruction(IFLT,null)); + b1 = mg.add(IFLT); } emitInstruction(-1,nextInsn,-1); - preSetReg(R+RA); - pushConst(pc+8); - setReg(); + link(pc); branch(pc,pc+branchTarget*4+4); - if(b1 != null) b1.setTarget(a(InstructionConstants.NOP)); - if(b1 == null) unreachable = true; + if(b1 != -1) mg.setArg(b1,mg.size()); + if(b1 == -1) ret |= UNREACHABLE; break; default: throw new Exn("Illegal Instruction 1/" + rt); @@ -1069,18 +1051,16 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if(pc == -1) throw new Exn("pc modifying insn in delay slot"); emitInstruction(-1,nextInsn,-1); branch(pc,(pc&0xf0000000)|(jumpTarget << 2)); - unreachable = true; + ret |= UNREACHABLE; break; } case 3: { // JAL 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); - pushConst(pc+8); - setReg(); + link(pc); branch(pc, target); - unreachable = true; + ret |= UNREACHABLE; break; } case 4: // BEQ @@ -1088,7 +1068,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if(rs == rt) { emitInstruction(-1,nextInsn,-1); branch(pc,pc+branchTarget*4+4); - unreachable = true; + ret |= UNREACHABLE; } else if(rs == 0 || rt == 0) { pushReg(rt == 0 ? R+rs : R+rt); return doIfInstruction(IFEQ,pc,pc+branchTarget*4+4,nextInsn); @@ -1118,69 +1098,74 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const case 8: // ADDI throw new Exn("ADDI (add immediate with oveflow trap) not suported"); case 9: // ADDIU - preSetReg(R+rt); - addiu(rs,signedImmediate); - setReg(); + if(rs != 0 && signedImmediate != 0 && rs == rt && doLocal(rt) && signedImmediate >= -32768 && signedImmediate <= 32767) { + // HACK: This should be a little cleaner + regLocalWritten[rt] = true; + mg.add(IINC, new MethodGen.Pair(getLocalForReg(rt),signedImmediate)); + } else { + preSetReg(R+rt); + addiu(rs,signedImmediate); + setReg(); + } break; case 10: // SLTI preSetReg(R+rt); pushRegWZ(R+rs); - pushConst(signedImmediate); - b1 = a(InstructionFactory.createBranchInstruction(IF_ICMPLT,null)); - a(InstructionConstants.ICONST_0); - b2 = a(InstructionFactory.createBranchInstruction(GOTO,null)); - b1.setTarget(a(InstructionConstants.ICONST_1)); - b2.setTarget(a(InstructionConstants.NOP)); + mg.add(LDC,signedImmediate); + b1 = mg.add(IF_ICMPLT); + mg.add(ICONST_0); + b2 = mg.add(GOTO); + mg.setArg(b1,mg.add(ICONST_1)); + mg.setArg(b2,mg.size()); setReg(); break; case 11: // SLTIU preSetReg(R+rt); pushRegWZ(R+rs); - a(InstructionConstants.I2L); - pushConst(0xffffffffL); - a(InstructionConstants.LAND); + mg.add(I2L); + mg.add(LDC,FFFFFFFF); + mg.add(LAND); // 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)); - a(InstructionConstants.ICONST_0); - b2 = a(InstructionFactory.createBranchInstruction(GOTO,null)); - b1.setTarget(a(InstructionConstants.ICONST_1)); - b2.setTarget(a(InstructionConstants.NOP)); - + mg.add(LDC,new Long(signedImmediate&0xffffffffL)); + mg.add(LCMP); + + b1 = mg.add(IFLT); + mg.add(ICONST_0); + b2 = mg.add(GOTO); + mg.setArg(b1,mg.add(ICONST_1)); + mg.setArg(b2,mg.size()); setReg(); break; case 12: // ANDI preSetReg(R+rt); pushRegWZ(R+rs); - pushConst(unsignedImmediate); - a(InstructionConstants.IAND); + mg.add(LDC,unsignedImmediate); + mg.add(IAND); setReg(); break; case 13: // ORI preSetReg(R+rt); if(rs != 0 && unsignedImmediate != 0) { pushReg(R+rs); - pushConst(unsignedImmediate); - a(InstructionConstants.IOR); + mg.add(LDC,unsignedImmediate); + mg.add(IOR); } else if(rs != 0){ pushReg(R+rs); } else { - pushConst(unsignedImmediate); + mg.add(LDC,unsignedImmediate); } setReg(); break; case 14: // XORI preSetReg(R+rt); pushRegWZ(R+rs); - pushConst(unsignedImmediate); - a(InstructionConstants.IXOR); + mg.add(LDC,unsignedImmediate); + mg.add(IXOR); setReg(); break; case 15: // LUI preSetReg(R+rt); - pushConst(unsignedImmediate << 16); + mg.add(LDC,unsignedImmediate << 16); setReg(); break; case 16: @@ -1200,10 +1185,8 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const break; case 4: // MTC.1 preSetReg(F+rd); - if(rt != 0) - pushReg(R+rt); - else - pushConst(0); + if(rt != 0) pushReg(R+rt); + else mg.add(ICONST_0); setReg(); break; case 6: // CTC.1 @@ -1214,8 +1197,8 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const break; case 8: {// BC1F, BC1T pushReg(FCSR); - pushConst(0x800000); - a(InstructionConstants.IAND); + mg.add(LDC,0x800000); + mg.add(IAND); return doIfInstruction(((insn>>>16)&1) == 0 ? IFEQ : IFNE,pc,pc+branchTarget*4+4,nextInsn); } case 16: @@ -1227,28 +1210,28 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const preSetDouble(F+fd,d); pushDouble(F+fs,d); pushDouble(F+ft,d); - a(d ? InstructionConstants.DADD : InstructionConstants.FADD); + mg.add(d ? DADD : FADD); setDouble(d); break; case 1: // SUB.X preSetDouble(F+fd,d); pushDouble(F+fs,d); pushDouble(F+ft,d); - a(d ? InstructionConstants.DSUB : InstructionConstants.FSUB); + mg.add(d ? DSUB : FSUB); setDouble(d); break; case 2: // MUL.X preSetDouble(F+fd,d); pushDouble(F+fs,d); pushDouble(F+ft,d); - a(d ? InstructionConstants.DMUL : InstructionConstants.FMUL); + mg.add(d ? DMUL : FMUL); setDouble(d); break; case 3: // DIV.X preSetDouble(F+fd,d); pushDouble(F+fs,d); pushDouble(F+ft,d); - a(d ? InstructionConstants.DDIV : InstructionConstants.FDIV); + mg.add(d ? DDIV : FDIV); setDouble(d); break; case 5: // ABS.X @@ -1256,85 +1239,88 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const // NOTE: We can't use fneg/dneg here since they'll turn +0.0 into -0.0 pushDouble(F+fs,d); - a(d ? InstructionConstants.DUP2 : InstructionConstants.DUP); - a(d ? InstructionConstants.DCONST_0 : InstructionConstants.FCONST_0); - a(d ? InstructionConstants.DCMPG : InstructionConstants.FCMPG); + mg.add(d ? DUP2 : DUP); + mg.add(d ? DCONST_0 : FCONST_0); + mg.add(d ? DCMPG : FCMPG); - b1 = a(InstructionFactory.createBranchInstruction(IFGT,null)); - a(d ? InstructionConstants.DCONST_0 : InstructionConstants.FCONST_0); - a(d ? InstructionConstants.DSUB : InstructionConstants.FSUB); + b1 = mg.add(IFGT); + mg.add(d ? DCONST_0 : FCONST_0); + if(d) { + mg.add(DUP2_X2); + mg.add(POP2); + } else { + mg.add(SWAP); + } + mg.add(d ? DSUB : FSUB); - b1.setTarget(setDouble(d)); + mg.setArg(b1,mg.size()); + setDouble(d); break; case 6: // MOV.X preSetReg(F+fd); pushReg(F+fs); 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); + mg.add(d ? DNEG : FNEG); setDouble(d); break; case 32: // CVT.S.X preSetFloat(F+fd); pushDouble(F+fs,d); - if(d) a(InstructionConstants.D2F); + if(d) mg.add(D2F); setFloat(); break; case 33: // CVT.D.X preSetDouble(F+fd); pushDouble(F+fs,d); - if(!d) a(InstructionConstants.F2D); + if(!d) mg.add(F2D); setDouble(); break; case 36: { // CVT.W.D - int[] matches = new int[4]; - for(int i=0;i<4;i++) matches[i] = i; - - TABLESWITCH ts = new TABLESWITCH(matches,new InstructionHandle[4], null); - + MethodGen.Switch.Table tsi = new MethodGen.Switch.Table(0,3); preSetReg(F+fd); pushDouble(F+fs,d); pushReg(FCSR); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(ts); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(TABLESWITCH,tsi); // Round towards plus infinity - ts.setTarget(2,a(InstructionConstants.NOP)); - if(!d) a(InstructionConstants.F2D); // Ugh.. java.lang.Math doesn't have a float ceil/floor - a(fac.createInvoke("java.lang.Math","ceil",Type.DOUBLE,new Type[]{Type.DOUBLE},INVOKESTATIC)); - if(!d) a(InstructionConstants.D2F); - b1 = a(InstructionFactory.createBranchInstruction(GOTO,null)); + tsi.setTarget(2,mg.size()); + if(!d) mg.add(F2D); // Ugh.. java.lang.Math doesn't have a float ceil/floor + mg.add(INVOKESTATIC,Type.Class.instance("java.lang.Math").method("ceil",Type.DOUBLE,new Type[]{Type.DOUBLE})); + if(!d) mg.add(D2F); + b1 = mg.add(GOTO); // Round to nearest - ts.setTarget(0,d ? pushConst(0.5d) : pushConst(0.5f)); - a(d ? InstructionConstants.DADD : InstructionConstants.FADD); + tsi.setTarget(0,mg.size()); + mg.add(LDC,d ? (Object)POINT_5_D : (Object)POINT_5_F); + mg.add(d ? DADD : FADD); // fall through // Round towards minus infinity - ts.setTarget(3,a(InstructionConstants.NOP)); - if(!d) a(InstructionConstants.F2D); - a(fac.createInvoke("java.lang.Math","floor",Type.DOUBLE,new Type[]{Type.DOUBLE},INVOKESTATIC)); - if(!d) a(InstructionConstants.D2F); + tsi.setTarget(3,mg.size()); + if(!d) mg.add(F2D); + mg.add(INVOKESTATIC,Type.Class.instance("java.lang.Math").method("floor",Type.DOUBLE,new Type[]{Type.DOUBLE})); + if(!d) mg.add(D2F); - InstructionHandle h = a(d ? InstructionConstants.D2I : InstructionConstants.F2I); + tsi.setTarget(1,mg.size()); + tsi.setDefaultTarget(mg.size()); + mg.setArg(b1,mg.size()); + + mg.add(d ? D2I : F2I); setReg(); - ts.setTarget(1,h); - ts.setTarget(h); - b1.setTarget(h); - break; } case 50: // C.EQ.D @@ -1342,22 +1328,20 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const case 62: // C.LE.D preSetReg(FCSR); pushReg(FCSR); - pushConst(~0x800000); - a(InstructionConstants.IAND); + mg.add(LDC,~0x800000); + mg.add(IAND); pushDouble(F+fs,d); pushDouble(F+ft,d); - a(d ? InstructionConstants.DCMPG : InstructionConstants.FCMPG); + mg.add(d ? DCMPG : FCMPG); switch(subcode) { - case 50: b1 = a(InstructionFactory.createBranchInstruction(IFEQ,null)); break; - case 60: b1 = a(InstructionFactory.createBranchInstruction(IFLT,null)); break; - case 62: b1 = a(InstructionFactory.createBranchInstruction(IFLE,null)); break; - default: b1 = null; + case 50: b1 = mg.add(IFNE); break; + case 60: b1 = mg.add(IFGE); break; + case 62: b1 = mg.add(IFGT); break; + default: b1 = -1; } - // FIXME: We probably don't need to pushConst(0x00000) - pushConst(0x000000); - b2 = a(InstructionFactory.createBranchInstruction(GOTO,null)); - b1.setTarget(pushConst(0x800000)); - b2.setTarget(a(InstructionConstants.IOR)); + mg.add(LDC,0x800000); + mg.add(IOR); + mg.setArg(b1,mg.size()); setReg(); break; default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode); @@ -1369,13 +1353,13 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const case 32: // CVT.S.W preSetFloat(F+fd); pushReg(F+fs); - a(InstructionConstants.I2F); + mg.add(I2F); setFloat(); break; case 33: // CVT.D.W preSetDouble(F+fd); pushReg(F+fs); - a(InstructionConstants.I2D); + mg.add(I2D); setDouble(); break; default: throw new Exn("Invalid Instruction 17/" + rs + "/" + subcode); @@ -1398,14 +1382,14 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const memRead(true); pushTmp(); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.IUSHR); - a(InstructionConstants.I2B); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(IUSHR); + mg.add(I2B); setReg(); break; } @@ -1418,14 +1402,14 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const memRead(true); pushTmp(); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.ICONST_2); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.IUSHR); - a(InstructionConstants.I2S); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(ICONST_2); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(IUSHR); + mg.add(I2S); setReg(); break; } @@ -1435,29 +1419,29 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const setTmp(); // addr pushRegWZ(R+rt); - pushConst(0x00ffffff); + mg.add(LDC,0x00ffffff); pushTmp(); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.IUSHR); - a(InstructionConstants.IAND); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(IUSHR); + mg.add(IAND); preMemRead(); pushTmp(); memRead(true); pushTmp(); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.ISHL); - a(InstructionConstants.IOR); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(ISHL); + mg.add(IOR); setReg(); @@ -1478,15 +1462,15 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const memRead(true); pushTmp(); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.IUSHR); - pushConst(0xff); - a(InstructionConstants.IAND); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(IUSHR); + mg.add(LDC,0xff); + mg.add(IAND); setReg(); break; } @@ -1499,16 +1483,16 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const memRead(true); pushTmp(); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.ICONST_2); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.IUSHR); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(ICONST_2); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(IUSHR); // chars are unsigend so this works - a(InstructionConstants.I2C); + mg.add(I2C); setReg(); break; } @@ -1518,29 +1502,29 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const setTmp(); // addr pushRegWZ(R+rt); - pushConst(0xffffff00); + mg.add(LDC,0xffffff00); pushTmp(); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.ISHL); - a(InstructionConstants.IAND); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(ISHL); + mg.add(IAND); preMemRead(); pushTmp(); memRead(true); pushTmp(); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.IUSHR); - a(InstructionConstants.IOR); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(IUSHR); + mg.add(IOR); setReg(); @@ -1550,125 +1534,113 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const addiu(R+rs,signedImmediate); setTmp(); // addr - // FEATURE: DO the preMemRead(true) thing for the rest of the S* instructions preMemRead(true); pushTmp(); memRead(true); - pushConst(0xff000000); + mg.add(LDC,0xff000000); pushTmp(); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.IUSHR); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.IAND); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(IUSHR); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(IAND); if(rt != 0) { pushReg(R+rt); - pushConst(0xff); - a(InstructionConstants.IAND); + mg.add(LDC,0xff); + mg.add(IAND); } else { - pushConst(0); + mg.add(LDC,0); } pushTmp(); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.ISHL); - a(InstructionConstants.IOR); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(ISHL); + mg.add(IOR); memWrite(); break; } case 41: { // SH - preMemWrite1(); - addiu(R+rs,signedImmediate); + setTmp(); - a(InstructionConstants.DUP); - setTmp(); // addr - - preMemWrite2(true); - - preMemRead(); + preMemRead(true); pushTmp(); memRead(true); - - pushConst(0xffff); + + mg.add(LDC,0xffff); pushTmp(); - a(InstructionConstants.ICONST_2); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.ISHL); - a(InstructionConstants.IAND); + mg.add(ICONST_2); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(ISHL); + mg.add(IAND); if(rt != 0) { pushReg(R+rt); - pushConst(0xffff); - a(InstructionConstants.IAND); + mg.add(LDC,0xffff); + mg.add(IAND); } else { - pushConst(0); + mg.add(LDC,0); } pushTmp(); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.ICONST_2); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.ISHL); - a(InstructionConstants.IOR); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(ICONST_2); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(ISHL); + mg.add(IOR); memWrite(); break; } case 42: { // SWL - preMemWrite1(); - addiu(R+rs,signedImmediate); - a(InstructionConstants.DUP); - setTmp(); // addr - - preMemWrite2(true); + setTmp(); - preMemRead(); + preMemRead(true); pushTmp(); memRead(true); - pushConst(0xffffff00); + mg.add(LDC,0xffffff00); pushTmp(); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.ISHL); - a(InstructionConstants.IAND); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(ISHL); + mg.add(IAND); pushRegWZ(R+rt); pushTmp(); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.IUSHR); - a(InstructionConstants.IOR); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(IUSHR); + mg.add(IOR); memWrite(); break; @@ -1681,39 +1653,34 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const memWrite(); break; case 46: { // SWR - preMemWrite1(); - addiu(R+rs,signedImmediate); - a(InstructionConstants.DUP); - setTmp(); // addr - - preMemWrite2(true); + setTmp(); - preMemRead(); + preMemRead(true); pushTmp(); memRead(true); - pushConst(0x00ffffff); + mg.add(LDC,0x00ffffff); pushTmp(); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.IUSHR); - a(InstructionConstants.IAND); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(IUSHR); + mg.add(IAND); pushRegWZ(R+rt); pushTmp(); - a(InstructionConstants.ICONST_M1); - a(InstructionConstants.IXOR); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.IAND); - a(InstructionConstants.ICONST_3); - a(InstructionConstants.ISHL); - a(InstructionConstants.ISHL); - a(InstructionConstants.IOR); + mg.add(ICONST_M1); + mg.add(IXOR); + mg.add(ICONST_3); + mg.add(IAND); + mg.add(ICONST_3); + mg.add(ISHL); + mg.add(ISHL); + mg.add(IOR); memWrite(); break; @@ -1732,7 +1699,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const break; /* This needs to fail (set rt to 0) if the memory location was modified - * between the LL and SC if we every support threads. + * between the LL and SC if we ever support threads. */ case 56: // SWC0/SC preSetReg(R+rt); @@ -1740,7 +1707,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const preMemWrite2(R+rs,signedImmediate); pushReg(R+rt); memWrite(); - pushConst(1); + mg.add(LDC,1); setReg(); break; @@ -1753,7 +1720,7 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const default: throw new Exn("Invalid Instruction: " + op + " at " + toHex(pc)); } - return false; + return ret; } // Helper functions for emitText @@ -1764,85 +1731,74 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const private static final int LO = 65; private static final int FCSR = 66; private static final int REG_COUNT=67; - + 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 final int MAX_LOCALS = 4; // doLocal can return true for this many regs + private static final int LOAD_LENGTH = 3; // number of instructions needed to load a field to a reg + + // Local register state info 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 boolean[] regLocalWritten = new boolean[REG_COUNT]; + private int nextAvailLocal; + private int loadsStart; + + 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]; - if(nextAvailLocal == 0) nextAvailLocal = onePage ? 3 : 4; regLocalMapping[reg] = nextAvailLocal++; return regLocalMapping[reg]; } - private void fixupRegs() { - InstructionHandle prev = realStart; + private void fixupRegsStart() { for(int i=0;i 0) { - a(InstructionConstants.ALOAD_0); - a(InstructionFactory.createLoad(Type.INT,regLocalMapping[i])); - a(fac.createFieldAccess(fullClassName,regField(i),Type.INT, PUTFIELD)); - } - - regLocalMapping[i] = regLocalReadCount[i] = regLocalWriteCount[i] = 0; + regLocalMapping[i] = 0; + regLocalWritten[i] = false; } - nextAvailLocal = 0; + nextAvailLocal = onePage ? 4 : 5; + loadsStart = mg.size(); + for(int i=0;i 0) { - a(InstructionConstants.ALOAD_0); - a(InstructionFactory.createLoad(Type.INT,regLocalMapping[i])); - a(fac.createFieldAccess(fullClassName,regField(i),Type.INT, PUTFIELD)); + if(regLocalMapping[i] == 0) continue; + mg.set(p++,ALOAD_0); + mg.set(p++,GETFIELD,me.field(regField[i],Type.INT)); + mg.set(p++,ISTORE,regLocalMapping[i]); + + if(regLocalWritten[i]) { + mg.add(ALOAD_0); + mg.add(ILOAD,regLocalMapping[i]); + mg.add(PUTFIELD,me.field(regField[i],Type.INT)); } } } - - 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) regFieldR[reg-R]; - else if(reg >= F && reg < F+32) return regFieldF[ - else throw new IllegalArgumentException(""+reg); + + private void restoreChangedRegs() { + for(int i=0;i= F+0 && reg <= F+31 && singleFloat) { + mg.add(ALOAD_0); + mg.add(GETFIELD,me.field(regField[reg],Type.FLOAT)); + mg.add(INVOKESTATIC,Type.FLOAT_OBJECT.method("floatToIntBits",Type.INT,new Type[]{Type.FLOAT})); } else { - h = a(InstructionConstants.ALOAD_0); - a(fac.createFieldAccess(fullClassName,regField(reg),Type.INT, GETFIELD)); + mg.add(ALOAD_0); + mg.add(GETFIELD,me.field(regField[reg],Type.INT)); } return h; } @@ -1873,55 +1832,62 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const // This can push ONE or ZERO words to the stack. If it pushed one it returns true private boolean preSetReg(int reg) { - regField(reg); // just to check for validity preSetRegStack[preSetRegStackPos] = reg; preSetRegStackPos++; if(doLocal(reg)) { return false; } else { - a(InstructionConstants.ALOAD_0); + mg.add(ALOAD_0); return true; } } - private InstructionHandle setReg() { + private int setReg() { if(preSetRegStackPos==0) throw new RuntimeException("didn't do preSetReg"); preSetRegStackPos--; int reg = preSetRegStack[preSetRegStackPos]; - InstructionHandle h; + int h = mg.size(); if(doLocal(reg)) { - h = a(InstructionFactory.createStore(Type.INT,getLocalForReg(reg))); - regLocalWriteCount[reg]++; + mg.add(ISTORE,getLocalForReg(reg)); + regLocalWritten[reg] = true; + } else if(reg >= F+0 && reg <= F+31 && singleFloat) { + mg.add(INVOKESTATIC,Type.FLOAT_OBJECT.method("intBitsToFloat",Type.FLOAT,new Type[]{Type.INT})); + mg.add(PUTFIELD,me.field(regField[reg],Type.FLOAT)); } else { - h = a(fac.createFieldAccess(fullClassName,regField(reg),Type.INT, PUTFIELD)); + mg.add(PUTFIELD,me.field(regField[reg],Type.INT)); } return h; } - private InstructionHandle preSetPC() { return a(InstructionConstants.ALOAD_0); } - private InstructionHandle setPC() { return a(fac.createFieldAccess(fullClassName,"pc",Type.INT, PUTFIELD)); } + private int preSetPC() { return mg.add(ALOAD_0); } + private int setPC() { + return mg.add(PUTFIELD,me.field("pc",Type.INT)); + } - //unused - private InstructionHandle pushFloat(int reg) throws CompilationException { return pushDouble(reg,false); } //unused - private InstructionHandle pushDouble(int reg) throws CompilationException { return pushDouble(reg,true); } - private InstructionHandle pushDouble(int reg, boolean d) throws Exn { + private int pushFloat(int reg) throws Exn { return pushDouble(reg,false); } + private int pushDouble(int reg, boolean d) throws Exn { if(reg < F || reg >= F+32) throw new IllegalArgumentException(""+reg); - InstructionHandle h; + int h = mg.size(); if(d) { + if(singleFloat) throw new Exn("Double operations not supported when singleFloat is enabled"); if(reg == F+31) throw new Exn("Tried to use a double in f31"); - h = pushReg(reg+1); - a(InstructionConstants.I2L); - pushConst(32); - a(InstructionConstants.LSHL); + pushReg(reg+1); + mg.add(I2L); + mg.add(LDC,32); + mg.add(LSHL); pushReg(reg); - a(InstructionConstants.I2L); - pushConst(0xffffffffL); - a(InstructionConstants.LAND); - a(InstructionConstants.LOR); - //p("invokestatic java/lang/Double/longBitsToDouble(J)D"); - a(fac.createInvoke("java.lang.Double","longBitsToDouble",Type.DOUBLE,new Type[]{Type.LONG},INVOKESTATIC)); + mg.add(I2L); + mg.add(LDC,FFFFFFFF); + mg.add(LAND); + mg.add(LOR); + mg.add(INVOKESTATIC,Type.DOUBLE_OBJECT.method("longBitsToDouble",Type.DOUBLE,new Type[]{Type.LONG})); + } else if(singleFloat) { + mg.add(ALOAD_0); + mg.add(GETFIELD,me.field(regField[reg],Type.FLOAT)); } else { - h = pushReg(reg); - a(fac.createInvoke("java.lang.Float","intBitsToFloat",Type.FLOAT,new Type[]{Type.INT},INVOKESTATIC)); + pushReg(reg); + mg.add(INVOKESTATIC,Type.Class.instance("java.lang.Float").method("intBitsToFloat",Type.FLOAT,new Type[]{Type.INT})); } return h; } @@ -1930,71 +1896,49 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const private void preSetDouble(int reg) { preSetDouble(reg,true); } private void preSetDouble(int reg, boolean d) { preSetReg(reg); } - private InstructionHandle setFloat() throws Exn { return setDouble(false); } - private InstructionHandle setDouble() throws Exn { return setDouble(true); } - private InstructionHandle setDouble(boolean d) throws Exn { + private int setFloat() throws Exn { return setDouble(false); } + private int setDouble() throws Exn { return setDouble(true); } + private int setDouble(boolean d) throws Exn { int reg = preSetRegStack[preSetRegStackPos-1]; if(reg < F || reg >= F+32) throw new IllegalArgumentException(""+reg); - //p("invokestatic java/lang/Double/doubleToLongBits(D)J"); - InstructionHandle h; + int h = mg.size(); if(d) { + if(singleFloat) throw new Exn("Double operations not supported when singleFloat is enabled"); if(reg == F+31) throw new Exn("Tried to use a double in f31"); - h = a(fac.createInvoke("java.lang.Double","doubleToLongBits",Type.LONG,new Type[]{Type.DOUBLE},INVOKESTATIC)); - a(InstructionConstants.DUP2); - pushConst(32); - a(InstructionConstants.LUSHR); - a(InstructionConstants.L2I); + mg.add(INVOKESTATIC,Type.DOUBLE_OBJECT.method("doubleToLongBits",Type.LONG,new Type[]{Type.DOUBLE})); + mg.add(DUP2); + mg.add(LDC,32); + mg.add(LUSHR); + mg.add(L2I); if(preSetReg(reg+1)) - a(InstructionConstants.SWAP); + mg.add(SWAP); setReg(); - a(InstructionConstants.L2I); + mg.add(L2I); setReg(); // preSetReg was already done for this by preSetDouble + } else if(singleFloat) { + // HACK: Clean this up + preSetRegStackPos--; + mg.add(PUTFIELD,me.field(regField[reg],Type.FLOAT)); } else { - h = a(fac.createInvoke("java.lang.Float","floatToRawIntBits",Type.INT,new Type[]{Type.FLOAT},INVOKESTATIC)); + //h = a(fac.createInvoke("java.lang.Float","floatToRawIntBits",Type.INT,new Type[]{Type.FLOAT},INVOKESTATIC)); + mg.add(INVOKESTATIC,Type.FLOAT_OBJECT.method("floatToRawIntBits",Type.INT,new Type[]{Type.FLOAT})); setReg(); } return h; } - - private Hashtable intCache = new Hashtable(); - private InstructionHandle pushConst(int n) { - 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); - case 3: return a(InstructionConstants.ICONST_3); - case 4: return a(InstructionConstants.ICONST_4); - case 5: return a(InstructionConstants.ICONST_5); - default: return null; - } - } else if(n >= -128 && n <= 127) { - return a(new BIPUSH((byte) n)); - } else if(n >= -32768 && n <= 32767) { - return a(new SIPUSH((short) n)); - } else { - return a(new PUSH(cp,n)); - } - } - - private InstructionHandle pushConst(long l) { return a(new PUSH(cp,l)); } - private InstructionHandle pushConst(float f) { return a(new PUSH(cp,f)); } - private InstructionHandle pushConst(double d) { return a(new PUSH(cp,d)); } - - private void pushTmp() { a(InstructionConstants.ILOAD_1); } - private void setTmp() { a(InstructionConstants.ISTORE_1); } + private void pushTmp() { mg.add(ILOAD_1); } + private void setTmp() { mg.add(ISTORE_1); } private void addiu(int reg, int offset) { if(reg != R+0 && offset != 0) { pushReg(reg); - pushConst(offset); - a(InstructionConstants.IADD); + mg.add(LDC,offset); + mg.add(IADD); } else if(reg != R+0) { pushReg(reg); } else { - pushConst(offset); + mg.add(LDC,offset); } } private int memWriteStage; @@ -2002,11 +1946,11 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const if(memWriteStage!=0) throw new Error("pending preMemWrite1/2"); memWriteStage=1; if(onePage) - a(InstructionConstants.ALOAD_2); + mg.add(ALOAD_2); else if(fastMem) - a(InstructionFactory.createLoad(Type.OBJECT,3)); + mg.add(ALOAD,3); else - a(InstructionConstants.ALOAD_0); + mg.add(ALOAD_0); } private void preMemWrite2(int reg, int offset) { @@ -2020,29 +1964,30 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const memWriteStage=2; if(nullPointerCheck) { - a(InstructionConstants.DUP); - a(InstructionConstants.ALOAD_0); - a(InstructionConstants.SWAP); - a(fac.createInvoke(fullClassName,"nullPointerCheck",Type.VOID,new Type[]{Type.INT},INVOKEVIRTUAL)); + mg.add(DUP); + mg.add(ALOAD_0); + mg.add(SWAP); + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime.nullPointerCheck + mg.add(INVOKEVIRTUAL,me.method("nullPointerCheck",Type.VOID,new Type[]{Type.INT})); } if(onePage) { - a(InstructionConstants.ICONST_2); - a(InstructionConstants.IUSHR); + mg.add(ICONST_2); + mg.add(IUSHR); } else if(fastMem) { if(!addrInTmp) - a(InstructionConstants.DUP_X1); - pushConst(pageShift); - a(InstructionConstants.IUSHR); - a(InstructionConstants.AALOAD); + mg.add(DUP_X1); + mg.add(LDC,pageShift); + mg.add(IUSHR); + mg.add(AALOAD); if(addrInTmp) pushTmp(); else - a(InstructionConstants.SWAP); - a(InstructionConstants.ICONST_2); - a(InstructionConstants.IUSHR); - pushConst((pageSize>>2)-1); - a(InstructionConstants.IAND); + mg.add(SWAP); + mg.add(ICONST_2); + mg.add(IUSHR); + mg.add(LDC,(pageSize>>2)-1); + mg.add(IAND); } } @@ -2052,11 +1997,12 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const memWriteStage=0; if(onePage) { - a(InstructionConstants.IASTORE); + mg.add(IASTORE); } else if(fastMem) { - a(InstructionConstants.IASTORE); + mg.add(IASTORE); } else { - a(fac.createInvoke(fullClassName,"unsafeMemWrite",Type.VOID,new Type[]{Type.INT,Type.INT},INVOKEVIRTUAL)); + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime.unsafeMemWrite + mg.add(INVOKEVIRTUAL,me.method("unsafeMemWrite",Type.VOID,new Type[]{Type.INT,Type.INT})); } } @@ -2077,11 +2023,11 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const didPreMemRead = true; preMemReadDoPreWrite = preWrite; if(onePage) - a(InstructionConstants.ALOAD_2); + mg.add(ALOAD_2); else if(fastMem) - a(InstructionFactory.createLoad(Type.OBJECT,preWrite ? 3 : 2)); + mg.add(ALOAD,preWrite ? 3 : 2); else - a(InstructionConstants.ALOAD_0); + mg.add(ALOAD_0); } // memRead pops an address off the stack, reads the value at that addr, and pushed the value // preMemRead MUST be called BEFORE the addresses is pushed @@ -2094,43 +2040,41 @@ public class ClassFileCompiler extends Compiler implements org.apache.bcel.Const memWriteStage=2; if(nullPointerCheck) { - a(InstructionConstants.DUP); - a(InstructionConstants.ALOAD_0); - a(InstructionConstants.SWAP); - a(fac.createInvoke(fullClassName,"nullPointerCheck",Type.VOID,new Type[]{Type.INT},INVOKEVIRTUAL)); + mg.add(DUP); + mg.add(ALOAD_0); + mg.add(SWAP); + mg.add(INVOKEVIRTUAL,me.method("nullPointerCheck",Type.VOID,new Type[]{Type.INT})); } if(onePage) { - // p(target + "= page[(" + addr + ")>>>2];"); - a(InstructionConstants.ICONST_2); - a(InstructionConstants.IUSHR); + mg.add(ICONST_2); + mg.add(IUSHR); if(preMemReadDoPreWrite) - a(InstructionConstants.DUP2); - a(InstructionConstants.IALOAD); + mg.add(DUP2); + mg.add(IALOAD); } else if(fastMem) { - //p(target + " = readPages[("+addr+")>>>"+pageShift+"][(("+addr+")>>>2)&"+toHex((pageSize>>2)-1)+"];"); - if(!addrInTmp) - a(InstructionConstants.DUP_X1); - pushConst(pageShift); - a(InstructionConstants.IUSHR); - a(InstructionConstants.AALOAD); + mg.add(DUP_X1); + mg.add(LDC,pageShift); + mg.add(IUSHR); + mg.add(AALOAD); if(addrInTmp) pushTmp(); else - a(InstructionConstants.SWAP); - a(InstructionConstants.ICONST_2); - a(InstructionConstants.IUSHR); - pushConst((pageSize>>2)-1); - a(InstructionConstants.IAND); + mg.add(SWAP); + mg.add(ICONST_2); + mg.add(IUSHR); + mg.add(LDC,(pageSize>>2)-1); + mg.add(IAND); if(preMemReadDoPreWrite) - a(InstructionConstants.DUP2); - a(InstructionConstants.IALOAD); + mg.add(DUP2); + mg.add(IALOAD); } else { if(preMemReadDoPreWrite) - a(InstructionConstants.DUP2); - a(fac.createInvoke(fullClassName,"unsafeMemWrite",Type.INT,new Type[]{Type.INT},INVOKEVIRTUAL)); + mg.add(DUP2); + // GCCLASS_HINT: org.ibex.nestedvm.RuntimeCompiler.compile org.ibex.nestedvm.Runtime.unsafeMemRead + mg.add(INVOKEVIRTUAL,me.method("unsafeMemRead",Type.INT,new Type[]{Type.INT})); } }