From: megacz Date: Fri, 30 Jan 2004 08:04:03 +0000 (+0000) Subject: 2004/01/18 03:55:10 X-Git-Tag: RC3~149 X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=commitdiff_plain;h=ac24a263326bdd328935ac74521093eda7aad074 2004/01/18 03:55:10 darcs-hash:20040130080403-2ba56-f55504bed9eb38eaa2416ed7078e70571b88f0f9.gz --- diff --git a/src/org/xwt/mips/Compiler.java b/src/org/xwt/mips/Compiler.java deleted file mode 100644 index a7fd8f2..0000000 --- a/src/org/xwt/mips/Compiler.java +++ /dev/null @@ -1,1019 +0,0 @@ -// Copyright 2004 Adam Megacz, see the COPYING file for licensing [GPL] -package org.xwt.mips; - -import java.util.*; -import java.io.*; - -// FEATURE: progress indicator -// FEATURE: emit bytecode rather than .java code (for on-the-fly classloading without javac present in "real" JVMs - -public class Compiler implements Registers { - - 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); - } - - String packageName = null; - String className = s[0]; - if (s[0].indexOf('.') != -1) { - packageName = s[0].substring(0, s[0].lastIndexOf('.')); - className = s[0].substring(s[0].lastIndexOf('.') + 1); - } - - 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"); - - p("// This file was generated by MipsToJava"); - if (packageName != null) p("package " + packageName + ";"); - p("public class " + className + " extends org.xwt.mips.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;"); - 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(" }"); - - 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 >> " + LOG_MAX_BYTES_PER_METHOD + ") {"); - p(runs.toString()); - p(" default: throw new Error(\"invalid address 0x\" + Long.toString(this.pc&0xffffffffL,16));"); - p(" }"); - p(" }"); - p(" }"); - p("}"); - } - - 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>>LOG_MAX_BYTES_PER_METHOD) + ": finished = !" + methodName + "(); break;\n"); - p("private final boolean " + methodName + "() throws ExecutionException { /"+"* " + toHex(addr) + " - " + toHex(endOfMethod) + " *" + "/"); - indent++; - p("int addr, tmp;"); - for(int i=0;i>2) {"); - indent++; - startOfMethod = addr; - - } - private static void endMethod() { endMethod(endOfMethod); } - private static void endMethod(int lastAddr) { - if(startOfMethod == 0) return; - // This isn't strictly necessary; its just here to work around unreachable code errors - p("case " + toHex(lastAddr>>2) + ":"); - indent++; - p("pc=" + toHex(lastAddr) + ";"); - leaveMethod(); - indent--; - if(debugCompiler) - p("default: throw new Error(\"invalid address 0x\" + Long.toString(pc&0xffffffffL,16) + \" (got here from 0x\" + Long.toString(lastPC&0xffffffffL,16)+\")\");"); - else - p("default: throw new Error(\"invalid address 0x\" + Long.toString(pc&0xffffffffL,16));"); - indent--; - p("}"); // end switch - p("/* NOT REACHED */"); - indent--; - p("}"); // end for - indent--; - p("}"); // end method - endOfMethod = 0; - } - - private static void branch(int pc, int target) { - if(debugCompiler) - p("lastPC = " + toHex(pc) + ";"); - p("pc=" + toHex(target) + ";"); - if((pc>>LOG_MAX_BYTES_PER_METHOD) == (target>>LOG_MAX_BYTES_PER_METHOD)) - p("continue;"); - else - leaveMethod(); - } - - private static void leaveMethod() { leaveMethod(true); } - private static void leaveMethod(boolean cont) { - for(int i=0;i= endOfMethod) { endMethod(); startMethod(addr); } - if(jumpableAddresses==null || addr == startOfMethod || jumpableAddresses.contains(new Integer(addr))) { - p("case " + toHex(addr>>2) + ":"); - unreachable = false; - } else if(unreachable) { - continue; - } else if(debugCompiler) { - p("/" + "* pc = " + toHex(addr) + "*" + "/"); - } - indent++; - emitInstruction(addr,insn,nextInsn); - indent--; - } - 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 - int ft = (insn >>> 16) & 0x1f; - int rd = (insn >>> 11) & 0x1f; // bits 11-15 - int fs = (insn >>> 11) & 0x1f; - int shamt = (insn >>> 6) & 0x1f; // bits 6-10 - int fd = (insn >>> 6) & 0x1f; - int subcode = insn & 0x3f; // bits 0-5 - - int jumpTarget = (insn & 0x03ffffff); // bits 0-25 - int unsignedImmediate = insn & 0xffff; - int signedImmediate = (insn << 16) >> 16; - int branchTarget = signedImmediate; - - 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) - p("/* NOOP */"); - else - p( "r"+rd+" = r"+rt+" << "+shamt+";"); - break; - case 2: // SRL - p( "r"+rd+" = r"+rt+" >>> "+shamt+";"); - break; - case 3: // SRA - p( "r"+rd+" = r"+rt+" >> "+shamt+";"); - break; - case 4: // SLLV - p( "r"+rd+" = r"+rt+" << (r"+rs+"&0x1f);"); - break; - case 6: // SRLV - p( "r"+rd+" = r"+rt+" >>> (r"+rs+"&0x1f);"); - break; - case 7: // SRAV - p( "r"+rd+" = r"+rt+" >> (r"+rs+"&0x1f);"); - break; - case 8: // JR - 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 - 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 - 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 - p( "throw new ExecutionException(\"Break\");"); - break; - case 16: // MFHI - p( "r"+rd+" = hi;"); - break; - case 17: // MTHI - p( "hi = r"+rs+";"); - break; - case 18: // MFLO - p( "r"+rd+" = lo;"); - break; - case 19: // MTLO - p( "lo = r"+rs+";"); - break; - case 24: // MULT - p( "{ long hilo = (long)(r"+rs+") * ((long)r"+rt+"); " + - "hi = (int) (hilo >>> 32); " + - "lo = (int) hilo; }"); - break; - case 25: // MULTU - p( "{ long hilo = (r"+rs+" & 0xffffffffL) * (r"+rt+" & 0xffffffffL); " + - "hi = (int) (hilo >>> 32); " + - "lo = (int) hilo; } "); - break; - case 26: // DIV - p( "hi = r"+rs+"%r"+rt+"; lo = r"+rs+"/r"+rt+";"); - break; - case 27: // DIVU - p( "hi = (int)((r"+rs+" & 0xffffffffL) % (r"+rt+" & 0xffffffffL)); " + - "lo = (int)((r"+rs+" & 0xffffffffL) / (r"+rt+" & 0xffffffffL));"); - break; - case 32: // ADD - 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 - p( "r"+rd+" = r"+rs+" + r"+rt+";"); - break; - case 34: // SUB - 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 - p( "r"+rd+" = r"+rs+" - r"+rt+";"); - break; - case 36: // AND - p( "r"+rd+" = r"+rs+" & r"+rt+";"); - break; - case 37: // OR - p( "r"+rd+" = r"+rs+" | r"+rt+";"); - break; - case 38: // XOR - p( "r"+rd+" = r"+rs+" ^ r"+rt+";"); - break; - case 39: // NOR - p( "r"+rd+" = ~(r"+rs+" | r"+rt+");"); - break; - case 42: // SLT - p( "r"+rd+" = r"+rs+" < r"+rt+" ? 1 : 0;"); - break; - case 43: // SLTU - p( "r"+rd+" = ((r"+rs+" & 0xffffffffL) < (r"+rt+" & 0xffffffffL)) ? 1 : 0;"); - break; - default: - throw new RuntimeException("Illegal instruction 0/" + subcode); - } - break; - } - case 1: { - switch(rt) { - case 0: // BLTZ - 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 - 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 - 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 - 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 1/" + rt); - } - break; - } - case 2: { // J - 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 - 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 - 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 - 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 - 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 - 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 - p( "r"+rt+" = r"+rs+" + "+signedImmediate +";"); - break; - case 9: // ADDIU - p( "r"+rt+" = r"+rs+" + "+signedImmediate+";"); - break; - case 10: // SLTI - p( "r"+rt+" = r"+rs+" < "+signedImmediate+" ? 1 : 0;"); - break; - case 11: // SLTIU - p( "r"+rt+" = (r"+rs+"&0xffffffffL) < ("+unsignedImmediate+"&0xffffffffL) ? 1 : 0;"); - break; - case 12: // ANDI - p( "r"+rt+" = r"+rs+" & "+unsignedImmediate+";"); - break; - case 13: // ORI - p( "r"+rt+" = r"+rs+" | "+unsignedImmediate+";"); - break; - case 14: // XORI - p( "r"+rt+" = r"+rs+" ^ "+unsignedImmediate+";"); - break; - case 15: // LUI - p( "r"+rt+" = "+unsignedImmediate+" << 16;"); - break; - case 16: - throw new CompilationException("TLB/Exception support not implemented"); - case 17: { // FPU - switch(rs) { - case 0: // MFC.1 - p( "r"+rt+" = f"+rd+";"); - break; - case 2: // CFC.1 - if(fs != 31) throw new CompilationException("FCR " + fs + " unavailable"); - p( "r"+rt+" = fcsr;"); - break; - case 4: // MTC.1 - p( "f"+rd+" = r"+rt+";"); - break; - case 6: // CTC.1 - 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 - switch(subcode) { - case 0: // ADD.S - p(setFloat(fd,getFloat(fs)+"+"+getFloat(ft))); - break; - case 1: // SUB.S - p(setFloat(fd,getFloat(fs)+"-"+getFloat(ft))); - break; - case 2: // MUL.S - p(setFloat(fd,getFloat(fs)+"*"+getFloat(ft))); - break; - case 3: // DIV.S - p(setFloat(fd,getFloat(fs)+"/"+getFloat(ft))); - break; - case 5: // ABS.S - p(setFloat(fd,"Math.abs("+getFloat(fs)+")")); - break; - case 6: // MOV.S - p("f"+fd+" = f"+fs+"; // MOV.S"); - break; - case 7: // NEG.S - p(setFloat(fd,"-"+getFloat(fs))); // FEATURE: just flip the sign bit - break; - case 33: // CVT.D.S - p(setDouble(fd,"(float)"+getFloat(fs))); - break; - 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; - 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.D - p("setFC("+getFloat(fs)+"<"+getFloat(ft)+");"); - break; - 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 - p(setDouble(fd,getDouble(fs)+"+"+getDouble(ft))); - break; - case 1: // SUB.D - p(setDouble(fd,getDouble(fs)+"-"+getDouble(ft))); - break; - case 2: // MUL.D - p(setDouble(fd,getDouble(fs)+"*"+getDouble(ft))); - break; - case 3: // DIV.D - p(setDouble(fd,getDouble(fs)+"/"+getDouble(ft))); - break; - case 5: // ABS.D - p(setDouble(fd,"Math.abs("+getDouble(fs)+")")); - break; - case 6: // MOV.D - p("f"+fd+" = f"+fs+";"); - p("f"+(fd+1)+" = f"+(fs+1)+";"); - break; - case 7: // NEG.D - p(setDouble(fd,"-"+getDouble(fs))); // FEATURE: just flip the sign bit - break; - case 32: // CVT.S.D - p(setFloat(fd,"(float)"+getDouble(fs))); - break; - case 36: // CVT.W.D - 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; - case 50: // C.EQ.D - p("setFC("+getDouble(fs)+"=="+getDouble(ft)+");"); // FEATURE: just compare the ints, be sure things are normalized - break; - case 60: // C.LT.D - p("setFC("+getDouble(fs)+"<"+getDouble(ft)+");"); - break; - case 62: // C.LE.D - p("setFC("+getDouble(fs)+"<="+getDouble(ft)+");"); - break; - 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 - p("// CVT.D.W"); - p(setDouble(fd,"((double)f"+fs+")")); - break; - default: throw new CompilationException("Invalid Instruction 17/" + rs + "/" + subcode); - } - break; - } - default: - throw new CompilationException("Invalid Instruction 17/" + rs); - } - break; - } - case 18: case 19: - throw new CompilationException("coprocessor 2 and 3 instructions not available"); - case 32: { // LB - 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 - 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; - } - case 34: { // LWL; - 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 - memRead("r" + rs +"+"+signedImmediate,"r"+rt); - break; - case 36: { // LBU - 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 - 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 - 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 - 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 - 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 - 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 - memWrite("r"+rs+"+"+signedImmediate,"r" + rt); - break; - case 46: { // SWR - 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 - memRead("r"+rs+"+"+signedImmediate,"f"+rt); - break; - case 57: // SWC1 - memWrite("r"+rs+"+"+signedImmediate,"f"+rt); - break; - default: - throw new CompilationException("Invalid Instruction: " + op + " at " + toHex(pc)); - } - } - - 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 + ");"); - } - - 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)))"; - } - 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; }"; - } - - 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(); - } -} - diff --git a/src/org/xwt/mips/ELF.java b/src/org/xwt/mips/ELF.java deleted file mode 100644 index 5de3a0b..0000000 --- a/src/org/xwt/mips/ELF.java +++ /dev/null @@ -1,293 +0,0 @@ -package org.xwt.mips; -import java.io.*; - -public class ELF { - - private DataInput fd; - private Object image; - private void seek(long l) throws IOException { - if (image instanceof RandomAccessFile) { - ((RandomAccessFile)image).seek(l); - } else if (image instanceof byte[]) { - ByteArrayInputStream bais = new ByteArrayInputStream((byte[])image); - bais.skip(l); - fd = new DataInputStream(bais); - } - } - - public ELFHeader header; - public PHeader[] pheaders; - public SHeader[] sheaders; - - private byte[] stringTable; - - private boolean sectionReaderActive; - - public class ELFHeader { - byte klass; - byte data; - byte osabi; - byte abiversion; - - public static final short ET_EXEC = 2; - public short type; - public static final short EM_MIPS = 8; - public short machine; - public int version; - public int entry; - public int phoff; - public int shoff; - public int flags; - public short ehsize; - public short phentsize; - public short phnum; - public short shentsize; - public short shnum; - public short shstrndx; - - private static final int ELF_MAGIC = 0x7f454c46; // '\177', 'E', 'L', 'F' - ELFHeader() throws IOException { - if(fd.readInt() != ELF_MAGIC) throw new ELFException("Bad Magic (is: " ); - klass = fd.readByte(); - data = fd.readByte(); - fd.skipBytes(1); // version - osabi = fd.readByte(); - abiversion = fd.readByte(); - fd.skipBytes(7); - type = fd.readShort(); - machine = fd.readShort(); - version = fd.readInt(); - entry = fd.readInt(); - phoff = fd.readInt(); - shoff = fd.readInt(); - flags = fd.readInt(); - ehsize = fd.readShort(); - phentsize = fd.readShort(); - phnum = fd.readShort(); - shentsize = fd.readShort(); - shnum = fd.readShort(); - shstrndx = fd.readShort(); - } - } - - public class PHeader { - public int type; - public int offset; - public int vaddr; - public int paddr; - public int filesz; - public int memsz; - public int flags; - public int align; - - public static final int PF_X = 0x1; - public static final int PF_W = 0x2; - public static final int PF_R = 0x4; - - public static final int PT_LOAD = 1; - - PHeader() throws IOException { - type = fd.readInt(); - offset = fd.readInt(); - vaddr = fd.readInt(); - paddr = fd.readInt(); - filesz = fd.readInt(); - memsz = fd.readInt(); - flags = fd.readInt(); - align = fd.readInt(); - if(filesz > memsz) throw new ELFException("ELF inconsistency: filesz > memsz"); - } - - public boolean writable() { return (flags & PF_W) != 0; } - - public InputStream getInputStream() throws IOException { - return new BufferedInputStream(new SectionInputStream( - offset,offset+filesz)); - } - } - - public class SHeader { - int nameidx; - public String name; - public int type; - public int flags; - public int addr; - public int offset; - public int size; - public int link; - public int info; - public int addralign; - public int entsize; - - public static final int SHT_SYMTAB = 2; - public static final int SHT_STRTAB = 3; - public static final int SHT_NOBITS = 8; - - SHeader() throws IOException { - nameidx = fd.readInt(); - type = fd.readInt(); - flags = fd.readInt(); - addr = fd.readInt(); - offset = fd.readInt(); - size = fd.readInt(); - link = fd.readInt(); - info = fd.readInt(); - addralign = fd.readInt(); - entsize = fd.readInt(); - } - - public InputStream getInputStream() throws IOException { - return new BufferedInputStream(new SectionInputStream( - offset, type == SHT_NOBITS ? 0 : offset+size)); - } - } - - public ELF(Object img) throws IOException, ELFException { - if (img instanceof String) { - image = fd = new MyRandomAccessFile((String)img, "r"); - } else { - image = img; - } - seek(0); - header = new ELFHeader(); - pheaders = new PHeader[header.phnum]; - for(int i=0;i= header.shnum) throw new ELFException("Bad shstrndx"); - seek(sheaders[header.shstrndx].offset); - stringTable = new byte[sheaders[header.shstrndx].size]; - fd.readFully(stringTable); - - for(int i=0;i= 0) pos++; return b; } - public int read(byte[] b, int off, int len) throws IOException { - fd.readFully(b,off,Math.min(len,bytesLeft())); return len; - } - public void close() { sectionReaderActive = false; } - } - - private Symtab _symtab; - public Symtab getSymtab() throws IOException { - if(_symtab != null) return _symtab; - - SHeader sh = sectionWithName(".symtab"); - if(sh == null || sh.type != SHeader.SHT_SYMTAB) return null; - - SHeader sth = sectionWithName(".strtab"); - if(sth == null || sth.type != SHeader.SHT_STRTAB) return null; - - byte[] strtab = new byte[sth.size]; - DataInputStream dis = new DataInputStream(sth.getInputStream()); - dis.readFully(strtab); - dis.close(); - - return _symtab = new Symtab(sh.getInputStream(),sh.size,strtab); - } - - public class Symtab { - public Symbol[] symbols; - - Symtab(InputStream is, int size, byte[] strtab) throws IOException { - DataInputStream dis = new DataInputStream(is); - int count = size/16; - symbols = new Symbol[count]; - for(int i=0;i>> 32); fpregs[r] = (int)l; - } - private final float getFloat(int r) { return Float.intBitsToFloat(fpregs[r]); } - private final void setFloat(int r, float f) { fpregs[r] = Float.floatToRawIntBits(f); } - - protected void _execute() throws ExecutionException { runSome(); } - - // Main interpretor - // the return value is meaningless, its just to catch people typing "return" by accident - private final int runSome() throws FaultException,ExecutionException { - int[] r = registers; - int[] f = fpregs; - int pc = nextPC; - int nextPC = pc + 4; - try { - OUTER: for(;;) { - int insn; - try { - insn = readPages[pc>>>PAGE_SHIFT][(pc>>>2)&PAGE_WORDS-1]; - } catch (RuntimeException e) { - insn = memRead(pc); - } - - int op = (insn >>> 26) & 0xff; // bits 26-31 - int rs = (insn >>> 21) & 0x1f; // bits 21-25 - int rt = (insn >>> 16) & 0x1f; // bits 16-20 - int ft = (insn >>> 16) & 0x1f; - int rd = (insn >>> 11) & 0x1f; // bits 11-15 - int fs = (insn >>> 11) & 0x1f; - int shamt = (insn >>> 6) & 0x1f; // bits 6-10 - int fd = (insn >>> 6) & 0x1f; - int subcode = insn & 0x3f; // bits 0-5 - - int jumpTarget = (insn & 0x03ffffff); // bits 0-25 - int unsignedImmediate = insn & 0xffff; - int signedImmediate = (insn << 16) >> 16; - int branchTarget = signedImmediate; - - int tmp, addr; // temporaries - - r[ZERO] = 0; - - switch(op) { - case 0: { - switch(subcode) { - case 0: // SLL - if(insn == 0) break; - r[rd] = r[rt] << shamt; - break; - case 2: // SRL - r[rd] = r[rt] >>> shamt; - break; - case 3: // SRA - r[rd] = r[rt] >> shamt; - break; - case 4: // SLLV - r[rd] = r[rt] << (r[rs]&0x1f); - break; - case 6: // SRLV - r[rd] = r[rt] >>> (r[rs]&0x1f); - break; - case 7: // SRAV - r[rd] = r[rt] >> (r[rs]&0x1f); - break; - case 8: // JR - tmp = r[rs]; pc += 4; nextPC = tmp; - continue OUTER; - case 9: // JALR - tmp = r[rs]; pc += 4; r[rd] = pc+4; nextPC = tmp; - continue OUTER; - case 12: // SYSCALL - r[V0] = syscall(r[V0],r[A0],r[A1],r[A2],r[A3]); - if(state != RUNNING) { - this.nextPC = nextPC; - break OUTER; - } - break; - case 13: // BREAK - throw new ExecutionException("Break"); - case 16: // MFHI - r[rd] = hi; - break; - case 17: // MTHI - hi = r[rs]; - break; - case 18: // MFLO - r[rd] = lo; - break; - case 19: // MTLO - lo = r[rs]; - break; - case 24: { // MULT - long hilo = (long)(r[rs]) * ((long)r[rt]); - hi = (int) (hilo >>> 32); - lo = (int) hilo; - break; - } - case 25: { // MULTU - long hilo = (r[rs] & 0xffffffffL) * (r[rt] & 0xffffffffL); - hi = (int) (hilo >>> 32); - lo = (int) hilo; - break; - } - case 26: // DIV - hi = r[rs]%r[rt]; - lo = r[rs]/r[rt]; - break; - case 27: // DIVU - hi = (int)((r[rs] & 0xffffffffL) % (r[rt] & 0xffffffffL)); - lo = (int)((r[rs] & 0xffffffffL) / (r[rt] & 0xffffffffL)); - break; - case 32: // ADD - throw new ExecutionException("ADD (add with oveflow trap) not suported"); - /*This must trap on overflow - r[rd] = r[rs] + r[rt]; - break;*/ - case 33: // ADDU - r[rd] = r[rs] + r[rt]; - break; - case 34: // SUB - throw new ExecutionException("SUB (sub with oveflow trap) not suported"); - /*This must trap on overflow - r[rd] = r[rs] - r[rt]; - break;*/ - case 35: // SUBU - r[rd] = r[rs] - r[rt]; - break; - case 36: // AND - r[rd] = r[rs] & r[rt]; - break; - case 37: // OR - r[rd] = r[rs] | r[rt]; - break; - case 38: // XOR - r[rd] = r[rs] ^ r[rt]; - break; - case 39: // NOR - r[rd] = ~(r[rs] | r[rt]); - break; - case 42: // SLT - r[rd] = r[rs] < r[rt] ? 1 : 0; - break; - case 43: // SLTU - r[rd] = ((r[rs] & 0xffffffffL) < (r[rt] & 0xffffffffL)) ? 1 : 0; - break; - default: - throw new ExecutionException("Illegal instruction 0/" + subcode); - } - break; - } - case 1: { - switch(rt) { - case 0: // BLTZ - if(r[rs] < 0) { - pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; - continue OUTER; - } - break; - case 1: // BGEZ - if(r[rs] >= 0) { - pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; - continue OUTER; - } - break; - case 16: // BLTZAL - if(r[rs] < 0) { - pc += 4; r[RA] = pc+4; tmp = pc + branchTarget*4; nextPC = tmp; - continue OUTER; - } - break; - case 17: // BGEZAL - if(r[rs] >= 0) { - pc += 4; r[RA] = pc+4; tmp = pc + branchTarget*4; nextPC = tmp; - continue OUTER; - } - break; - default: - throw new ExecutionException("Illegal Instruction"); - } - break; - } - case 2: { // J - tmp = (pc&0xf0000000) | (jumpTarget << 2); - pc+=4; nextPC = tmp; - continue OUTER; - } - case 3: { // JAL - tmp = (pc&0xf0000000) | (jumpTarget << 2); - pc+=4; r[RA] = pc+4; nextPC = tmp; - continue OUTER; - } - case 4: // BEQ - if(r[rs] == r[rt]) { - pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; - continue OUTER; - } - break; - case 5: // BNE - if(r[rs] != r[rt]) { - pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; - continue OUTER; - } - break; - case 6: //BLEZ - if(r[rs] <= 0) { - pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; - continue OUTER; - } - break; - case 7: //BGTZ - if(r[rs] > 0) { - pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; - continue OUTER; - } - break; - case 8: // ADDI - r[rt] = r[rs] + signedImmediate; - break; - case 9: // ADDIU - r[rt] = r[rs] + signedImmediate; - break; - case 10: // SLTI - r[rt] = r[rs] < signedImmediate ? 1 : 0; - break; - case 11: // SLTIU - r[rt] = (r[rs]&0xffffffffL) < (unsignedImmediate&0xffffffffL) ? 1 : 0; - break; - case 12: // ANDI - r[rt] = r[rs] & unsignedImmediate; - break; - case 13: // ORI - r[rt] = r[rs] | unsignedImmediate; - break; - case 14: // XORI - r[rt] = r[rs] ^ unsignedImmediate; - break; - case 15: // LUI - r[rt] = unsignedImmediate << 16; - break; - case 16: - throw new ExecutionException("TLB/Exception support not implemented"); - case 17: { // FPU - boolean debug = false; - String line = ""; - boolean debugon = debug && (line.indexOf("dtoa.c:51") >= 0 || line.indexOf("dtoa.c:52") >= 0 || line.indexOf("test.c") >= 0); - if(rs > 8 && debugon) - System.out.println(" FP Op: " + op + "/" + rs + "/" + subcode + " " + line); - // FEATURE: This could probably be removed. I don't think gcc will ever generate code that does this - if(roundingMode() != 0 && rs != 6 /*CTC.1*/ && !((rs==16 || rs==17) && subcode == 36 /* CVT.W.Z */)) - throw new ExecutionException("Non-cvt.w.z operation attempted with roundingMode != round to nearest"); - switch(rs) { - case 0: // MFC.1 - r[rt] = f[rd]; - break; - case 2: // CFC.1 - if(fs != 31) throw new ExecutionException("FCR " + fs + " unavailable"); - r[rt] = fcsr; - break; - case 4: // MTC.1 - f[rd] = r[rt]; - break; - case 6: // CTC.1 - if(fs != 31) throw new ExecutionException("FCR " + fs + " unavailable"); - fcsr = r[rt]; - break; - case 8: // BC1F, BC1T - if(((fcsr&0x800000)!=0) == (((insn>>>16)&1)!=0)) { - pc += 4; tmp = pc + branchTarget*4; nextPC = tmp; - continue OUTER; - } - break; - case 16: { // Single - switch(subcode) { - case 0: // ADD.S - setFloat(fd,getFloat(fs)+getFloat(ft)); - break; - case 1: // SUB.S - setFloat(fd,getFloat(fs)-getFloat(ft)); - break; - case 2: // MUL.S - setFloat(fd,getFloat(fs)*getFloat(ft)); - break; - case 3: // DIV.S - setFloat(fd,getFloat(fs)/getFloat(ft)); - break; - case 5: // ABS.S - setFloat(fd,Math.abs(getFloat(fs))); - break; - case 6: // MOV.S - f[fd] = f[fs]; - break; - case 7: // NEG.S - setFloat(fd,-getFloat(fs)); // FEATURE: just flip the sign bit - break; - case 33: // CVT.D.S - setDouble(fd,getFloat(fs)); - break; - case 36: // CVT.W.S - switch(roundingMode()) { - case 0: f[fd] = (int)Math.floor(getFloat(fs)+0.5f); break; // Round to nearest - case 1: f[fd] = (int)getFloat(fs); break; // Round towards zero - case 2: f[fd] = (int)Math.ceil(getFloat(fs)); break; // Round towards plus infinity - case 3: f[fd] = (int)Math.floor(getFloat(fs)); break; // Round towards minus infinity - } - break; - case -50: // C.EQ.S - 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)); - break; - default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode); - } - break; - } - case 17: { // Double - switch(subcode) { - case 0: // ADD.D - setDouble(fd,getDouble(fs)+getDouble(ft)); - break; - case 1: // SUB.D - if(debugon) System.out.println("f" + fd + " = f" + fs + " (" + getDouble(fs) + ") - f" + ft + " (" + getDouble(ft) + ")"); - setDouble(fd,getDouble(fs)-getDouble(ft)); - break; - case 2: // MUL.D - if(debugon) System.out.println("f" + fd + " = f" + fs + " (" + getDouble(fs) + ") * f" + ft + " (" + getDouble(ft) + ")"); - setDouble(fd,getDouble(fs)*getDouble(ft)); - if(debugon) System.out.println("f" + fd + " = " + getDouble(fd)); - break; - case 3: // DIV.D - setDouble(fd,getDouble(fs)/getDouble(ft)); - break; - case 5: // ABS.D - setDouble(fd,Math.abs(getDouble(fs))); - break; - case 6: // MOV.D - f[fd] = f[fs]; - f[fd+1] = f[fs+1]; - break; - case 7: // NEG.D - setDouble(fd,-getDouble(fs)); // FEATURE: just flip the sign bit - break; - case 32: // CVT.S.D - setFloat(fd,(float)getDouble(fs)); - break; - case 36: // CVT.W.D - if(debugon) System.out.println("CVT.W.D rm: " + roundingMode() + " f" + fs + ":" + getDouble(fs)); - switch(roundingMode()) { - case 0: f[fd] = (int)Math.floor(getDouble(fs)+0.5); break; // Round to nearest - case 1: f[fd] = (int)getDouble(fs); break; // Round towards zero - case 2: f[fd] = (int)Math.ceil(getDouble(fs)); break; // Round towards plus infinity - case 3: f[fd] = (int)Math.floor(getDouble(fs)); break; // Round towards minus infinity - } - if(debugon) System.out.println("CVT.W.D: f" + fd + ":" + f[fd]); - break; - case 50: // C.EQ.D - 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)); - break; - case 62: // C.LE.D - setFC(getDouble(fs) <= getDouble(ft)); - break; - default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode); - } - break; - } - case 20: { // Integer - switch(subcode) { - case 33: // CVT.D.W - setDouble(fd,(double)f[fs]); - break; - default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode); - } - break; - } - default: - throw new ExecutionException("Invalid Instruction 17/" + rs); - } - break; - } - case 18: case 19: - throw new ExecutionException("No coprocessor installed"); - case 32: { // LB - addr = r[rs] + signedImmediate; - try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; - } catch(RuntimeException e) { - tmp = memRead(addr&~3); - } - switch(addr&3) { - case 0: tmp = (tmp>>>24)&0xff; break; - case 1: tmp = (tmp>>>16)&0xff; break; - case 2: tmp = (tmp>>> 8)&0xff; break; - case 3: tmp = (tmp>>> 0)&0xff; break; - } - if((tmp&0x80)!=0) tmp |= 0xffffff00; // sign extend - r[rt] = tmp; - break; - } - case 33: { // LH - addr = r[rs] + signedImmediate; - try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; - } catch(RuntimeException e) { - tmp = memRead(addr&~3); - } - switch(addr&2) { - case 0: tmp = (tmp>>>16)&0xffff; break; - case 2: tmp = (tmp>>> 0)&0xffff; break; - } - if((tmp&0x8000)!=0) tmp |= 0xffff0000; // sign extend - r[rt] = tmp; - break; - } - case 34: { // LWL; - addr = r[rs] + signedImmediate; - try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; - } catch(RuntimeException e) { - 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; - } - 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); - } - break; - case 36: { // LBU - addr = r[rs] + signedImmediate; - try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; - } catch(RuntimeException e) { - 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; - } - case 37: { // LHU - addr = r[rs] + signedImmediate; - try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; - } catch(RuntimeException e) { - tmp = memRead(addr&~3); - } - switch(addr&2) { - case 0: r[rt] = (tmp>>>16)&0xffff; break; - case 2: r[rt] = (tmp>>> 0)&0xffff; break; - } - break; - } - case 38: { // LWR - addr = r[rs] + signedImmediate; - try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; - } catch(RuntimeException e) { - 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; - } - break; - } - case 40: { // SB - addr = r[rs] + signedImmediate; - try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; - } catch(RuntimeException e) { - tmp = memRead(addr&~3); - } - switch(addr&3) { - case 0: tmp = (tmp&0x00ffffff) | ((r[rt]&0xff)<<24); break; - case 1: tmp = (tmp&0xff00ffff) | ((r[rt]&0xff)<<16); break; - case 2: tmp = (tmp&0xffff00ff) | ((r[rt]&0xff)<< 8); break; - case 3: 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); - } - break; - } - case 41: { // SH - addr = r[rs] + signedImmediate; - try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; - } catch(RuntimeException e) { - tmp = memRead(addr&~3); - } - switch(addr&2) { - case 0: tmp = (tmp&0x0000ffff) | ((r[rt]&0xffff)<<16); break; - case 2: 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); - } - break; - } - case 42: { // SWL - addr = r[rs] + signedImmediate; - 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); - } - 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]); - } - break; - case 46: { // SWR - addr = r[rs] + signedImmediate; - 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); - break; - } - case 49: // LWC1 - f[rt] = memRead(r[rs] + signedImmediate); - break; - case 57: // SWC1 - memWrite(r[rs] + signedImmediate,f[rt]); - break; - default: - throw new ExecutionException("Invalid Instruction: " + op); - } - pc = nextPC; - nextPC = pc + 4; - } // for(;;) - } catch(ExecutionException e) { - this.nextPC = pc; - throw e; - } - return 0; - } - - // Image loading function - void loadImage(Object file) throws IOException { - ELF elf = new ELF(file); - 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"); - entryPoint = elf.header.entry; - ELF.PHeader[] pheaders = elf.pheaders; - brk = 0; - for(int i=0;i= (brk<> PAGE_SHIFT; - - for(int j=0;j>> PAGE_SHIFT; - if(readPages[page] == null) - readPages[page] = new int[PAGE_WORDS]; - if(ph.writable()) writePages[page] = readPages[page]; - } - if(filesize != 0) { - filesize = filesize & ~3; - DataInputStream dis = new DataInputStream(ph.getInputStream()); - do { - readPages[addr >>> PAGE_SHIFT][(addr >>> 2)&(PAGE_WORDS-1)] = dis.readInt(); - addr+=4; - filesize-=4; - } while(filesize > 0); - dis.close(); - } - } - state = INITIALIZED; - } - - protected void _start(int pc) { - registers[K0] = STUFF_BASE; - registers[K1] = PAGE_SIZE; - registers[SP] = INITIAL_SP; - registers[RA] = 0xdeadbeef; - nextPC = pc; - } - public Interpreter() { super(true); /* allow empty pages */ } - public Interpreter(String filename) throws IOException { loadImage(filename); } - public Interpreter(byte[] bytes) throws IOException { loadImage(bytes); } - - public class DebugShutdownHook implements Runnable { - public void run() { - int pc = nextPC; - if(getState() == RUNNING) - System.err.print("\nCPU Executing " + toHex(pc) + "\n"); - } - } - - public static void main(String[] argv) throws Exception { - String image = argv[0]; - Interpreter emu = new Interpreter(); - emu.loadImage(image); - java.lang.Runtime.getRuntime().addShutdownHook(new Thread(emu.new DebugShutdownHook())); - // User data - int addr = emu.sbrk(PAGE_SIZE); - for(int i=0;i<10;i++) { - String s = "User Info item: " + (i+1) + "\0"; - byte[] b = s.getBytes("US-ASCII"); - emu.copyout(b,addr,b.length); - emu.setUserInfo(i,addr); - addr += b.length; - } - // End user data - int status = emu.run(argv); - System.err.println("Exit status: " + status); - System.exit(status); - } -} diff --git a/src/org/xwt/mips/Registers.java b/src/org/xwt/mips/Registers.java deleted file mode 100644 index 79603c4..0000000 --- a/src/org/xwt/mips/Registers.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.xwt.mips; -interface Registers { - // Register Names - public final static int ZERO = 0; // Immutable, hardwired to 0 - public final static int AT = 1; // Reserved for assembler - public final static int K0 = 26; // Reserved for kernel - public final static int K1 = 27; // Reserved for kernel - public final static int GP = 28; // Global pointer (the middle of .sdata/.sbss) - public final static int SP = 29; // Stack pointer - public final static int FP = 30; // Frame Pointer - public final static int RA = 31; // Return Address - - // Return values (caller saved) - public final static int V0 = 2; - public final static int V1 = 3; - // Argument Registers (caller saved) - public final static int A0 = 4; - public final static int A1 = 5; - public final static int A2 = 6; - public final static int A3 = 7; - // Temporaries (caller saved) - public final static int T0 = 8; - public final static int T1 = 9; - public final static int T2 = 10; - public final static int T3 = 11; - public final static int T4 = 12; - public final static int T5 = 13; - public final static int T6 = 14; - public final static int T7 = 15; - public final static int T8 = 24; - public final static int T9 = 25; - // Saved (callee saved) - public final static int S0 = 16; - public final static int S1 = 17; - public final static int S2 = 18; - public final static int S3 = 19; - public final static int S4 = 20; - public final static int S5 = 21; - public final static int S6 = 22; - public final static int S7 = 23; -} diff --git a/src/org/xwt/mips/Runtime.java b/src/org/xwt/mips/Runtime.java deleted file mode 100644 index be050bf..0000000 --- a/src/org/xwt/mips/Runtime.java +++ /dev/null @@ -1,771 +0,0 @@ -// Copyright 2003 Brian Alliet -// Based on org.xwt.imp.MIPS by Adam Megacz -// Portions Copyright 2003 Adam Megacz -package org.xwt.mips; -import java.io.*; - -public abstract class Runtime implements Syscalls, Errno,Registers { - /** Pages are 4k in size */ - public final static int PAGE_SIZE = 4096; - public final static int PAGE_WORDS = (int)(PAGE_SIZE >>> 2); - public final static int PAGE_SHIFT = 12; - /** There are 65536 pages available for a total of 256mb of addressable memory */ - protected final static int TOTAL_PAGES = 65536; - /** The top 256 pages are reserved for the stack. Arguments and userdata info use up the first few pages */ - protected final static int STACK_PAGES = 256; - /** This is the upper limit of the pages allocated by the brk() syscall. */ - protected final static int BRK_LIMIT = TOTAL_PAGES - STACK_PAGES - 1024; - - /* High memory layout - TOP - <-- ((TOTAL_PAGES-0)*PAGE_SIZE) --> - Empty Page - <-- ((TOTAL_PAGES-1)*PAGE_SIZE) --> - Args (1 page) - <-- ((TOTAL_PAGES-2)*PAGE_SIZE) --> - User info (1 page) - <-- ((TOTAL_PAGES-3)*PAGE_SIZE) --> - Empty page - <-- ((TOTAL_PAGES-4)*PAGE_SIZE) --> - Stack top - */ - - /** The base address for the args and user_info (this will be passed to crt0.c) - The args must be at STUFF_BASE+1 page and user_info must be at STUFF_BASE */ - protected final static int STUFF_BASE = (TOTAL_PAGES-3)*PAGE_SIZE; - protected final static int ARGS_ADDR = STUFF_BASE + PAGE_SIZE; - protected final static int USER_INFO_ADDR = STUFF_BASE; - - /** The initial stack pointer address */ - protected final static int INITIAL_SP = STUFF_BASE - PAGE_SIZE; - - /** True if we allow empty pages (_emptyPage) to exist in memory. - Empty pages are pages which are allocated by the program but do not contain any - data yet (they are all 0s). If empty pages are allowed subclasses must always - access main memory with the memRead and memWrite functions */ - private final boolean allowEmptyPages; - /** the "empty page" */ - private final static int[] _emptyPage = new int[0]; - - /** Returns a new empty page (_emptyPage is empty pages are enabled or a new zero'd page) */ - private final int[] emptyPage() { return allowEmptyPages ? _emptyPage : new int[PAGE_WORDS]; } - - /** Readable main memory pages */ - protected final int[][] readPages; - /** Writable main memory pages. - If the page is writable writePages[x] == readPages[x]; if not writePages[x] == null. */ - protected final int[][] writePages; - - /** The current break between the heap and unallocated memory and the stack. - This is the page number NOT an address */ - protected int brk; - - /** The program's entry point */ - protected int entryPoint; - - /** State contant: There is no program loaded in memory */ - public final static int UNINITIALIZED = 0; - /** Text/Data loaded in memory */ - public final static int INITIALIZED = 1; - /** Program is executing instructions */ - public final static int RUNNING = 2; - /** Prgram has been started but is paused */ - public final static int PAUSED = 3; - /** Program has exited (it cannot currently be restarted) */ - public final static int DONE = 4; - - /** The current state (UNINITIALIZED, INITIALIZED, RUNNING, PAUSED, or DONE) */ - protected int state = UNINITIALIZED; - /** @see Runtime#state state */ - public final int getState() { return state; } - - /** The exit status if the process (only valid if state==DONE) - @see Runtime#state */ - protected int exitStatus; - - /** Maximum number of open file descriptors */ - private final static int OPEN_MAX = 256; - /** Table containing all open file descriptors. (Entries are null if the fd is not in use */ - private FileDescriptor[] fds; - - /** Temporary buffer for read/write operations */ - private byte[] _byteBuf = null; - /** Max size of temporary buffer - @see Runtime#_byteBuf */ - private final static int MAX_CHUNK = 4*1024*1024; - - /** The pid of this "process" */ - public static final int PID = 1; - - /** Subclasses should actually execute program in this method. They should continue - executing until state != RUNNING. Only syscall() can modify state. It is safe - to only check the state attribyte after a call to syscall() */ - protected abstract void _execute() throws ExecutionException; - - /** This should setup the system to begin executing at pc and - initialize the cpu registers as follows - K0 (r26) = STUFF_BASE - K1 (r27) = PAGE_SIZE - SP (r29) = INITIAL_SP - RA (r31) = 0xdeadbeef - */ - protected abstract void _start(int pc); - - /** Initialize the Runtime with empty pages disabled - @see Runtime#Runtime(boolean) */ - public Runtime() { this(false); } - - /** Initialize the Runtime. Empty pages are enabled if allowEmptyPages is set */ - public Runtime(boolean allowEmptyPages) { - this.allowEmptyPages = allowEmptyPages; - readPages = new int[TOTAL_PAGES][]; - writePages = new int[TOTAL_PAGES][]; - for(int i=0;isrc to addr initializing uninitialized pages if required. - Newly initalized pages will be marked read-only if ro is set */ - protected final void initPages(int[] src, int addr, boolean ro) { - for(int i=0;i>> PAGE_SHIFT; - int start = (addr&(PAGE_SIZE-1))>>2; - int elements = min(PAGE_WORDS-start,src.length-i); - if(readPages[page]==null) { - initPage(page,ro); - } else if(!ro) { - if(writePages[page] == null) writePages[page] = readPages[page]; - } - System.arraycopy(src,i,readPages[page],start,elements); - i += elements; - addr += elements*4; - } - } - - /** Initialize words of pages starting at addr to 0 */ - protected final void clearPages(int addr, int words) { - for(int i=0;i>> PAGE_SHIFT; - int start = (addr&(PAGE_SIZE-1))>>2; - int elements = min(PAGE_WORDS-start,words-i); - if(readPages[page]==null) { - readPages[page] = writePages[page] = emptyPage(); - } else { - if(writePages[page] == null) writePages[page] = readPages[page]; - for(int j=start;jlength bytes from the processes memory space starting at - addr INTO a java byte array a */ - public final void copyin(int addr, byte[] a, int length) throws ReadFaultException { - int n=0; - if((addr&3)!=0) { - int word = memRead(addr&~3); - switch(addr&3) { - case 1: a[n++] = (byte)((word>>>16)&0xff); if(length-n==0) break; - case 2: a[n++] = (byte)((word>>> 8)&0xff); if(length-n==0) break; - case 3: a[n++] = (byte)((word>>> 0)&0xff); if(length-n==0) break; - } - addr = (addr&~3)+4; - } - while(length-n > 3) { - int start = (addr&(PAGE_SIZE-1))>>2; - int end = start + (min(PAGE_SIZE-(addr&(PAGE_SIZE-1)),(length-n)&~3) >> 2); - int[] page = readPages[addr >>> PAGE_SHIFT]; - if(page == null) throw new ReadFaultException(addr); - if(page == _emptyPage) { addr+=(end-start)<<2; n+=(end-start)<<2; continue; } - for(int i=start;i>>24)&0xff); a[n++] = (byte)((word>>>16)&0xff); - a[n++] = (byte)((word>>> 8)&0xff); a[n++] = (byte)((word>>> 0)&0xff); - } - } - if(length-n > 0) { - int word = memRead(addr); - if(length-n >= 1) a[n+0] = (byte)((word>>>24)&0xff); - if(length-n >= 2) a[n+1] = (byte)((word>>>16)&0xff); - if(length-n >= 3) a[n+2] = (byte)((word>>> 8)&0xff); - } - } - - /** Copies length bytes OUT OF the java array a into the processes memory - space at addr */ - public final void copyout(byte[] a, int addr, int length) throws FaultException { - int n=0; - if((addr&3)!=0) { - int word = memRead(addr&~3); - switch(addr&3) { - case 1: word = (word&0xff00ffff)|((a[n]&0xff)<<16); n++; if(length-n==0) break; - case 2: word = (word&0xffff00ff)|((a[n]&0xff)<< 8); n++; if(length-n==0) break; - case 3: word = (word&0xffffff00)|((a[n]&0xff)<< 0); n++; if(length-n==0) break; - } - memWrite(addr&~3,word); - addr = (addr&~3)+4; - } - - while(length-n > 3) { - int start = (addr&(PAGE_SIZE-1))>>2; - int end = start + (min(PAGE_SIZE-(addr&(PAGE_SIZE-1)),(length-n)&~3) >> 2); - int[] page = writePages[addr >>> PAGE_SHIFT]; - if(page == null) throw new WriteFaultException(addr); - if(page == _emptyPage) { memWrite(addr,0); page = writePages[addr >>> PAGE_SHIFT]; } - for(int i=start;i 0) { - int word = memRead(addr); - if(length-n >= 1) { word = (word&0x00ffffff)|((a[n+0]&0xff)<<24); } - if(length-n >= 2) { word = (word&0xff00ffff)|((a[n+1]&0xff)<<16); } - if(length-n >= 3) { word = (word&0xffff00ff)|((a[n+2]&0xff)<< 8); } - memWrite(addr,word); - } - } - - /** Read a word from the processes memory at addr */ - public final int memRead(int addr) throws ReadFaultException { - if((addr & 3) != 0) throw new ReadFaultException(addr); - int page = addr >>> PAGE_SHIFT; - int entry = (addr >>> 2) & (PAGE_WORDS-1); - try { - return readPages[page][entry]; - } catch(ArrayIndexOutOfBoundsException e) { - if(page < 0) throw e; // should never happen - if(page > readPages.length) throw new ReadFaultException(addr); - if(readPages[page] != _emptyPage) throw e; // should never happen - initPage(page); - return 0; - } catch(NullPointerException e) { - throw new ReadFaultException(addr); - } - } - - /** Writes a word to the processes memory at addr */ - public final void memWrite(int addr, int value) throws WriteFaultException { - if((addr & 3) != 0) throw new WriteFaultException(addr); - int page = addr >>> PAGE_SHIFT; - int entry = (addr>>>2)&(PAGE_WORDS-1); - try { - writePages[page][entry] = value; - } catch(ArrayIndexOutOfBoundsException e) { - if(page < 0) throw e;// should never happen - if(page > writePages.length) throw new WriteFaultException(addr); - if(readPages[page] != _emptyPage) throw e; // should never happen - initPage(page); - writePages[page][entry] = value; - } catch(NullPointerException e) { - throw new WriteFaultException(addr); - } - } - - /** Created a new non-empty writable page at page number page */ - private final void initPage(int page) { initPage(page,false); } - /** Created a new non-empty page at page number page. If ro is set the page will be read-only */ - private final void initPage(int page, boolean ro) { - int[] buf = new int[PAGE_WORDS]; - writePages[page] = ro ? null : buf; - readPages[page] = buf; - } - - /** Returns the exit status of the process. (only valid if state == DONE) - @see Runtime#state */ - public final int exitStatus() { - if(state != DONE) throw new IllegalStateException("exitStatus() called in an inappropriate state"); - return exitStatus; - } - - /** Runs the process until it exits and returns the exit status. - If the process executes the PAUSE syscall execution will be paused for 500ms and a warning will be displayed */ - public final int run(String[] args) throws ExecutionException { - start(args); - for(;;) { - if(execute()) break; - System.err.println("WARNING: Pause requested while executing run()"); - try { Thread.sleep(500); } catch(InterruptedException e) { } - } - return exitStatus(); - } - - /** Adds the String[] array, args, to the arguments page in main memory */ - private void addArgs(String[] args) throws ExecutionException { - int count = args.length; - byte[] nullTerminator = new byte[1]; - int total = 4; /* null last table entry */ - for(int i=0;i= PAGE_SIZE-4) throw new ExecutionException("Arguments too large"); - int start = ARGS_ADDR; - int addr = start + (count+1)*4; - int[] table = new int[count+1]; - for(int i=0;iindex in the _user_info table to word - _user_info is a 4096 byte table in the process's memory. It contains 1024 32-bit entries. This - can be used by the process to communicate with the caller of the process. Each entry is 32-bit - wide and can be used to store integers or pointers */ - public void setUserInfo(int index, int word) { - if(index < 0 || index >= 1024) throw new IllegalStateException("setUserInfo called with index >= 1024"); - try { - memWrite(USER_INFO_ADDR+index*4,word); - } catch(FaultException e) { throw new Error("should never happen: " + e); } - } - - /** Returns the word in the _user_info table entry index - @see Runtime#setUserInfo(int,int) setUserInfo */ - public int getUserInfo(int index) { - if(index < 0 || index >= 1024) throw new IllegalStateException("setUserInfo called with index >= 1024"); - try { - return memRead(USER_INFO_ADDR+index*4); - } catch(FaultException e) { throw new Error("should never happen: " + e); } - } - - /** Executes the process until the PAUSE syscall is invoked or the process exits. Returns true if the process exited. */ - public final boolean execute() throws ExecutionException { - if(state == PAUSED) state = RUNNING; - if(state != RUNNING) throw new IllegalStateException("execute() called in inappropriate state"); - _execute(); - if(state != PAUSED && state != DONE) throw new IllegalStateException("execute() ended up in an inappropriate state"); - return state == DONE; - } - - /** Initializes the process and prepairs it to be executed with execute() */ - public final void start(String[] args) throws ExecutionException { - if(state != INITIALIZED) throw new IllegalStateException("start() called in inappropriate state"); - _start(entryPoint); - addArgs(args); - fds = new FileDescriptor[OPEN_MAX]; - fds[0] = new InputStreamFD(System.in) { public boolean isatty() { return true; } }; - fds[1] = new OutputStreamFD(System.out) { public boolean isatty() { return true; } }; - fds[2] = new OutputStreamFD(System.err) { public boolean isatty() { return true; } }; - state = PAUSED; - } - - /** Determines if the process can access fileName. The default implementation simply logs - the request and allows it */ - protected boolean allowFileAccess(String fileName, boolean write) { - System.err.println("Allowing " + (write?"write":"read-only") + " to " + fileName); - return true; - } - - /** Allocated an entry in the FileDescriptor table for fd and returns the number. - Returns -1 if the table is full. This can be used by subclasses to use custom file - descriptors */ - protected int allocFDEnt(FileDescriptor fd) { - int i; - for(i=0;i= Integer.MAX_VALUE) return -EOPNOTSUPP; - } else { - if((flags & O_CREAT) == 0) return -ENOENT; - } - int fdn = allocFDEnt(new RegularFileDescriptor(f,flags&3)); - return fdn == -1 ? -ENFILE : fdn; - } catch(FaultException e) { - return -EFAULT; - } catch(FileNotFoundException e) { - if(e.getMessage().indexOf("Permission denied") >= 0) return -EACCES; - return -ENOENT; - } catch(IOException e) { - return -EIO; - } - } - - /** The write syscall */ - private int sys_write(int fdn, int addr, int count) { - int n = 0; - int r; - FileDescriptor fd; - count = Math.min(count,MAX_CHUNK); - try { - fd = fds[fdn]; - if(fd == null || !fd.writable()) return -EBADFD; - } catch(ArrayIndexOutOfBoundsException e) { - return -EBADFD; - } - try { - byte[] buf = byteBuf(count); - copyin(addr,buf,count); - return fd.write(buf,0,count); - } catch(FaultException e) { - System.err.println(e); - return -EFAULT; - } catch(IOException e) { - System.err.println(e); - return -EIO; - } - } - - /** The read syscall */ - private int sys_read(int fdn, int addr, int count) { - FileDescriptor fd; - count = Math.min(count,MAX_CHUNK); - try { - fd = fds[fdn]; - if(fd == null || !fd.readable()) return -EBADFD; - } catch(ArrayIndexOutOfBoundsException e) { - return -EBADFD; - } - try { - byte[] buf = byteBuf(count); - int n = fd.read(buf,0,count); - copyout(buf,addr,n); - return n; - } catch(FaultException e) { - System.err.println(e); - return -EFAULT; - } catch(IOException e) { - System.err.println(e); - return -EIO; - } - } - - /** The close syscall */ - private int sys_close(int fdn) { - FileDescriptor fd; - try { - fd = fds[fdn]; - if(fd == null) return -EBADFD; - } catch(ArrayIndexOutOfBoundsException e) { - return -EBADFD; - } - fds[fdn] = null; - fd.close(); - return 0; - } - - /** The seek syscall */ - private int sys_seek(int fdn, int offset, int whence) { - FileDescriptor fd; - try { - fd = fds[fdn]; - if(fd == null || !fd.readable()) return -EBADFD; - } catch(ArrayIndexOutOfBoundsException e) { - return -EBADFD; - } - if(whence != FileDescriptor.SEEK_SET && whence != FileDescriptor.SEEK_CUR && whence != FileDescriptor.SEEK_END) return -EINVAL; - try { - int n = fd.seek(offset,whence); - return n < 0 ? -ESPIPE : n; - } catch(IOException e) { - return -ESPIPE; - } - } - - /** The stat/fstat syscall helper */ - private int stat(FileInfo fi, int addr) { - int size = fi.size(); - try { - memWrite(addr+0,(1<<16)|1); // st_dev (top 16), // st_ino (bottom 16) - memWrite(addr+4,(fi.type() & 0xf000)|0644); // st_mode - memWrite(addr+8,1<<16); // st_nlink (top 16) // st_uid (bottom 16) - memWrite(addr+12,0); // st_gid (top 16) // st_rdev (bottom 16) - memWrite(addr+16,size); // st_size - memWrite(addr+20,0); // st_atime - // memWrite(addr+24,0) // st_spare1 - memWrite(addr+28,(int)(fi.modTime()/1000)); // st_mtime - // memWrite(addr+32,0) // st_spare2 - memWrite(addr+36,0); // st_ctime - // memWrite(addr+40,0) // st_spare3 - memWrite(addr+44,512); // st_bklsize; - memWrite(addr+48,(size+511)&(~511)); // st_blocks - // memWrite(addr+52,0) // st_spare4[0] - // memWrite(addr+56,0) // st_spare4[1] - } catch(FaultException e) { - System.err.println(e); - return -EFAULT; - } - return 0; - } - - /** The fstat syscall */ - private int sys_fstat(int fdn, int addr) { - FileDescriptor fd; - try { - fd = fds[fdn]; - if(fd == null) return -EBADFD; - } catch(ArrayIndexOutOfBoundsException e) { - return -EBADFD; - } - return stat(fd.fileInfo(),addr); - } - - /** The sbrk syscall. This can also be used by subclasses to allocate memory. - incr is how much to increase the break by */ - public int sbrk(int incr) { - if(incr==0) return brk<>PAGE_SHIFT); - if(newBrk >= BRK_LIMIT) { - System.err.println("Hit BRK_LIMIT"); - return -ENOMEM; - } - for(int i=oldBrk;i= 32) return -EINVAL; - switch(signal) { - case 0: return 0; - case 17: // SIGSTOP - case 18: // SIGTSTP - case 21: // SIGTTIN - case 22: // SIGTTOU - state = PAUSED; - break; - case 19: // SIGCONT - case 20: // SIGCHLD - case 23: // SIGIO - case 28: // SIGWINCH - break; - default: { - String msg = "Terminating on signal: " + signal + "\n"; - exitStatus = 1; - state = DONE; - if(fds[2]==null) { - System.out.print(msg); - } else { - try { - byte[] b = msg.getBytes("US-ASCII"); - fds[2].write(b,0,b.length); - } - catch(UnsupportedEncodingException e){ throw new Error(e.getMessage()); } - catch(IOException e) { } - } - } - } - return 0; - } - - /** The getpid syscall */ - private int sys_getpid() { return PID; } - - /** The syscall dispatcher. - The should be called by subclasses when the syscall instruction is invoked. - syscall should be the contents of V0 and a, b, c, and d should be - the contenst of A0, A1, A2, and A3. The call MAY change the state - @see Runtime#state state */ - protected int syscall(int syscall, int a, int b, int c, int d) { - switch(syscall) { - case SYS_null: return 0; - case SYS_exit: exitStatus = a; state = DONE; return 0; - case SYS_pause: state = PAUSED; return 0; - case SYS_write: return sys_write(a,b,c); - case SYS_fstat: return sys_fstat(a,b); - case SYS_sbrk: return sbrk(a); - case SYS_open: return sys_open(a,b,c); - case SYS_close: return sys_close(a); - case SYS_read: return sys_read(a,b,c); - case SYS_seek: return sys_seek(a,b,c); - case SYS_kill: return sys_kill(a,b); - case SYS_getpid: return sys_getpid(); - default: - System.err.println("Attempted to use unknown syscall: " + syscall); - return -ENOSYS; - } - } - - /** Helper function to read a cstring from main memory */ - public String cstring(int addr) throws ReadFaultException { - StringBuffer sb = new StringBuffer(); - for(;;) { - int word = memRead(addr&~3); - switch(addr&3) { - case 0: if(((word>>>24)&0xff)==0) return sb.toString(); sb.append((char)((word>>>24)&0xff)); addr++; - case 1: if(((word>>>16)&0xff)==0) return sb.toString(); sb.append((char)((word>>>16)&0xff)); addr++; - case 2: if(((word>>> 8)&0xff)==0) return sb.toString(); sb.append((char)((word>>> 8)&0xff)); addr++; - case 3: if(((word>>> 0)&0xff)==0) return sb.toString(); sb.append((char)((word>>> 0)&0xff)); addr++; - } - } - } - - /** FileInfo class - used by stat */ - public static class FileInfo { - public static final int S_IFIFO = 0010000; - public static final int S_FCHR = 0020000; - public static final int S_IFDIR = 0040000; - public static final int S_IFREG = 0100000; - - public int size() { return 0; } - public int type() { return S_IFIFO; } - public long modTime() { return 0; } - } - - /** FileInfo subclass for normal files */ - public static class FileFileInfo extends FileInfo { - public File f; - public FileFileInfo(File f) { this.f = f; } - public int size() { return (int)f.length(); } - public int type() { return f.isDirectory() ? S_IFDIR : S_IFREG; } - public long modTime() { return f.lastModified(); } - } - - /** File Descriptor class */ - public static abstract class FileDescriptor { - protected final static int SEEK_SET = 0; - protected final static int SEEK_CUR = 1; - protected final static int SEEK_END = 2; - - /** returns true if the fd is readable */ - public boolean readable() { return false; } - /** returns true if the fd is writable */ - public boolean writable() { return false; } - - private static final FileInfo nullFi = new FileInfo(); - private FileInfo fi; - public FileInfo fileInfo() { return fi; } - - /** Initializes the FileDescriptor with no FileInfo struct */ - FileDescriptor() { this(null); } - /** Initializes the FileDescriptor with the given FileInfo struct (used by fstat) */ - FileDescriptor(FileInfo fi) { this.fi = fi==null ? nullFi : fi; } - - /** Read some bytes. Should return the number of bytes read, 0 on EOF, or throw an IOException on error */ - public int read(byte[] a, int off, int length) throws IOException { throw new IOException("no definition"); } - /** Write. Should return the number of bytes written or throw an IOException on error */ - public int write(byte[] a, int off, int length) throws IOException { throw new IOException("no definition"); } - - /** Seek in the filedescriptor. Whence is SEEK_SET, SEEK_CUR, or SEEK_END. Should return -1 on error or the new position. */ - public int seek(int n, int whence) throws IOException { return -1; } - - /** Should return true if this is a tty */ - public boolean isatty() { return false; } - - /** Closes the fd */ - void close() { } - } - - /** FileDescriptor class for normal files */ - public static class RegularFileDescriptor extends FileDescriptor { - private int mode; - private RandomAccessFile raf; - public boolean readable() { return mode != 1; } - public boolean writable() { return mode != 0; } - - RegularFileDescriptor(File f,int m) throws IOException { - super(new FileFileInfo(f)); - String mode = m == 0 ? "r" : "rw"; - this.mode = m; - raf = new RandomAccessFile(f,mode); - if(raf.length() >= Integer.MAX_VALUE) throw new IOException("File too large"); - } - - public int seek(int n_, int whence) throws IOException { - long n = n_; - switch(whence) { - case SEEK_SET: break; - case SEEK_CUR: n += raf.getFilePointer(); break; - case SEEK_END: n += raf.length(); break; - default: return -1; - } - raf.seek(n); - return (int)n; - } - - public int write(byte[] a, int off, int length) throws IOException { raf.write(a,off,length); return length; } - public int read(byte[] a, int off, int length) throws IOException { int n = raf.read(a,off,length); return n < 0 ? 0 : n; } - - void close() { try { raf.close(); } catch(Exception e) { } } - } - - public class OutputStreamFD extends FileDescriptor { - private OutputStream os; - public boolean writable() { return true; } - public OutputStreamFD(OutputStream os) { this.os = os; } - public int write(byte[] a, int off, int length) throws IOException { os.write(a,off,length); return length; } - } - - public class InputStreamFD extends FileDescriptor { - private InputStream is; - public boolean readable() { return true; } - public InputStreamFD(InputStream is) { this.is = is; } - public int read(byte[] a, int off, int length) throws IOException { int n = is.read(a,off,length); return n < 0 ? 0 : n; } - } - - // Exceptions - public static class ReadFaultException extends FaultException { - public ReadFaultException(int addr) { super(addr); } - } - public static class WriteFaultException extends FaultException { - public WriteFaultException(int addr) { super(addr); } - } - public static abstract class FaultException extends ExecutionException { - private int addr; - public FaultException(int addr) { this.addr = addr; } - public String getMessage() { return "fault at: " + toHex(addr); } - } - public static class ExecutionException extends Exception { - public ExecutionException() { } - public ExecutionException(String s) { super(s); } - } - - // Utility functions - private byte[] byteBuf(int size) { - if(_byteBuf==null) _byteBuf = new byte[size]; - else if(_byteBuf.length < size) - _byteBuf = new byte[min(max(_byteBuf.length*2,size),MAX_CHUNK)]; - return _byteBuf; - } - - protected final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); } - protected final static int min(int a, int b) { return a < b ? a : b; } - protected final static int max(int a, int b) { return a > b ? a : b; } -} diff --git a/src/org/xwt/mips/Syscalls.java b/src/org/xwt/mips/Syscalls.java deleted file mode 100644 index 26829df..0000000 --- a/src/org/xwt/mips/Syscalls.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.xwt.mips; -public interface Syscalls { - public static final int SYS_null = 0; - public static final int SYS_exit = 1; - public static final int SYS_pause = 2; - public static final int SYS_open = 3; - public static final int SYS_close = 4; - public static final int SYS_read = 5; - public static final int SYS_write = 6; - public static final int SYS_sbrk = 7; - public static final int SYS_fstat = 8; - public static final int SYS_isatty = 9; - public static final int SYS_seek = 10; - public static final int SYS_kill = 11; - public static final int SYS_getpid = 12; -} diff --git a/src/org/xwt/mips/crt0.c b/src/org/xwt/mips/crt0.c deleted file mode 100644 index 8275ada..0000000 --- a/src/org/xwt/mips/crt0.c +++ /dev/null @@ -1,17 +0,0 @@ -#include - -extern int _gp[]; -extern int main(int argc, char **argv, char **envp); -extern void exit(int status); - -static char *environ[1] = { NULL }; -static char **argv = (char**)0xfffe000; - -int *_user_info = (int*) 0xfffd000; - -void _start() { - int argc; - __asm__ volatile ("move $28,%0" : : "r"(_gp)); - for(argc=0;argv[argc];argc++); - exit(main(argc,argv,environ)); -} diff --git a/src/org/xwt/mips/linker.ld b/src/org/xwt/mips/linker.ld deleted file mode 100644 index 75a179e..0000000 --- a/src/org/xwt/mips/linker.ld +++ /dev/null @@ -1,57 +0,0 @@ -ENTRY(_start) -/*INPUT(support.o support_aux.o)*/ -GROUP(-lc -lgcc) -/*GROUP(-lgcc)*/ -__DYNAMIC = 0; - -SECTIONS { - . = 0x10000; - .text : { - KEEP(*(.init)) - KEEP(*(.fini)) - KEEP(*(.text)) - *(.text.*) - } - - _etext = .; - - .ctors : - { - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } - - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } - - . = ALIGN(4k); - - .rodata : { - *(.rodata*) *(.eh_frame) *(.jcr) - } - - .data : { - *(.data*) - } - - . = ALIGN(16); - _gp = . + 0x8000; - .sdata : { - *(.rosdata*) *(.sdata*) - } - .sbss : { - *(.sbss*) *(.scommon*) - } - .bss : { - *(.bss*) *(COMMON) - } - - _end = .; -} diff --git a/src/org/xwt/mips/syscalls.c b/src/org/xwt/mips/syscalls.c deleted file mode 100644 index ca35ddf..0000000 --- a/src/org/xwt/mips/syscalls.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#undef errno - -#include -#include - -// NOTE: This must match up with the Syscalls interface in MIPSInterpreter.java -// (in my tree the Syscalls interface is autogenerated from a syscalls.h. We should -// do the same) -#define SYS_null 0 -#define SYS_exit 1 -#define SYS_pause 2 -#define SYS_open 3 -#define SYS_close 4 -#define SYS_read 5 -#define SYS_write 6 -#define SYS_sbrk 7 -#define SYS_fstat 8 -#define SYS_isatty 9 -#define SYS_seek 10 -#define SYS_kill 11 -#define SYS_getpid 12 - -static inline int syscall4(int n, int a, int b, int c, int d) { - int ret; - __asm__ __volatile__ ( - ".set noreorder\n\t" - "move $2,%1\n\t" - "move $4,%2\n\t" - "move $5,%3\n\t" - "move $6,%4\n\t" - "move $7,%5\n\t" - "syscall\n\t" - "move %0,$2\n\t" - ".set reorder\n\t" - : "=r"(ret) - : "0"(n),"r"(a),"r"(b),"r"(c),"r"(d) - : "$2","$4","$5","$6","$7","memory" - ); - return ret; -} -static inline int syscall0(int n) { return syscall4(n,0,0,0,0); } -static inline int syscall1(int n, int a) { return syscall4(n,a,0,0,0); } -static inline int syscall2(int n, int a, int b) { return syscall4(n,a,b,0,0); } -static inline int syscall3(int n, int a, int b, int c) { return syscall4(n,a,b,c,0); } - -static inline int errnoize(struct _reent *ptr,int n) { - if(n < 0) { - ptr->_errno = -n; - n = -1; - } - return n; -} - -/* These return errno values and must be reentrant */ -caddr_t _sbrk_r(struct _reent *ptr,int incr) { - int n = syscall1(SYS_sbrk,incr); - if(n == -ENOMEM) { ptr->_errno = ENOMEM; return (caddr_t)-1; } - return (caddr_t) n; -} - -int _write_r(struct _reent *ptr,int fd, char *p, int len) { return errnoize(ptr,syscall3(SYS_write,fd,(int)p,len)); } -int _read_r(struct _reent *ptr,int fd, char *p, int len) { return errnoize(ptr,syscall3(SYS_read,fd,(int)p,len)); } -int _close_r(struct _reent *ptr,int fd) { return errnoize(ptr,syscall1(SYS_close,fd)); } -int _fstat_r(struct _reent *ptr,int fd, struct stat *st) { return errnoize(ptr,syscall2(SYS_fstat,fd,(int)st)); } -int _lseek_r(struct _reent *ptr,int fd, int off, int whence) { return errnoize(ptr,syscall3(SYS_seek,fd,off,whence)); } -int _open_r(struct _reent *ptr,char *name, int flags, int mode) { return errnoize(ptr,syscall3(SYS_open,(int)name,flags,mode)); } -int _kill_r(struct _reent *ptr,pid_t pid, int sig) { return errnoize(ptr,syscall2(SYS_kill,(int)pid,sig)); } -int _getpid_r(struct _reent *ptr) { return errnoize(ptr,syscall0(SYS_getpid)); } - -/* No errno values */ -void _exit(int status) { - syscall1(SYS_exit,status); - for(;;); /* shut up gcc */ -} -int isatty(int fd) { return syscall1(SYS_isatty,fd); } - -void emu_pause() { syscall0(SYS_pause); }