X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=src%2Forg%2Fxwt%2Fmips%2FCompiler.java;h=ff6369e3d748def931f0395e3be3870c7d757973;hb=0b0673bbc7f06c5d5418d5ab7ad5961a464e2de0;hp=21fe7e5e80b1da2e075ead00d87c81421762a90b;hpb=7f5df8070a5551fe66abd11a589677e285ca62f8;p=org.ibex.core.git diff --git a/src/org/xwt/mips/Compiler.java b/src/org/xwt/mips/Compiler.java index 21fe7e5..ff6369e 100644 --- a/src/org/xwt/mips/Compiler.java +++ b/src/org/xwt/mips/Compiler.java @@ -4,29 +4,58 @@ package org.xwt.mips; import java.util.*; import java.io.*; -// FIXME: lb/sb/sh/lh need not be word aligned -// FIXME: memory accesses aren't handling sign-extending properly -// FIXME: probably have to implement nonaligned access -// FIXME: implement malloc() -// FIXME: implement an ELF parser based on RandomAccessFile // FEATURE: progress indicator -// FEATURE: support n32 abi (passes more arguments in registers) -// FEATURE: trap on arithmetic overflows -// FEATURE: FPU -// FEATURE: we always know the value of the pc register; we should emit it as a literal when it appears in computations -// FEATURE: emit bytecode rather than .java code (for on-the-fly classloading without javac present in "real" JVMs) +// FEATURE: emit bytecode rather than .java code (for on-the-fly classloading without javac present in "real" JVMs -/** reads a fully linked MIPS ELF binary image on stdin; writes a .java file on stdout */ -public class Compiler { +public class Compiler implements Registers { - static String runs = ""; - static int last_emit = -1; - static DataInputStream dis; - public static void main(String[] s) throws IOException { + private static StringBuffer runs = new StringBuffer(); + private static StringBuffer inits = new StringBuffer(); + + private static PrintStream out = System.out; + + private static int indent; + private static String indents[] = new String[16]; + static { String s=""; for(int i=0;i "); - System.exit(-1); + System.exit(1); } String packageName = null; @@ -35,160 +64,360 @@ public class Compiler { packageName = s[0].substring(0, s[0].lastIndexOf('.')); className = s[0].substring(s[0].lastIndexOf('.') + 1); } - - System.out.println(prefix + "// This file was generated by MipsToJava"); - if (packageName != null) System.out.println(prefix + "package " + packageName + ";"); - System.out.println(prefix + "public class " + className + " extends org.xwt.mips.VM {"); - System.out.println(prefix + ""); - System.out.println(prefix + " public " + className + "() { }"); - System.out.println(prefix + ""); - System.out.println(prefix + " // program counter"); - System.out.println(prefix + " int pc = 0;"); - System.out.println(prefix + ""); - System.out.println(prefix + " // temporary"); - System.out.println(prefix + " int tmp = 0;"); - System.out.println(prefix + ""); - System.out.println(prefix + " // MIPS multiply/divide subsystem; 64-bit result"); - System.out.println(prefix + " long hilo = 0;"); - System.out.println(prefix + ""); - System.out.println(prefix + " // General Purpose registers"); - System.out.println(prefix + " final int r0 = 0;"); - System.out.println(prefix + " int r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0,"); - System.out.println(prefix + " r8 = 0, r9 = 0, r10 = 0, r11 = 0, r12 = 0, r13 = 0, r14 = 0, r15 = 0,"); - System.out.println(prefix + " r16 = 0, r17 = 0, r18 = 0, r19 = 0, r20 = 0, r21 = 0, r22 = 0, r23 = 0,"); - System.out.println(prefix + " r24 = 0, r25 = 0, r26 = 0, r27 = 0, r28 = 0, r29 = 0, r30 = 0, r31 = 0;"); - System.out.println(prefix + ""); - - ELF elf = new ELF(new RandomAccessFile(args[1], "r")); + + ELF elf = new ELF(s[1]); if(elf.header.type != ELF.ELFHeader.ET_EXEC) throw new IOException("Binary is not an executable"); if(elf.header.machine != ELF.ELFHeader.EM_MIPS) throw new IOException("Binary is not for the MIPS I Architecture"); - ELF.PHeader[] pheaders = elf.pheaders; - - int[][] readPages = new int[TOTAL_PAGES][]; - int[][] writePages = new int[TOTAL_PAGES][]; - for(int i=0; i= (brk<> PAGE_SHIFT; - // FIXME: set memsize, serialize readPages/writePages - for(int j=0;j>> PAGE_SHIFT; - if(readPages[page] == null) readPages[page] = new int[PAGE_WORDS]; - if(ph.writable()) writePages[page] = readPages[page]; + p("// This file was generated by MipsToJava"); + if (packageName != null) p("package " + packageName + ";"); + p("public class " + className + " extends Runtime {"); + p(""); + p(" // program counter"); + p(" private int pc = 0;"); + if(debugCompiler) + p(" private int lastPC = 0;"); + p(""); + p(" // General Purpose registers"); + p(" private final static int r0 = 0;"); + p(" int r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0,"); + p(" r8 = 0, r9 = 0, r10 = 0, r11 = 0, r12 = 0, r13 = 0, r14 = 0, r15 = 0,"); + p(" r16 = 0, r17 = 0, r18 = 0, r19 = 0, r20 = 0, r21 = 0, r22 = 0, r23 = 0,"); + p(" r24 = 0, r25 = 0, r26 = 0, r27 = 0, r28 = 0, r29 = 0, r30 = 0, r31 = 0,"); + p(" hi = 0, lo = 0;"); + p(" // FP registers"); + p(" private int f0 = 0, f1 = 0, f2 = 0, f3 = 0, f4 = 0, f5 = 0, f6 = 0, f7 = 0,"); + p(" f8 = 0, f9 = 0, f10 = 0, f11 = 0, f12 = 0, f13 = 0, f14 = 0, f15 = 0,"); + p(" f16 = 0, f17 = 0, f18 = 0, f19 = 0, f20 = 0, f21 = 0, f22 = 0, f23 = 0,"); + p(" f24 = 0, f25 = 0, f26 = 0, f27 = 0, f28 = 0, f29 = 0, f30 = 0, f31 = 0;"); + p(" // FP Control Register"); + p(" private int fcsr = 0;"); + p(""); + indent++; + // These should all be inlind by javac + p("private final void setFC(boolean b) { fcsr = (fcsr&~0x800000) | (b ? 0x800000 : 0x000000); }"); + p("private final int roundingMode() { return fcsr & 3; /* bits 0-1 */ }"); + indent--; + + Set jumpableAddresses = null; + if(pruneCases) { + // Find all possible branches + jumpableAddresses = new HashSet(); + + jumpableAddresses.add(new Integer(elf.header.entry)); + + ELF.SHeader text = elf.sectionWithName(".text"); + if(text == null) throw new Error("No .text segment"); + findBranchesInText(text.addr,new DataInputStream(text.getInputStream()),text.size,jumpableAddresses); + + findBranchesInSymtab(elf.getSymtab(),jumpableAddresses); + + for(int i=0;i>> PAGE_SHIFT][(addr >>> 2)&(PAGE_WORDS-1)] = dis.readInt(); - addr+=4; - filesize-=4; - } while(filesize > 0); - dis.close(); + } + + // Generate main body functions + int highestAddr = 0; + indent=1; + for(int i=0;i>> PAGE_SHIFT;"); + p(" state = INITIALIZED;"); + p(" }"); + p(""); + p(); + p(" public static void main(String[] javaArgs) throws Exception {"); + p(" String[] args = new String[javaArgs.length+1];"); + p(" System.arraycopy(javaArgs,0,args,1,javaArgs.length);"); + p(" args[0] = \"" + className + "\";"); + p(" " + className + " me = new " + className + "();"); + p(" // User data"); + p(" int addr = me.sbrk(PAGE_SIZE);"); + p(" for(int i=0;i<10;i++) {"); + p(" String s = \"User Info item: \" + (i+1) + \"\\0\";"); + p(" byte[] b = s.getBytes(\"US-ASCII\");"); + p(" me.copyout(b,addr,b.length);"); + p(" me.setUserInfo(i,addr);"); + p(" addr += b.length;"); + p(" }"); + p(" // End user data"); + p(" int status = me.run(args);"); + p(" System.err.println(\"Exit status: \" + status);"); + p(" System.exit(status);"); + p(" }"); + p(); + p(" protected void _start(int pc) {"); + p(" // set the stack pointer"); + p(" r26 = STUFF_BASE;"); + p(" r27 = PAGE_SIZE;"); + p(" r29 = INITIAL_SP;"); + p(" // set the \"return address\" from _start to point at the \"magic exit address\" (0xdeadbeef)"); + p(" r31 = 0xdeadbeef;"); + p(" this.pc = pc;"); + p(" }"); - // cap off the last method - emit(-1, -1, dis); - - System.out.println(prefix + " protected int state = INITIALIZED;"); - System.out.println(prefix + " protected int brk = " + brk + ";"); + p(); + p(" protected void _execute() throws ExecutionException { trampoline(); }"); + p(); + p(" private final void trampoline() throws ExecutionException {"); + p(" boolean finished = false;"); + p(" while(!finished) {"); + p(" switch(this.pc & " + toHex(~(MAX_BYTES_PER_METHOD-1)) + ") {"); + p(runs.toString()); + p(" default: throw new Error(\"invalid address 0x\" + Long.toString(this.pc&0xffffffffL,16));"); + p(" }"); + p(" }"); + p(" }"); + p("}"); + } - System.out.println(); - System.out.println(prefix + " public static void main(String[] s) { new " + className + "()._start(entryPoint); }"); - System.out.println(); - System.out.println(prefix + " protected int entryPoint = " + elf.header.entry + ";"); - System.out.println(); - System.out.println(prefix + " protected void _start(int pc) {"); - System.out.println(); - System.out.println(prefix + " // set the stack pointer"); - System.out.println(prefix + " r29 = INITIAL_SP;"); - System.out.println(); - System.out.println(prefix + " // set the \"return address\" from _start to point at the \"magic exit address\" (0xdeadbeef)"); - System.out.println(prefix + " r31 = 0xdeadbeef;"); - System.out.println(); - System.out.println(prefix + " // read in the .data segment"); - System.out.println(prefix + " //initData();"); - System.out.println(); - System.out.println(prefix + " trampoline(pc);"); - System.out.println(); - System.out.println(prefix + " }"); + private static int startOfMethod = 0; + private static int endOfMethod = 0; + + private static void startMethod(int addr) { + addr &= ~(MAX_BYTES_PER_METHOD-1); + endOfMethod = addr + MAX_BYTES_PER_METHOD; + String methodName = "run_" + Long.toString(addr & 0xffffffffL, 16); + runs.append(indents[4] + "case " + toHex(addr) + ": finished = !" + methodName + "(); break;\n"); + p("private final boolean " + methodName + "() throws ExecutionException { /"+"* " + toHex(addr) + " - " + toHex(endOfMethod) + " *" + "/"); + indent++; + p("int addr, tmp;"); + for(int i=0;inumbytes from the stream, emitting case blocks starting at vaddr ofs */ - static void emit(int vaddr, int numbytes, DataInputStream dis) throws IOException { - if ((vaddr == -1 && numbytes == -1) || (last_emit != -1 && ((last_emit & 0xffffff00) != (vaddr & 0xffffff00)))) { - System.out.println(prefix + " case 0x" + Long.toString((last_emit & 0xffffffffL) + 0x1000, 16) + ": return;"); - System.out.println(prefix + " default: throw new Error(\"invalid address 0x\" + Long.toString(pc&0xffffffffL,16));"); - System.out.println(prefix + " }"); - System.out.println(prefix + " }"); - if (vaddr == -1 && numbytes == -1) return; + for(int i=0;i= endOfMethod) { endMethod(); startMethod(addr); } + if(jumpableAddresses==null || addr == startOfMethod || jumpableAddresses.contains(new Integer(addr))) { + p("case " + toHex(addr) + ":"); + unreachable = false; + } else if(unreachable) { + continue; + } else if(debugCompiler) { + p("/" + "* pc = " + toHex(addr) + "*" + "/"); + } + indent++; + emitInstruction(addr,insn,nextInsn); + indent--; } - if (last_emit == -1 || ((last_emit & 0xffffff00) != (vaddr & 0xffffff00))) { - System.out.println(""); - System.out.println(prefix + " private void run_" + Long.toString(vaddr & 0xffffff00L,16) + "() {"); - runs += " case 0x" + Long.toString(vaddr & 0xffffff00L,16) + - ": run_" + Long.toString(vaddr & 0xffffff00L,16) + "(); continue;\n"; - System.out.println(prefix + " switch(pc) {"); + nextEmitTextAddr = addr; + dis.close(); + } + + private static int initDataCount = 0; + private static void emitData(int addr, DataInputStream dis, int size, boolean readOnly) throws CompilationException,IOException { + if((addr&3)!=0 || (size&3)!=0) throw new CompilationException("Section on weird boundaries"); + int count = size/4; + String varname = "_data" + (++initDataCount); + p("private final static int[] " + varname + " = {"); + indent++; + for(int i=0;i>> 26) & 0xff; + int rs = (insn >>> 21) & 0x1f; + int rt = (insn >>> 16) & 0x1f; + int signedImmediate = (insn << 16) >> 16; + int branchTarget = signedImmediate; + int jumpTarget = (insn & 0x03ffffff); + int subcode = insn & 0x3f; + + switch(op) { + case 0: + switch(subcode) { + case 9: // JALR + if(jumps.add(new Integer(pc+8))) n++; // return address + break; + case 12: // SYSCALL + if(jumps.add(new Integer(pc+4))) n++; + break; + } + break; + case 1: + switch(rt) { + case 16: // BLTZAL + case 17: // BGTZAL + if(jumps.add(new Integer(pc+8))) n++; // return address + // fall through + case 0: // BLTZ + case 1: // BGEZ + if(jumps.add(new Integer(pc+branchTarget*4+4))) n++; + break; + } + break; + case 3: // JAL + if(jumps.add(new Integer(pc+8))) n++; // return address + // fall through + case 2: // J + if(jumps.add(new Integer((pc&0xf0000000)|(jumpTarget << 2)))) n++; + break; + case 4: // BEQ + case 5: // BNE + case 6: // BLEZ + case 7: // BGTZ + if(jumps.add(new Integer(pc+branchTarget*4+4))) n++; + break; + case 17: // FPU Instructions + switch(rs) { + case 8: // BC1F, BC1T + if(jumps.add(new Integer(pc+branchTarget*4+4))) n++; + break; + } + break; + } + } + dis.close(); + if(printStats) System.err.println("Found " + n + " additional possible branch targets in Text segment"); + } + + private static void findBranchesInData(DataInputStream dis, int size, Set jumps, int textStart, int textEnd) throws IOException { + int count = size/4; + int n=0; + for(int i=0;i= textStart && word < textEnd) { + if(jumps.add(new Integer(word))) n++; + } + } + dis.close(); + if(n>0 && printStats) System.err.println("Found " + n + " additional possible branch targets in Data segment"); + } + + private static boolean unreachable = false; + + private static void emitInstruction(int pc, int insn, int nextInsn) throws IOException,CompilationException { + if(insn == -1) throw new Error("insn is -1"); + int op = (insn >>> 26) & 0xff; // bits 26-31 int rs = (insn >>> 21) & 0x1f; // bits 21-25 int rt = (insn >>> 16) & 0x1f; // bits 16-20 @@ -206,99 +435,125 @@ public class Compiler { int tmp, addr; // temporaries + //if(pc%64==0) p("System.err.println(\"Executing: " + toHex(pc) + "\");"); + //p("/" + "*" + (pc == -1 ? "Delay Slot" : toHex(pc)) + " *" + "/ "); + if(pc==-1) p("/" + "* Next insn is delay slot *" + "/ "); + switch(op) { case 0: { switch(subcode) { case 0: // SLL - if(insn == 0) break; - emit(pc, "r"+rd+" = r"+rt+" << "+shamt+";"); + if(insn == 0) + p("/* NOOP */"); + else + p( "r"+rd+" = r"+rt+" << "+shamt+";"); break; case 2: // SRL - emit(pc, "r"+rd+" = r"+rt+" >>> "+shamt+";"); + p( "r"+rd+" = r"+rt+" >>> "+shamt+";"); break; case 3: // SRA - emit(pc, "r"+rd+" = r"+rt+" >> "+shamt+";"); + p( "r"+rd+" = r"+rt+" >> "+shamt+";"); break; - // FIXME: Do we need % 32 on the r"+rs+" ? case 4: // SLLV - emit(pc, "r"+rd+" = r"+rt+" << r"+rs+";"); + p( "r"+rd+" = r"+rt+" << (r"+rs+"&0x1f);"); break; case 6: // SRLV - emit(pc, "r"+rd+" = r"+rt+" >>> r"+rs+";"); + p( "r"+rd+" = r"+rt+" >>> (r"+rs+"&0x1f);"); break; case 7: // SRAV - emit(pc, "r"+rd+" = r"+rt+" >> r"+rs+";"); + p( "r"+rd+" = r"+rt+" >> (r"+rs+"&0x1f);"); break; case 8: // JR - emit(pc, "{ int tmp = r"+rs+"; pc += 4; nextPC = tmp; }"); - continue OUTER; + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + emitInstruction(-1,nextInsn,-1); + if(debugCompiler) p("lastPC = " + toHex(pc) + ";"); + p("pc=r" + rs + ";"); + leaveMethod(); + unreachable = true; + break; case 9: // JALR - emit(pc, "{ int tmp = r"+rs+"; pc += 4; r"+rd+" = pc+4; nextPC = tmp; }"); - continue OUTER; + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + emitInstruction(-1,nextInsn,-1); + if(debugCompiler) p("lastPC = " + toHex(pc) + ";"); + p("pc=r" + rs + ";"); + p("r" + RA + "=" + toHex(pc+8 /*skip this insn and delay slot*/) + ";"); + leaveMethod(); + unreachable = true; + break; case 12: // SYSCALL - emit(pc, "r"+V0+" = syscall(r"+V0+",r"+A0+",r"+A1+",r"+A2+",r"+A3+"); " + - "if (state != RUNNING) { this.nextPC = nextPC; return; }"); + p( "r"+V0+" = syscall(r"+V0+",r"+A0+",r"+A1+",r"+A2+",r"+A3+");"); + p("if (state != RUNNING) {"); + indent++; + p("pc = " + toHex(pc+4) + ";"); + leaveMethod(false); + indent--; + p("}"); break; case 13: // BREAK - emit(pc, "throw new EmulationException(\"Break\")"); + p( "throw new ExecutionException(\"Break\");"); break; case 16: // MFHI - emit(pc, "r"+rd+" = hi;"); + p( "r"+rd+" = hi;"); break; case 17: // MTHI - emit(pc, "hi = r"+rs+";"); + p( "hi = r"+rs+";"); break; case 18: // MFLO - emit(pc, "r"+rd+" = lo;"); + p( "r"+rd+" = lo;"); break; case 19: // MTLO - emit(pc, "lo = r"+rs+";"); + p( "lo = r"+rs+";"); break; case 24: // MULT - emit(pc, "long hilo = (long)(r"+rs+") * ((long)r"+rt+"); " + + p( "{ long hilo = (long)(r"+rs+") * ((long)r"+rt+"); " + "hi = (int) (hilo >>> 32); " + - "lo = (int) hilo;"); + "lo = (int) hilo; }"); break; case 25: // MULTU - emit(pc, "long hilo = (r"+rs+" & 0xffffffffL) * (r"+rt+" & 0xffffffffL); " + + p( "{ long hilo = (r"+rs+" & 0xffffffffL) * (r"+rt+" & 0xffffffffL); " + "hi = (int) (hilo >>> 32); " + - "lo = (int) hilo;"); + "lo = (int) hilo; } "); + break; case 26: // DIV - emit(pc, "hi = r"+rs+"%r"+rt+"; lo = r"+rs+"/r"+rt+";"); + p( "hi = r"+rs+"%r"+rt+"; lo = r"+rs+"/r"+rt+";"); break; case 27: // DIVU - emit(pc, "hi = (int)((r"+rs+" & 0xffffffffL) % (r"+rt+" & 0xffffffffL)); " + + p( "hi = (int)((r"+rs+" & 0xffffffffL) % (r"+rt+" & 0xffffffffL)); " + "lo = (int)((r"+rs+" & 0xffffffffL) / (r"+rt+" & 0xffffffffL));"); break; case 32: // ADD - emit(pc, "r"+rd+" = r"+rs+" + r"+rt+";"); // FIXME: Trap on overflow - break; + throw new CompilationException("ADD (add with oveflow trap) not suported"); + /*This must trap on overflow + p( "r"+rd+" = r"+rs+" + r"+rt+";"); + break;*/ case 33: // ADDU - emit(pc, "r"+rd+" = r"+rs+" + r"+rt+";"); + p( "r"+rd+" = r"+rs+" + r"+rt+";"); break; case 34: // SUB - emit(pc, "r"+rd+" = r"+rs+" - r"+rt+";"); // FIXME: Trap on overflow - break; + throw new CompilationException("SUB (add with oveflow trap) not suported"); + /*This must trap on overflow + p( "r"+rd+" = r"+rs+" - r"+rt+";"); + break;*/ case 35: // SUBU - emit(pc, "r"+rd+" = r"+rs+" - r"+rt+";"); + p( "r"+rd+" = r"+rs+" - r"+rt+";"); break; case 36: // AND - emit(pc, "r"+rd+" = r"+rs+" & r"+rt+";"); + p( "r"+rd+" = r"+rs+" & r"+rt+";"); break; case 37: // OR - emit(pc, "r"+rd+" = r"+rs+" | r"+rt+";"); + p( "r"+rd+" = r"+rs+" | r"+rt+";"); break; case 38: // XOR - emit(pc, "r"+rd+" = r"+rs+" ^ r"+rt+";"); + p( "r"+rd+" = r"+rs+" ^ r"+rt+";"); break; case 39: // NOR - emit(pc, "r"+rd+" = ~(r"+rs+" | r"+rt+");"); + p( "r"+rd+" = ~(r"+rs+" | r"+rt+");"); break; case 42: // SLT - emit(pc, "r"+rd+" = r"+rs+" < r"+rt+" ? 1 : 0;"); + p( "r"+rd+" = r"+rs+" < r"+rt+" ? 1 : 0;"); break; case 43: // SLTU - emit(pc, "r"+rd+" = ((r"+rs+" & 0xffffffffL) < (r"+rt+" & 0xffffffffL)) ? 1 : 0;"); + p( "r"+rd+" = ((r"+rs+" & 0xffffffffL) < (r"+rt+" & 0xffffffffL)) ? 1 : 0;"); break; default: throw new RuntimeException("Illegal instruction 0/" + subcode); @@ -308,411 +563,460 @@ public class Compiler { case 1: { switch(rt) { case 0: // BLTZ - emit(pc, "if (r"+rs+"<0) { pc += 4; int tmp = pc + "+ - branchTarget+"*4; nextPC = tmp; }"); + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " < 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); break; case 1: // BGEZ - emit(pc, "if (r"+rs+">=0) { pc += 4; int tmp = pc + "+ - branchTarget+"*4; nextPC = tmp; }"); + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " >= 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); break; case 16: // BLTZAL - emit(pc, "if(r"+rs+" < 0) { pc += 4; r"+RA+" = pc+4; int tmp = pc + "+ - branchTarget+"*4; nextPC = tmp; }"); + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " < 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + p("r" + RA + "=" + toHex(pc+8 /*skip this insn and delay slot*/) + ";"); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); break; case 17: // BGEZAL - emit(pc, "if(r"+rs+" >= 0) { pc += 4; r"+RA+" = pc+4; int tmp = pc + "+ - branchTarget+"*4; nextPC = tmp; }"); + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " >= 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + p("r" + RA + "=" + toHex(pc+8 /*skip this insn and delay slot*/) + ";"); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); break; default: - throw new RuntimeException("Illegal Instruction"); + throw new RuntimeException("Illegal Instruction 1/" + rt); } break; } case 2: { // J - emit(pc, "int tmp = (pc&0xf0000000) | ("+jumpTarget+" << 2); pc+=4; nextPC = tmp;"); + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + emitInstruction(-1,nextInsn,-1); + branch(pc,(pc&0xf0000000)|(jumpTarget << 2)); + unreachable = true; break; } case 3: { // JAL - emit(pc, "int tmp = (pc&0xf0000000) | ("+jumpTarget+" << 2); pc+=4; r"+RA+ - " = pc+4; nextPC = tmp;"); + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + emitInstruction(-1,nextInsn,-1); + p("r" + RA + "=" + toHex(pc+8 /*skip this insn and delay slot*/) + ";"); + branch(pc, (pc&0xf0000000)|(jumpTarget << 2)); + unreachable = true; break; } case 4: // BEQ - emit(pc, "if(r"+rs+" == r"+rt+") { pc += 4; int tmp = pc + "+ - branchTarget+"*4; nextPC = tmp; }"); + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("// BEQ"); + p("if(r" + rs + " == r" + rt + ") {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); break; - case 5: // BNE - emit(pc, "if(r"+rs+" != r"+rt+") { pc += 4; int tmp = pc + "+ - branchTarget+"*4; nextPC = tmp; }"); + case 5: // BNE + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " != r" + rt + ") {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); break; case 6: //BLEZ - emit(pc, "if(r"+rs+" <= 0) { pc += 4; int tmp = pc + "+ - branchTarget+"*4; nextPC = tmp; ;"); + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " <= 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); break; case 7: //BGTZ - emit(pc, "if(r"+rs+" > 0) { pc += 4; int tmp = pc + "+branchTarget+"*4; nextPC = tmp; }"); + if(pc == -1) throw new Error("pc modifying insn in delay slot"); + p("if(r" + rs + " > 0) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); break; case 8: // ADDI - emit(pc, "r"+rt+" = r"+rs+" + "+signedImmediate +";"); + p( "r"+rt+" = r"+rs+" + "+signedImmediate +";"); break; case 9: // ADDIU - emit(pc, "r"+rt+" = r"+rs+" + "+signedImmediate+";"); + p( "r"+rt+" = r"+rs+" + "+signedImmediate+";"); break; case 10: // SLTI - emit(pc, "r"+rt+" = r"+rs+" < "+signedImmediate+" ? 1 : 0;"); + p( "r"+rt+" = r"+rs+" < "+signedImmediate+" ? 1 : 0;"); break; case 11: // SLTIU - emit(pc, "r"+rt+" = (r"+rs+"&0xffffffffL) < ("+unsignedImmediate+"&0xffffffffL) ? 1 : 0;"); + p( "r"+rt+" = (r"+rs+"&0xffffffffL) < ("+unsignedImmediate+"&0xffffffffL) ? 1 : 0;"); break; case 12: // ANDI - emit(pc, "r"+rt+" = r"+rs+" & "+unsignedImmediate+";"); + p( "r"+rt+" = r"+rs+" & "+unsignedImmediate+";"); break; case 13: // ORI - emit(pc, "r"+rt+" = r"+rs+" | "+unsignedImmediate+";"); + p( "r"+rt+" = r"+rs+" | "+unsignedImmediate+";"); break; case 14: // XORI - emit(pc, "r"+rt+" = r"+rs+" ^ "+unsignedImmediate+";"); + p( "r"+rt+" = r"+rs+" ^ "+unsignedImmediate+";"); break; case 15: // LUI - emit(pc, "r"+rt+" = "+unsignedImmediate+" << 16;"); + p( "r"+rt+" = "+unsignedImmediate+" << 16;"); break; case 16: - throw new RuntimeException("TLB/Exception support not implemented"); + throw new CompilationException("TLB/Exception support not implemented"); case 17: { // FPU switch(rs) { case 0: // MFC.1 - emit(pc, "r"+rt+" = f"+rd); + p( "r"+rt+" = f"+rd+";"); break; case 2: // CFC.1 - if(fs != 31) throw new EmulationException("FCR " + fs + " unavailable"); - emit(pc, "r"+rt+" = fcsr;"); + if(fs != 31) throw new CompilationException("FCR " + fs + " unavailable"); + p( "r"+rt+" = fcsr;"); break; case 4: // MTC.1 - emit(pc, "f"+rd+" = r"+rt+";"); + p( "f"+rd+" = r"+rt+";"); break; case 6: // CTC.1 - if(fs != 31) throw new EmulationException("FCR " + fs + " unavailable"); - emit(pc, "fcsr = r"+rt+"; ;") - break; - case 8: // BC1F, BC1T - emit(pc, "if(((fcsr&0x800000)!=0) == (((insn>>>16)&1)!=0)) {"+ - " pc += 4; int tmp = pc + "+branchTarget+"*4; nextPC = tmp; ;")} + if(fs != 31) throw new CompilationException("FCR " + fs + " unavailable"); + p( "fcsr = r"+rt+";"); + break; + case 8: {// BC1F, BC1T + tmp = (insn>>>16)&1; + p("//BC1F, BC1T"); + p("if(((fcsr&0x800000)!=0) == (" + tmp + "!=0)) {"); + indent++; + emitInstruction(-1,nextInsn,-1); + branch(pc,pc+branchTarget*4+4); + indent--; + p("}"); break; - case 16: { // Single + } + case 16: { // Single switch(subcode) { case 0: // ADD.S - emit(pc, setFloat(fd,getFloat(fs)+"+"+getFloat(ft))); + p(setFloat(fd,getFloat(fs)+"+"+getFloat(ft))); break; case 1: // SUB.S - emit(pc, setFloat(fd,getFloat(fs)+"-"+getFloat(ft))); + p(setFloat(fd,getFloat(fs)+"-"+getFloat(ft))); break; case 2: // MUL.S - emit(pc, setFloat(fd,getFloat(fs)+"*"+getFloat(ft))); + p(setFloat(fd,getFloat(fs)+"*"+getFloat(ft))); break; case 3: // DIV.S - emit(pc, setFloat(fd,getFloat(fs)+"/"+getFloat(ft))); + p(setFloat(fd,getFloat(fs)+"/"+getFloat(ft))); break; case 5: // ABS.S - emit(pc, setFloat(fd,Math.abs("+getFloat(fs)+"))); + p(setFloat(fd,"Math.abs("+getFloat(fs)+")")); break; case 6: // MOV.S - emit(pc, f"+fd+" = f"+fs+"); + p("f"+fd+" = f"+fs+"; // MOV.S"); break; case 7: // NEG.S - emit(pc, setFloat(fd,"-1 * ("+getFloat(fs)+")")); // FIXME: just flip the sign bi)t + p(setFloat(fd,"-"+getFloat(fs))); // FEATURE: just flip the sign bit break; case 33: // CVT.D.S - emit(pc, setDouble(fd,getFloat(fs))); + p(setDouble(fd,"(float)"+getFloat(fs))); break; - case 36: // CVT.W.S - switch(roundingMode()) { - case 0: emit(pc, "f"+fd+" = (int)Math.floor("+getFloat(fs)+"+0.5f;"); break; // Round to nearest - case 1: emit(pc, "f"+fd+" = (int)"+getFloat(fs)+";"); break; // Round towards zero - case 2: emit(pc, "f"+fd+" = (int)Math.ceil("+getFloat(fs)+";"); break; // Round towards plus infinity - case 3: emit(pc, "f"+fd+" = (int)Math.floor("+getFloat(fs)+";"); break; // Round towards minus infinity - } + case 36: // CVT.W.D + p("// CVT.W.D"); + p("switch(roundingMode()) {"); + indent++; + p("case 0: f"+fd+" = (int)Math.floor("+getFloat(fs)+"+0.5); break; // Round to nearest"); + p("case 1: f"+fd+" = (int)"+getFloat(fs)+"; break; // Round towards zero"); + p("case 2: f"+fd+" = (int)Math.ceil("+getFloat(fs)+"); break; // Round towards plus infinity"); + p("case 3: f"+fd+" = (int)Math.floor("+getFloat(fs)+"); break; // Round towards minus infinity"); + indent--; + p("}"); break; - /* FIXME: not implemented yet - case -50: // C.EQ.S - setFC("+getFloat(fs)+" == "+getFloat(ft)+"); // FIXME: just compare the ints, be sure things are normalized + case 50: // C.EQ.D + p("setFC("+getFloat(fs)+"=="+getFloat(ft)+");"); // FEATURE: just compare the ints, be sure things are normalized break; - case 60: // C.LT.S - setFC("+getFloat(fs)+" < "+getFloat(ft)+"); + case 60: // C.LT.D + p("setFC("+getFloat(fs)+"<"+getFloat(ft)+");"); break; - */ - default: throw new RuntimeException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc)); + case 62: // C.LE.D + p("setFC("+getFloat(fs)+"<="+getFloat(ft)+");"); + break; + default: throw new CompilationException("Invalid Instruction 17/" + rs + "/" + subcode); } break; } case 17: { // Double switch(subcode) { case 0: // ADD.D - emit(pc, "setDouble(fd,"+getDouble(fs)+"+"+getDouble(ft)+");"); + p(setDouble(fd,getDouble(fs)+"+"+getDouble(ft))); break; case 1: // SUB.D - emit(pc, "setDouble(fd,"+getDouble(fs)+"-"+getDouble(ft)+");"); + p(setDouble(fd,getDouble(fs)+"-"+getDouble(ft))); break; case 2: // MUL.D - emit(pc, "setDouble(fd,"+getDouble(fs)+"*"+getDouble(ft)+");"); + p(setDouble(fd,getDouble(fs)+"*"+getDouble(ft))); break; case 3: // DIV.D - emit(pc, "setDouble(fd,"+getDouble(fs)+"/"+getDouble(ft)+");"); + p(setDouble(fd,getDouble(fs)+"/"+getDouble(ft))); break; case 5: // ABS.D - emit(pc, "setDouble(fd,Math.abs("+getDouble(fs)+"));"); + p(setDouble(fd,"Math.abs("+getDouble(fs)+")")); break; case 6: // MOV.D - emit(pc, "f"+fd+" = f"+fs+";"); - emit(pc, "f"+fd+1+" = f"+fs+1+";"); + p("f"+fd+" = f"+fs+";"); + p("f"+(fd+1)+" = f"+(fs+1)+";"); break; case 7: // NEG.D - emit(pc, "setDouble(fd,-"+getDouble(fs)+");"); // FIXME: just flip the sign bit" + p(setDouble(fd,"-"+getDouble(fs))); // FEATURE: just flip the sign bit break; case 32: // CVT.S.D - emit(pc, "setFloat(fd,(float)"+getDouble(fs)+");"); + p(setFloat(fd,"(float)"+getDouble(fs))); break; case 36: // CVT.W.D - switch(roundingMode()) { - case 0: emit(pc, "f"+fd+" = (int)Math.floor("+getDouble(fs)+"+0.5);"); break; // Round to nearest - case 1: emit(pc, "f"+fd+" = (int)"+getDouble(fs)+";"); break; // Round towards zero - case 2: emit(pc, "f"+fd+" = (int)Math.ceil("+getDouble(fs)+");"); break; // Round towards plus infinity - case 3: emit(pc, "f"+fd+" = (int)Math.floor("+getDouble(fs)+");"); break; // Round towards minus infinity - } + p("// CVT.W.D"); + p("switch(roundingMode()) {"); + indent++; + p("case 0: f"+fd+" = (int)Math.floor("+getDouble(fs)+"+0.5); break; // Round to nearest"); + p("case 1: f"+fd+" = (int)"+getDouble(fs)+"; break; // Round towards zero"); + p("case 2: f"+fd+" = (int)Math.ceil("+getDouble(fs)+"); break; // Round towards plus infinity"); + p("case 3: f"+fd+" = (int)Math.floor("+getDouble(fs)+"); break; // Round towards minus infinity"); + indent--; + p("}"); break; - /* FIXME not implemented yet case 50: // C.EQ.D - setFC("+getDouble(fs)+" == "+getDouble(ft)+"); // FIXME: just compare the ints, be sure things are normalized + p("setFC("+getDouble(fs)+"=="+getDouble(ft)+");"); // FEATURE: just compare the ints, be sure things are normalized break; case 60: // C.LT.D - setFC("+getDouble(fs)+" < "+getDouble(ft)+"); + p("setFC("+getDouble(fs)+"<"+getDouble(ft)+");"); break; case 62: // C.LE.D - setFC("+getDouble(fs)+" <= "+getDouble(ft)+"); + p("setFC("+getDouble(fs)+"<="+getDouble(ft)+");"); break; - */ - default: throw new EmulationException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc)); + default: throw new CompilationException("Invalid Instruction 17/" + rs + "/" + subcode); } break; } case 20: { // Integer switch(subcode) { + case 32: // CVT.S.W + p(" // CVS.S.W"); + p(setFloat(fd,"((float)f"+fs+")")); + break; case 33: // CVT.D.W - emit(pc, "setDouble(fd,(double)f"+fs+");"); + p("// CVT.D.W"); + p(setDouble(fd,"((double)f"+fs+")")); break; - default: throw new EmulationException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc)); + default: throw new CompilationException("Invalid Instruction 17/" + rs + "/" + subcode); } - break; + break; } default: - throw new RuntimeException("Invalid Instruction 17/" + rs); + throw new CompilationException("Invalid Instruction 17/" + rs); + } + break; } case 18: case 19: - throw new RuntimeException("No coprocessor installed"); + throw new CompilationException("coprocessor 2 and 3 instructions not available"); case 32: { // LB - /* FIXME not done yet - emit(pc, "addr = r"+rs+" + "+signedImmediate+";"); - try { - int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1]; - } catch(RuntimeException e) { - int tmp = memRead(addr&~3); - } - switch(addr&3) { - case 0: int tmp = (tmp>>>24)&0xff; break; - case 1: int tmp = (tmp>>>16)&0xff; break; - case 2: int tmp = (tmp>>> 8)&0xff; break; - case 3: int tmp = (tmp>>> 0)&0xff; break; - } - if((tmp&0x80)!=0) tmp |= 0xffffff00; // sign extend - r"+rt+" = tmp; - */ - break; + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&3) {"); + indent++; + p("case 0: tmp = (tmp>>>24)&0xff; break;"); + p("case 1: tmp = (tmp>>>16)&0xff; break;"); + p("case 2: tmp = (tmp>>> 8)&0xff; break;"); + p("case 3: tmp = (tmp>>> 0)&0xff; break;"); + indent--; + p("}"); + p("if((tmp&0x80)!=0) tmp |= 0xffffff00; // sign extend"); + p("r"+rt+" = tmp;"); + break; } case 33: { // LH - /* FIXME not done yet - addr = r"+rs+" + signedImmediate; - try { - int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1]; - } catch(RuntimeException e) { - int tmp = memRead(addr&~3); - } - switch(addr&2) { - case 0: int tmp = (tmp>>>16)&0xffff; break; - case 2: int tmp = (tmp>>> 0)&0xffff; break; - } - if((tmp&0x8000)!=0) tmp |= 0xffff0000; // sign extend - r"+rt+" = tmp; - break; - */ + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&2) {"); + indent++; + p("case 0: tmp = (tmp>>>16)&0xffff; break;"); + p("case 2: tmp = (tmp>>> 0)&0xffff; break;"); + indent--; + p("}"); + p("if((tmp&0x8000)!=0) tmp |= 0xffff0000; // sign extend"); + p("r"+rt+" = tmp;"); + break; } - /* FIXME not done yet case 34: { // LWL; - addr = r"+rs+" + signedImmediate; - try { - int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1]; - } catch(RuntimeException e) { - int tmp = memRead(addr&~3); - } - switch(addr&3) { - case 0: r"+rt+" = (r"+rt+"&0x00000000)|(tmp<< 0); break; - case 1: r"+rt+" = (r"+rt+"&0x000000ff)|(tmp<< 8); break; - case 2: r"+rt+" = (r"+rt+"&0x0000ffff)|(tmp<<16); break; - case 3: r"+rt+" = (r"+rt+"&0x00ffffff)|(tmp<<24); break; - } + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&3) {"); + indent++; + p("case 0: r"+rt+" = (r"+rt+"&0x00000000)|(tmp<< 0); break;"); + p("case 1: r"+rt+" = (r"+rt+"&0x000000ff)|(tmp<< 8); break;"); + p("case 2: r"+rt+" = (r"+rt+"&0x0000ffff)|(tmp<<16); break;"); + p("case 3: r"+rt+" = (r"+rt+"&0x00ffffff)|(tmp<<24); break;"); + indent--; + p("}"); break; } case 35: // LW - addr = r"+rs+" + signedImmediate; - try { - r"+rt+" = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1]; - } catch(RuntimeException e) { - r"+rt+" = memRead(addr); - } + memRead("r" + rs +"+"+signedImmediate,"r"+rt); break; case 36: { // LBU - addr = r"+rs+" + signedImmediate; - try { - int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1]; - } catch(RuntimeException e) { - int tmp = memRead(addr); - } - switch(addr&3) { - case 0: r"+rt+" = (tmp>>>24)&0xff; break; - case 1: r"+rt+" = (tmp>>>16)&0xff; break; - case 2: r"+rt+" = (tmp>>> 8)&0xff; break; - case 3: r"+rt+" = (tmp>>> 0)&0xff; break; - } - break; + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&3) {"); + indent++; + p("case 0: r"+rt+" = (tmp>>>24)&0xff; break;"); + p("case 1: r"+rt+" = (tmp>>>16)&0xff; break;"); + p("case 2: r"+rt+" = (tmp>>> 8)&0xff; break;"); + p("case 3: r"+rt+" = (tmp>>> 0)&0xff; break;"); + indent--; + p("}"); + break; } case 37: { // LHU - addr = r"+rs+" + signedImmediate; - try { - int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1]; - } catch(RuntimeException e) { - int tmp = memRead(addr&~3); - } - switch(addr&2) { - case 0: r"+rt+" = (tmp>>>16)&0xffff; break; - case 2: r"+rt+" = (tmp>>> 0)&0xffff; break; - } - break; + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&2) {"); + indent++; + p("case 0: r"+rt+" = (tmp>>>16)&0xffff; break;"); + p("case 2: r"+rt+" = (tmp>>> 0)&0xffff; break;"); + indent--; + p("}"); + break; } case 38: { // LWR - addr = r"+rs+" + signedImmediate; - try { - int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1]; - } catch(RuntimeException e) { - int tmp = memRead(addr&~3); - } - switch(addr&3) { - case 0: r"+rt+" = (r"+rt+"&0xffffff00)|(tmp>>>24); break; - case 1: r"+rt+" = (r"+rt+"&0xffff0000)|(tmp>>>16); break; - case 2: r"+rt+" = (r"+rt+"&0xff000000)|(tmp>>> 8); break; - case 3: r"+rt+" = (r"+rt+"&0x00000000)|(tmp>>> 0); break; - } + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&3) {"); + indent++; + p("case 0: r"+rt+" = (r"+rt+"&0xffffff00)|(tmp>>>24); break;"); + p("case 1: r"+rt+" = (r"+rt+"&0xffff0000)|(tmp>>>16); break;"); + p("case 2: r"+rt+" = (r"+rt+"&0xff000000)|(tmp>>> 8); break;"); + p("case 3: r"+rt+" = (r"+rt+"&0x00000000)|(tmp>>> 0); break;"); + indent--; + p("}"); break; } case 40: { // SB - addr = r"+rs+" + signedImmediate; - try { - int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1]; - } catch(RuntimeException e) { - int tmp = memRead(addr&~3); - } - switch(addr&3) { - case 0: int tmp = (tmp&0x00ffffff) | ((r"+rt+"&0xff)<<24); break; - case 1: int tmp = (tmp&0xff00ffff) | ((r"+rt+"&0xff)<<16); break; - case 2: int tmp = (tmp&0xffff00ff) | ((r"+rt+"&0xff)<< 8); break; - case 3: int tmp = (tmp&0xffffff00) | ((r"+rt+"&0xff)<< 0); break; - } - try { - writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = tmp; - } catch(RuntimeException e) { - memWrite(addr&~3,tmp); - } + p("// SB"); + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&3) {"); + indent++; + p("case 0: tmp = (tmp&0x00ffffff) | ((r"+rt+"&0xff)<<24); break;"); + p("case 1: tmp = (tmp&0xff00ffff) | ((r"+rt+"&0xff)<<16); break;"); + p("case 2: tmp = (tmp&0xffff00ff) | ((r"+rt+"&0xff)<< 8); break;"); + p("case 3: tmp = (tmp&0xffffff00) | ((r"+rt+"&0xff)<< 0); break;"); + indent--; + p("}"); + memWrite("addr&~3","tmp"); break; } case 41: { // SH - addr = r"+rs+" + signedImmediate; - try { - int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1]; - } catch(RuntimeException e) { - int tmp = memRead(addr&~3); - } - switch(addr&2) { - case 0: int tmp = (tmp&0x0000ffff) | ((r"+rt+"&0xffff)<<16); break; - case 2: int tmp = (tmp&0xffff0000) | ((r"+rt+"&0xffff)<< 0); break; - } - try { - writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = tmp; - } catch(RuntimeException e) { - memWrite(addr&~3,tmp); - } + p("// SH"); + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&2) {"); + indent++; + p("case 0: tmp = (tmp&0x0000ffff) | ((r"+rt+"&0xffff)<<16); break;"); + p("case 2: tmp = (tmp&0xffff0000) | ((r"+rt+"&0xffff)<< 0); break;"); + indent--; + p("}"); + memWrite("addr&~3","tmp"); break; } case 42: { // SWL - addr = r"+rs+" + signedImmediate; - int tmp = memRead(addr&~3); - switch(addr&3) { - case 0: tmp=(tmp&0x00000000)|(r"+rt+">>> 0); break; - case 1: tmp=(tmp&0xff000000)|(r"+rt+">>> 8); break; - case 2: tmp=(tmp&0xffff0000)|(r"+rt+">>>16); break; - case 3: tmp=(tmp&0xffffff00)|(r"+rt+">>>24); break; - } - try { - writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = tmp; - } catch(RuntimeException e) { - memWrite(addr&~3,tmp); - } + p(" // SWL"); + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&3) {"); + indent++; + p("case 0: tmp=(tmp&0x00000000)|(r"+rt+">>> 0); break;"); + p("case 1: tmp=(tmp&0xff000000)|(r"+rt+">>> 8); break;"); + p("case 2: tmp=(tmp&0xffff0000)|(r"+rt+">>>16); break;"); + p("case 3: tmp=(tmp&0xffffff00)|(r"+rt+">>>24); break;"); + indent--; + p("}"); + memWrite("addr&~3","tmp"); break; } case 43: // SW - addr = r"+rs+" + signedImmediate; - try { - writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = r"+rt+"; - } catch(RuntimeException e) { - memWrite(addr&~3,r"+rt+"); - } + memWrite("r"+rs+"+"+signedImmediate,"r" + rt); break; case 46: { // SWR - addr = r"+rs+" + signedImmediate; - int tmp = memRead(addr&~3); - switch(addr&3) { - case 0: tmp=(tmp&0x00ffffff)|(r"+rt+"<<24); break; - case 1: tmp=(tmp&0x0000ffff)|(r"+rt+"<<16); break; - case 2: tmp=(tmp&0x000000ff)|(r"+rt+"<< 8); break; - case 3: tmp=(tmp&0x00000000)|(r"+rt+"<< 0); break; - } - memWrite(addr&~3,tmp); + p(" // SWR"); + p("addr=r" + rs +"+"+signedImmediate + ";"); + memRead("addr&~3","tmp"); + p("switch(addr&3) {"); + indent++; + p("case 0: tmp=(tmp&0x00ffffff)|(r"+rt+"<<24); break;"); + p("case 1: tmp=(tmp&0x0000ffff)|(r"+rt+"<<16); break;"); + p("case 2: tmp=(tmp&0x000000ff)|(r"+rt+"<< 8); break;"); + p("case 3: tmp=(tmp&0x00000000)|(r"+rt+"<< 0); break;"); + indent--; + p("}"); + memWrite("addr&~3","tmp"); break; } case 49: // LWC1 - f"+rt+" = memRead(r"+rs+" + signedImmediate); + memRead("r"+rs+"+"+signedImmediate,"f"+rt); break; case 57: // SWC1 - memWrite(r"+rs+" + signedImmediate,f"+rt+"); + memWrite("r"+rs+"+"+signedImmediate,"f"+rt); break; default: - throw new EmulationException("Invalid Instruction: " + op); - */ + throw new CompilationException("Invalid Instruction: " + op + " at " + toHex(pc)); } - } - static String prefix = ""; - static void emit(int vaddr, String s) { - if (s.indexOf("r0 = ") != -1) s = " /* NOP */"; - if (!s.trim().endsWith("return;") && s.indexOf("throw") == -1) s += " pc = 0x" + Long.toString((vaddr + 4) & 0xffffffffL,16) + ";"; - System.out.println(s); + private static void memWrite(String addr, String target) { + if(fastMem) + p("writePages[("+addr+")>>>"+Runtime.PAGE_SHIFT+"][(("+addr+")>>>2)&"+toHex(Runtime.PAGE_WORDS-1)+"] = " + target + ";"); + else + p("memWrite(" + addr + "," + target + ");"); + + } + + private static void memRead(String addr, String target) { + if(fastMem) + p(target + " = readPages[("+addr+")>>>"+Runtime.PAGE_SHIFT+"][(("+addr+")>>>2)&"+toHex(Runtime.PAGE_WORDS-1)+"];"); + else + p(target + " = memRead(" + addr + ");"); } - static String getFloat(int r) { return "Float.intBitsToFloat(f"+r+")"; } - static String getDouble(int r) { - return "Double.longBitsToDouble(((f"+r+"&0xffffffffL) << 32) | (f"+r+"&0xffffffffL));"; + private static String getFloat(int r) { return "(Float.intBitsToFloat(f"+r+"))"; } + private static String getDouble(int r) { + return "(Double.longBitsToDouble(((f"+(r+1)+"&0xffffffffL) << 32) | (f"+r+"&0xffffffffL)))"; } - static String setFloat(int r, String expr) { return "f"+r+" = Float.floatToRawIntBits("+expr+");" } - static String setDouble(int r, String expr) { + private static String setFloat(int r, String expr) { return "f"+r+"=Float.floatToRawIntBits("+expr+");"; } + private static String setDouble(int r, String expr) { return "{ long l = Double.doubleToLongBits("+expr+"); "+ - "f"+(r+1)+" = (int)(l >>> 32); f"+(r)+" = (int)l; }"; + "f"+(r+1)+" = (int)(l >>> 32); f"+r+" = (int)l; }"; + } + + private final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); } + private final static String toHex8(int n) { + String s = Long.toString(n & 0xffffffffL, 16); + StringBuffer sb = new StringBuffer("0x"); + for(int i=8-s.length();i>0;i--) sb.append('0'); + sb.append(s); + return sb.toString(); } }