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
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
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));
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();
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)) {
// 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());
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;
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);
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();
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;
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;
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;
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];
return regLocalMapping[reg];
}
-
- private int loadsStart;
private void fixupRegsStart() {
for(int i=0;i<REG_COUNT;i++)
regLocalMapping[i] = regLocalReadCount[i] = regLocalWriteCount[i] = 0;
}
}
- 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) {
}
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);
}