1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
7 // FIXME: lb/sb/sh/lh need not be word aligned
8 // FIXME: memory accesses aren't handling sign-extending properly
9 // FIXME: probably have to implement nonaligned access
10 // FIXME: implement malloc()
11 // FIXME: implement an ELF parser based on RandomAccessFile
12 // FEATURE: progress indicator
13 // FEATURE: support n32 abi (passes more arguments in registers)
14 // FEATURE: trap on arithmetic overflows
16 // FEATURE: we always know the value of the pc register; we should emit it as a literal when it appears in computations
17 // FEATURE: emit bytecode rather than .java code (for on-the-fly classloading without javac present in "real" JVMs)
19 /** reads a fully linked MIPS ELF binary image on stdin; writes a .java file on stdout */
20 public class Compiler {
22 static String runs = "";
23 static int last_emit = -1;
24 static DataInputStream dis;
25 public static void main(String[] s) throws IOException {
28 System.err.println("usage: java " + Compiler.class.getName() + " <classname> <binary.mips>");
32 String packageName = null;
33 String className = s[0];
34 if (s[0].indexOf('.') != -1) {
35 packageName = s[0].substring(0, s[0].lastIndexOf('.'));
36 className = s[0].substring(s[0].lastIndexOf('.') + 1);
39 System.out.println(prefix + "// This file was generated by MipsToJava");
40 if (packageName != null) System.out.println(prefix + "package " + packageName + ";");
41 System.out.println(prefix + "public class " + className + " extends org.xwt.mips.VM {");
42 System.out.println(prefix + "");
43 System.out.println(prefix + " public " + className + "() { }");
44 System.out.println(prefix + "");
45 System.out.println(prefix + " // program counter");
46 System.out.println(prefix + " int pc = 0;");
47 System.out.println(prefix + "");
48 System.out.println(prefix + " // temporary");
49 System.out.println(prefix + " int tmp = 0;");
50 System.out.println(prefix + "");
51 System.out.println(prefix + " // MIPS multiply/divide subsystem; 64-bit result");
52 System.out.println(prefix + " long hilo = 0;");
53 System.out.println(prefix + "");
54 System.out.println(prefix + " // General Purpose registers");
55 System.out.println(prefix + " final int r0 = 0;");
56 System.out.println(prefix + " int r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0,");
57 System.out.println(prefix + " r8 = 0, r9 = 0, r10 = 0, r11 = 0, r12 = 0, r13 = 0, r14 = 0, r15 = 0,");
58 System.out.println(prefix + " r16 = 0, r17 = 0, r18 = 0, r19 = 0, r20 = 0, r21 = 0, r22 = 0, r23 = 0,");
59 System.out.println(prefix + " r24 = 0, r25 = 0, r26 = 0, r27 = 0, r28 = 0, r29 = 0, r30 = 0, r31 = 0;");
60 System.out.println(prefix + "");
62 ELF elf = new ELF(new RandomAccessFile(args[1], "r"));
63 if(elf.header.type != ELF.ELFHeader.ET_EXEC) throw new IOException("Binary is not an executable");
64 if(elf.header.machine != ELF.ELFHeader.EM_MIPS) throw new IOException("Binary is not for the MIPS I Architecture");
66 ELF.PHeader[] pheaders = elf.pheaders;
68 int[][] readPages = new int[TOTAL_PAGES][];
69 int[][] writePages = new int[TOTAL_PAGES][];
70 for(int i=0; i<STACK_PAGES; i++)
71 readPages[TOTAL_PAGES-1-i] = writePages[TOTAL_PAGES-1-i] = emptyPage;
73 // FIXME: what is this?
75 for(int i=0;i<pheaders.length;i++) {
76 ELF.PHeader ph = pheaders[i];
77 if(ph.type != ELF.PHeader.PT_LOAD) continue;
78 int memsize = ph.memsz;
79 int filesize = ph.filesz;
80 if(memsize == 0) continue;
81 if(memsize < 0) throw new IOException("pheader size too large");
83 if(addr == 0x0) throw new IOException("pheader vaddr == 0x0");
84 if(addr+memsize >= (brk<<PAGE_SHIFT)) brk = (addr+memsize+PAGE_SIZE-1) >> PAGE_SHIFT;
85 // FIXME: set memsize, serialize readPages/writePages
86 for(int j=0;j<memsize+PAGE_SIZE-1;j+=PAGE_SIZE) {
87 int page = (j+addr) >>> PAGE_SHIFT;
88 if(readPages[page] == null) readPages[page] = new int[PAGE_WORDS];
89 if(ph.writable()) writePages[page] = readPages[page];
92 filesize = filesize & ~3;
93 DataInputStream dis = new DataInputStream(ph.getInputStream());
95 if (ph.executable()) emit(addr, 1, dis);
96 readPages[addr >>> PAGE_SHIFT][(addr >>> 2)&(PAGE_WORDS-1)] = dis.readInt();
99 } while(filesize > 0);
104 // cap off the last method
107 System.out.println(prefix + " protected int state = INITIALIZED;");
108 System.out.println(prefix + " protected int brk = " + brk + ";");
110 System.out.println();
111 System.out.println(prefix + " public static void main(String[] s) { new " + className + "()._start(entryPoint); }");
112 System.out.println();
113 System.out.println(prefix + " protected int entryPoint = " + elf.header.entry + ";");
114 System.out.println();
115 System.out.println(prefix + " protected void _start(int pc) {");
116 System.out.println();
117 System.out.println(prefix + " // set the stack pointer");
118 System.out.println(prefix + " r29 = INITIAL_SP;");
119 System.out.println();
120 System.out.println(prefix + " // set the \"return address\" from _start to point at the \"magic exit address\" (0xdeadbeef)");
121 System.out.println(prefix + " r31 = 0xdeadbeef;");
122 System.out.println();
123 System.out.println(prefix + " // read in the .data segment");
124 System.out.println(prefix + " //initData();");
125 System.out.println();
126 System.out.println(prefix + " trampoline(pc);");
127 System.out.println();
128 System.out.println(prefix + " }");
130 System.out.println();
131 System.out.println(prefix + " public void execute() throws EmulationException {");
132 System.out.println(prefix + " if(state == PAUSED) state = RUNNING;");
133 System.out.println(prefix + " if(state != RUNNING)");
134 System.out.println(prefix + " throw new IllegalStateException(\"execute() called in inappropriate state\");");
135 System.out.println(prefix + " trampoline(this.pc);");
136 System.out.println(prefix + " }");
137 System.out.println();
138 System.out.println(prefix + " public void trampoline(int pc) {");
139 System.out.println(prefix + " this.pc = pc;");
140 System.out.println(prefix + " while(true) {");
141 System.out.println(prefix + " switch(this.pc & 0xffffff00) {");
142 System.out.println(prefix + " case 0xdeadbe00: System.out.println(\"exiting with return value \" + r2); System.exit(r2); continue;");
143 System.out.print(runs);
144 System.out.println(prefix + " default: throw new Error(\"invalid address 0x\" + Long.toString(this.pc&0xffffffffL,16));");
145 System.out.println(prefix + " }");
146 System.out.println(prefix + " }");
147 System.out.println(prefix + " }");
148 System.out.println(prefix + "}");
151 static int _instruction;
152 static boolean readnext = true;
154 /** reads <tt>numbytes</tt> from the stream, emitting <tt>case</tt> blocks starting at vaddr <tt>ofs</tt> */
155 static void emit(int vaddr, int numbytes, DataInputStream dis) throws IOException {
156 if ((vaddr == -1 && numbytes == -1) || (last_emit != -1 && ((last_emit & 0xffffff00) != (vaddr & 0xffffff00)))) {
157 System.out.println(prefix + " case 0x" + Long.toString((last_emit & 0xffffffffL) + 0x1000, 16) + ": return;");
158 System.out.println(prefix + " default: throw new Error(\"invalid address 0x\" + Long.toString(pc&0xffffffffL,16));");
159 System.out.println(prefix + " }");
160 System.out.println(prefix + " }");
161 if (vaddr == -1 && numbytes == -1) return;
163 if (last_emit == -1 || ((last_emit & 0xffffff00) != (vaddr & 0xffffff00))) {
164 System.out.println("");
165 System.out.println(prefix + " private void run_" + Long.toString(vaddr & 0xffffff00L,16) + "() {");
166 runs += " case 0x" + Long.toString(vaddr & 0xffffff00L,16) +
167 ": run_" + Long.toString(vaddr & 0xffffff00L,16) + "(); continue;\n";
168 System.out.println(prefix + " switch(pc) {");
172 OUTER: for(ofs = vaddr; ofs < vaddr + numbytes; ofs+=4) {
173 if (readnext) _instruction = dis.readInt();
176 String istring = Long.toString(_instruction & 0xffffffffL, 16);
177 while(istring.length() < 8) istring = "0" + istring;
178 String ostring = Long.toString(ofs & 0xffffffffL, 16);
179 while(ostring.length() < 8) ostring = "0" + ostring;
180 System.out.print(prefix + " /* " + istring + " */ case 0x" + ostring + ": System.out.println(\"pc=0x\" + Long.toString(pc&0xffffffffL,16));");
182 emit_instruction(ofs, _instruction);
184 } catch (EOFException e) {
185 emit(ofs, " // warning, reached EOF before section end");
191 private static void emit_instruction(int pc, int insn) throws IOException {
192 int op = (insn >>> 26) & 0xff; // bits 26-31
193 int rs = (insn >>> 21) & 0x1f; // bits 21-25
194 int rt = (insn >>> 16) & 0x1f; // bits 16-20
195 int ft = (insn >>> 16) & 0x1f;
196 int rd = (insn >>> 11) & 0x1f; // bits 11-15
197 int fs = (insn >>> 11) & 0x1f;
198 int shamt = (insn >>> 6) & 0x1f; // bits 6-10
199 int fd = (insn >>> 6) & 0x1f;
200 int subcode = insn & 0x3f; // bits 0-5
202 int jumpTarget = (insn & 0x03ffffff); // bits 0-25
203 int unsignedImmediate = insn & 0xffff;
204 int signedImmediate = (insn << 16) >> 16;
205 int branchTarget = signedImmediate;
207 int tmp, addr; // temporaries
214 emit(pc, "r"+rd+" = r"+rt+" << "+shamt+";");
217 emit(pc, "r"+rd+" = r"+rt+" >>> "+shamt+";");
220 emit(pc, "r"+rd+" = r"+rt+" >> "+shamt+";");
222 // FIXME: Do we need % 32 on the r"+rs+" ?
224 emit(pc, "r"+rd+" = r"+rt+" << r"+rs+";");
227 emit(pc, "r"+rd+" = r"+rt+" >>> r"+rs+";");
230 emit(pc, "r"+rd+" = r"+rt+" >> r"+rs+";");
233 emit(pc, "{ int tmp = r"+rs+"; pc += 4; nextPC = tmp; }");
236 emit(pc, "{ int tmp = r"+rs+"; pc += 4; r"+rd+" = pc+4; nextPC = tmp; }");
239 emit(pc, "r"+V0+" = syscall(r"+V0+",r"+A0+",r"+A1+",r"+A2+",r"+A3+"); " +
240 "if (state != RUNNING) { this.nextPC = nextPC; return; }");
243 emit(pc, "throw new EmulationException(\"Break\")");
246 emit(pc, "r"+rd+" = hi;");
249 emit(pc, "hi = r"+rs+";");
252 emit(pc, "r"+rd+" = lo;");
255 emit(pc, "lo = r"+rs+";");
258 emit(pc, "long hilo = (long)(r"+rs+") * ((long)r"+rt+"); " +
259 "hi = (int) (hilo >>> 32); " +
263 emit(pc, "long hilo = (r"+rs+" & 0xffffffffL) * (r"+rt+" & 0xffffffffL); " +
264 "hi = (int) (hilo >>> 32); " +
267 emit(pc, "hi = r"+rs+"%r"+rt+"; lo = r"+rs+"/r"+rt+";");
270 emit(pc, "hi = (int)((r"+rs+" & 0xffffffffL) % (r"+rt+" & 0xffffffffL)); " +
271 "lo = (int)((r"+rs+" & 0xffffffffL) / (r"+rt+" & 0xffffffffL));");
274 emit(pc, "r"+rd+" = r"+rs+" + r"+rt+";"); // FIXME: Trap on overflow
277 emit(pc, "r"+rd+" = r"+rs+" + r"+rt+";");
280 emit(pc, "r"+rd+" = r"+rs+" - r"+rt+";"); // FIXME: Trap on overflow
283 emit(pc, "r"+rd+" = r"+rs+" - r"+rt+";");
286 emit(pc, "r"+rd+" = r"+rs+" & r"+rt+";");
289 emit(pc, "r"+rd+" = r"+rs+" | r"+rt+";");
292 emit(pc, "r"+rd+" = r"+rs+" ^ r"+rt+";");
295 emit(pc, "r"+rd+" = ~(r"+rs+" | r"+rt+");");
298 emit(pc, "r"+rd+" = r"+rs+" < r"+rt+" ? 1 : 0;");
301 emit(pc, "r"+rd+" = ((r"+rs+" & 0xffffffffL) < (r"+rt+" & 0xffffffffL)) ? 1 : 0;");
304 throw new RuntimeException("Illegal instruction 0/" + subcode);
311 emit(pc, "if (r"+rs+"<0) { pc += 4; int tmp = pc + "+
312 branchTarget+"*4; nextPC = tmp; }");
315 emit(pc, "if (r"+rs+">=0) { pc += 4; int tmp = pc + "+
316 branchTarget+"*4; nextPC = tmp; }");
319 emit(pc, "if(r"+rs+" < 0) { pc += 4; r"+RA+" = pc+4; int tmp = pc + "+
320 branchTarget+"*4; nextPC = tmp; }");
323 emit(pc, "if(r"+rs+" >= 0) { pc += 4; r"+RA+" = pc+4; int tmp = pc + "+
324 branchTarget+"*4; nextPC = tmp; }");
327 throw new RuntimeException("Illegal Instruction");
332 emit(pc, "int tmp = (pc&0xf0000000) | ("+jumpTarget+" << 2); pc+=4; nextPC = tmp;");
336 emit(pc, "int tmp = (pc&0xf0000000) | ("+jumpTarget+" << 2); pc+=4; r"+RA+
337 " = pc+4; nextPC = tmp;");
341 emit(pc, "if(r"+rs+" == r"+rt+") { pc += 4; int tmp = pc + "+
342 branchTarget+"*4; nextPC = tmp; }");
345 emit(pc, "if(r"+rs+" != r"+rt+") { pc += 4; int tmp = pc + "+
346 branchTarget+"*4; nextPC = tmp; }");
349 emit(pc, "if(r"+rs+" <= 0) { pc += 4; int tmp = pc + "+
350 branchTarget+"*4; nextPC = tmp; ;");
353 emit(pc, "if(r"+rs+" > 0) { pc += 4; int tmp = pc + "+branchTarget+"*4; nextPC = tmp; }");
356 emit(pc, "r"+rt+" = r"+rs+" + "+signedImmediate +";");
359 emit(pc, "r"+rt+" = r"+rs+" + "+signedImmediate+";");
362 emit(pc, "r"+rt+" = r"+rs+" < "+signedImmediate+" ? 1 : 0;");
365 emit(pc, "r"+rt+" = (r"+rs+"&0xffffffffL) < ("+unsignedImmediate+"&0xffffffffL) ? 1 : 0;");
368 emit(pc, "r"+rt+" = r"+rs+" & "+unsignedImmediate+";");
371 emit(pc, "r"+rt+" = r"+rs+" | "+unsignedImmediate+";");
374 emit(pc, "r"+rt+" = r"+rs+" ^ "+unsignedImmediate+";");
377 emit(pc, "r"+rt+" = "+unsignedImmediate+" << 16;");
380 throw new RuntimeException("TLB/Exception support not implemented");
384 emit(pc, "r"+rt+" = f"+rd);
387 if(fs != 31) throw new EmulationException("FCR " + fs + " unavailable");
388 emit(pc, "r"+rt+" = fcsr;");
391 emit(pc, "f"+rd+" = r"+rt+";");
394 if(fs != 31) throw new EmulationException("FCR " + fs + " unavailable");
395 emit(pc, "fcsr = r"+rt+"; ;")
397 case 8: // BC1F, BC1T
398 emit(pc, "if(((fcsr&0x800000)!=0) == (((insn>>>16)&1)!=0)) {"+
399 " pc += 4; int tmp = pc + "+branchTarget+"*4; nextPC = tmp; ;")}
404 emit(pc, setFloat(fd,getFloat(fs)+"+"+getFloat(ft)));
407 emit(pc, setFloat(fd,getFloat(fs)+"-"+getFloat(ft)));
410 emit(pc, setFloat(fd,getFloat(fs)+"*"+getFloat(ft)));
413 emit(pc, setFloat(fd,getFloat(fs)+"/"+getFloat(ft)));
416 emit(pc, setFloat(fd,Math.abs("+getFloat(fs)+")));
419 emit(pc, f"+fd+" = f"+fs+");
422 emit(pc, setFloat(fd,"-1 * ("+getFloat(fs)+")")); // FIXME: just flip the sign bi)t
425 emit(pc, setDouble(fd,getFloat(fs)));
428 switch(roundingMode()) {
429 case 0: emit(pc, "f"+fd+" = (int)Math.floor("+getFloat(fs)+"+0.5f;"); break; // Round to nearest
430 case 1: emit(pc, "f"+fd+" = (int)"+getFloat(fs)+";"); break; // Round towards zero
431 case 2: emit(pc, "f"+fd+" = (int)Math.ceil("+getFloat(fs)+";"); break; // Round towards plus infinity
432 case 3: emit(pc, "f"+fd+" = (int)Math.floor("+getFloat(fs)+";"); break; // Round towards minus infinity
435 /* FIXME: not implemented yet
437 setFC("+getFloat(fs)+" == "+getFloat(ft)+"); // FIXME: just compare the ints, be sure things are normalized
440 setFC("+getFloat(fs)+" < "+getFloat(ft)+");
443 default: throw new RuntimeException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc));
450 emit(pc, "setDouble(fd,"+getDouble(fs)+"+"+getDouble(ft)+");");
453 emit(pc, "setDouble(fd,"+getDouble(fs)+"-"+getDouble(ft)+");");
456 emit(pc, "setDouble(fd,"+getDouble(fs)+"*"+getDouble(ft)+");");
459 emit(pc, "setDouble(fd,"+getDouble(fs)+"/"+getDouble(ft)+");");
462 emit(pc, "setDouble(fd,Math.abs("+getDouble(fs)+"));");
465 emit(pc, "f"+fd+" = f"+fs+";");
466 emit(pc, "f"+fd+1+" = f"+fs+1+";");
469 emit(pc, "setDouble(fd,-"+getDouble(fs)+");"); // FIXME: just flip the sign bit"
472 emit(pc, "setFloat(fd,(float)"+getDouble(fs)+");");
475 switch(roundingMode()) {
476 case 0: emit(pc, "f"+fd+" = (int)Math.floor("+getDouble(fs)+"+0.5);"); break; // Round to nearest
477 case 1: emit(pc, "f"+fd+" = (int)"+getDouble(fs)+";"); break; // Round towards zero
478 case 2: emit(pc, "f"+fd+" = (int)Math.ceil("+getDouble(fs)+");"); break; // Round towards plus infinity
479 case 3: emit(pc, "f"+fd+" = (int)Math.floor("+getDouble(fs)+");"); break; // Round towards minus infinity
482 /* FIXME not implemented yet
484 setFC("+getDouble(fs)+" == "+getDouble(ft)+"); // FIXME: just compare the ints, be sure things are normalized
487 setFC("+getDouble(fs)+" < "+getDouble(ft)+");
490 setFC("+getDouble(fs)+" <= "+getDouble(ft)+");
493 default: throw new EmulationException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc));
497 case 20: { // Integer
500 emit(pc, "setDouble(fd,(double)f"+fs+");");
502 default: throw new EmulationException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc));
507 throw new RuntimeException("Invalid Instruction 17/" + rs);
510 throw new RuntimeException("No coprocessor installed");
512 /* FIXME not done yet
513 emit(pc, "addr = r"+rs+" + "+signedImmediate+";");
515 int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
516 } catch(RuntimeException e) {
517 int tmp = memRead(addr&~3);
520 case 0: int tmp = (tmp>>>24)&0xff; break;
521 case 1: int tmp = (tmp>>>16)&0xff; break;
522 case 2: int tmp = (tmp>>> 8)&0xff; break;
523 case 3: int tmp = (tmp>>> 0)&0xff; break;
525 if((tmp&0x80)!=0) tmp |= 0xffffff00; // sign extend
531 /* FIXME not done yet
532 addr = r"+rs+" + signedImmediate;
534 int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
535 } catch(RuntimeException e) {
536 int tmp = memRead(addr&~3);
539 case 0: int tmp = (tmp>>>16)&0xffff; break;
540 case 2: int tmp = (tmp>>> 0)&0xffff; break;
542 if((tmp&0x8000)!=0) tmp |= 0xffff0000; // sign extend
547 /* FIXME not done yet
549 addr = r"+rs+" + signedImmediate;
551 int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
552 } catch(RuntimeException e) {
553 int tmp = memRead(addr&~3);
556 case 0: r"+rt+" = (r"+rt+"&0x00000000)|(tmp<< 0); break;
557 case 1: r"+rt+" = (r"+rt+"&0x000000ff)|(tmp<< 8); break;
558 case 2: r"+rt+" = (r"+rt+"&0x0000ffff)|(tmp<<16); break;
559 case 3: r"+rt+" = (r"+rt+"&0x00ffffff)|(tmp<<24); break;
564 addr = r"+rs+" + signedImmediate;
566 r"+rt+" = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
567 } catch(RuntimeException e) {
568 r"+rt+" = memRead(addr);
572 addr = r"+rs+" + signedImmediate;
574 int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
575 } catch(RuntimeException e) {
576 int tmp = memRead(addr);
579 case 0: r"+rt+" = (tmp>>>24)&0xff; break;
580 case 1: r"+rt+" = (tmp>>>16)&0xff; break;
581 case 2: r"+rt+" = (tmp>>> 8)&0xff; break;
582 case 3: r"+rt+" = (tmp>>> 0)&0xff; break;
587 addr = r"+rs+" + signedImmediate;
589 int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
590 } catch(RuntimeException e) {
591 int tmp = memRead(addr&~3);
594 case 0: r"+rt+" = (tmp>>>16)&0xffff; break;
595 case 2: r"+rt+" = (tmp>>> 0)&0xffff; break;
600 addr = r"+rs+" + signedImmediate;
602 int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
603 } catch(RuntimeException e) {
604 int tmp = memRead(addr&~3);
607 case 0: r"+rt+" = (r"+rt+"&0xffffff00)|(tmp>>>24); break;
608 case 1: r"+rt+" = (r"+rt+"&0xffff0000)|(tmp>>>16); break;
609 case 2: r"+rt+" = (r"+rt+"&0xff000000)|(tmp>>> 8); break;
610 case 3: r"+rt+" = (r"+rt+"&0x00000000)|(tmp>>> 0); break;
615 addr = r"+rs+" + signedImmediate;
617 int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
618 } catch(RuntimeException e) {
619 int tmp = memRead(addr&~3);
622 case 0: int tmp = (tmp&0x00ffffff) | ((r"+rt+"&0xff)<<24); break;
623 case 1: int tmp = (tmp&0xff00ffff) | ((r"+rt+"&0xff)<<16); break;
624 case 2: int tmp = (tmp&0xffff00ff) | ((r"+rt+"&0xff)<< 8); break;
625 case 3: int tmp = (tmp&0xffffff00) | ((r"+rt+"&0xff)<< 0); break;
628 writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = tmp;
629 } catch(RuntimeException e) {
630 memWrite(addr&~3,tmp);
635 addr = r"+rs+" + signedImmediate;
637 int tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1];
638 } catch(RuntimeException e) {
639 int tmp = memRead(addr&~3);
642 case 0: int tmp = (tmp&0x0000ffff) | ((r"+rt+"&0xffff)<<16); break;
643 case 2: int tmp = (tmp&0xffff0000) | ((r"+rt+"&0xffff)<< 0); break;
646 writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = tmp;
647 } catch(RuntimeException e) {
648 memWrite(addr&~3,tmp);
653 addr = r"+rs+" + signedImmediate;
654 int tmp = memRead(addr&~3);
656 case 0: tmp=(tmp&0x00000000)|(r"+rt+">>> 0); break;
657 case 1: tmp=(tmp&0xff000000)|(r"+rt+">>> 8); break;
658 case 2: tmp=(tmp&0xffff0000)|(r"+rt+">>>16); break;
659 case 3: tmp=(tmp&0xffffff00)|(r"+rt+">>>24); break;
662 writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = tmp;
663 } catch(RuntimeException e) {
664 memWrite(addr&~3,tmp);
669 addr = r"+rs+" + signedImmediate;
671 writePages[addr>>>PAGE_SHIFT][(addr>>>2)&PAGE_WORDS-1] = r"+rt+";
672 } catch(RuntimeException e) {
673 memWrite(addr&~3,r"+rt+");
677 addr = r"+rs+" + signedImmediate;
678 int tmp = memRead(addr&~3);
680 case 0: tmp=(tmp&0x00ffffff)|(r"+rt+"<<24); break;
681 case 1: tmp=(tmp&0x0000ffff)|(r"+rt+"<<16); break;
682 case 2: tmp=(tmp&0x000000ff)|(r"+rt+"<< 8); break;
683 case 3: tmp=(tmp&0x00000000)|(r"+rt+"<< 0); break;
685 memWrite(addr&~3,tmp);
689 f"+rt+" = memRead(r"+rs+" + signedImmediate);
692 memWrite(r"+rs+" + signedImmediate,f"+rt+");
695 throw new EmulationException("Invalid Instruction: " + op);
701 static String prefix = "";
702 static void emit(int vaddr, String s) {
703 if (s.indexOf("r0 = ") != -1) s = " /* NOP */";
704 if (!s.trim().endsWith("return;") && s.indexOf("throw") == -1) s += " pc = 0x" + Long.toString((vaddr + 4) & 0xffffffffL,16) + ";";
705 System.out.println(s);
708 static String getFloat(int r) { return "Float.intBitsToFloat(f"+r+")"; }
709 static String getDouble(int r) {
710 return "Double.longBitsToDouble(((f"+r+"&0xffffffffL) << 32) | (f"+r+"&0xffffffffL));";
712 static String setFloat(int r, String expr) { return "f"+r+" = Float.floatToRawIntBits("+expr+");" }
713 static String setDouble(int r, String expr) {
714 return "{ long l = Double.doubleToLongBits("+expr+"); "+
715 "f"+(r+1)+" = (int)(l >>> 32); f"+(r)+" = (int)l; }";