X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fnestedvm%2FInterpreter.java;h=2e8252f640a79397b6dee2abdd93686c04630eb0;hp=cd82365e172eb44a5f6d4645c8ac92fea4ea1883;hb=b11e7c6c29f2b5f7b0828bf93eb741c4a30ec411;hpb=c2b2704764af1ade923ba8f15d517b87f9d16189 diff --git a/src/org/ibex/nestedvm/Interpreter.java b/src/org/ibex/nestedvm/Interpreter.java index cd82365..2e8252f 100644 --- a/src/org/ibex/nestedvm/Interpreter.java +++ b/src/org/ibex/nestedvm/Interpreter.java @@ -1,3 +1,7 @@ +// Copyright 2000-2005 the Contributors, as shown in the revision logs. +// Licensed under the Apache License 2.0 ("the License"). +// You may not use this file except in compliance with the License. + // Copyright 2003 Brian Alliet // Based on org.xwt.imp.MIPS by Adam Megacz // Portions Copyright 2003 Adam Megacz @@ -7,7 +11,7 @@ package org.ibex.nestedvm; import org.ibex.nestedvm.util.*; import java.io.*; -public class Interpreter extends UnixRuntime { +public class Interpreter extends UnixRuntime implements Cloneable { // Registers private int[] registers = new int[32]; private int hi,lo; @@ -51,9 +55,17 @@ public class Interpreter extends UnixRuntime { } } + protected Object clone() throws CloneNotSupportedException { + Interpreter r = (Interpreter) super.clone(); + r.registers = (int[]) registers.clone(); + r.fpregs = (int[]) fpregs.clone(); + return r; + } + // Main interpretor // the return value is meaningless, its just to catch people typing "return" by accident private final int runSome() throws FaultException,ExecutionException { + final int PAGE_WORDS = (1<>2; int[] r = registers; int[] f = fpregs; int pc = this.pc; @@ -62,8 +74,9 @@ public class Interpreter extends UnixRuntime { OUTER: for(;;) { int insn; try { - insn = readPages[pc>>>PAGE_SHIFT][(pc>>>2)&PAGE_WORDS-1]; + insn = readPages[pc>>>pageShift][(pc>>>2)&PAGE_WORDS-1]; } catch (RuntimeException e) { + if(pc == 0xdeadbeef) throw new Error("fell off cpu: r2: " + r[2]); insn = memRead(pc); } @@ -85,7 +98,7 @@ public class Interpreter extends UnixRuntime { int tmp, addr; // temporaries r[ZERO] = 0; - + switch(op) { case 0: { switch(subcode) { @@ -116,7 +129,7 @@ public class Interpreter extends UnixRuntime { continue OUTER; case 12: // SYSCALL this.pc = pc; - r[V0] = syscall(r[V0],r[A0],r[A1],r[A2],r[A3]); + r[V0] = syscall(r[V0],r[A0],r[A1],r[A2],r[A3],r[T0],r[T1]); if(state != RUNNING) { this.pc = nextPC; break OUTER; } break; case 13: // BREAK @@ -134,7 +147,7 @@ public class Interpreter extends UnixRuntime { lo = r[rs]; break; case 24: { // MULT - long hilo = (long)(r[rs]) * ((long)r[rt]); + long hilo = ((long)r[rs]) * ((long)r[rt]); hi = (int) (hilo >>> 32); lo = (int) hilo; break; @@ -269,7 +282,7 @@ public class Interpreter extends UnixRuntime { r[rt] = r[rs] < signedImmediate ? 1 : 0; break; case 11: // SLTIU - r[rt] = (r[rs]&0xffffffffL) < (unsignedImmediate&0xffffffffL) ? 1 : 0; + r[rt] = (r[rs]&0xffffffffL) < (signedImmediate&0xffffffffL) ? 1 : 0; break; case 12: // ANDI r[rt] = r[rs] & unsignedImmediate; @@ -354,6 +367,9 @@ public class Interpreter extends UnixRuntime { case 60: // C.LT.S setFC(getFloat(fs) < getFloat(ft)); break; + case 62: // C.LE.S + setFC(getFloat(fs) <= getFloat(ft)); + break; default: throw new ExecutionException("Invalid Instruction 17/" + rs + "/" + subcode + " at " + sourceLine(pc)); } break; @@ -413,6 +429,9 @@ public class Interpreter extends UnixRuntime { } case 20: { // Integer switch(subcode) { + case 32: // CVT.S.W + setFloat(fd,f[fs]); + break; case 33: // CVT.D.W setDouble(fd,f[fs]); break; @@ -430,7 +449,7 @@ public class Interpreter extends UnixRuntime { case 32: { // LB addr = r[rs] + signedImmediate; try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + tmp = readPages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)]; } catch(RuntimeException e) { tmp = memRead(addr&~3); } @@ -447,13 +466,14 @@ public class Interpreter extends UnixRuntime { case 33: { // LH addr = r[rs] + signedImmediate; try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + tmp = readPages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)]; } catch(RuntimeException e) { tmp = memRead(addr&~3); } - switch(addr&2) { + switch(addr&3) { case 0: tmp = (tmp>>>16)&0xffff; break; case 2: tmp = (tmp>>> 0)&0xffff; break; + default: throw new ReadFaultException(addr); } if((tmp&0x8000)!=0) tmp |= 0xffff0000; // sign extend r[rt] = tmp; @@ -462,7 +482,7 @@ public class Interpreter extends UnixRuntime { case 34: { // LWL; addr = r[rs] + signedImmediate; try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + tmp = readPages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)]; } catch(RuntimeException e) { tmp = memRead(addr&~3); } @@ -477,7 +497,7 @@ public class Interpreter extends UnixRuntime { case 35: // LW addr = r[rs] + signedImmediate; try { - r[rt] = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + r[rt] = readPages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)]; } catch(RuntimeException e) { r[rt] = memRead(addr); } @@ -485,7 +505,7 @@ public class Interpreter extends UnixRuntime { case 36: { // LBU addr = r[rs] + signedImmediate; try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + tmp = readPages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)]; } catch(RuntimeException e) { tmp = memRead(addr); } @@ -500,20 +520,21 @@ public class Interpreter extends UnixRuntime { case 37: { // LHU addr = r[rs] + signedImmediate; try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + tmp = readPages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)]; } catch(RuntimeException e) { tmp = memRead(addr&~3); } - switch(addr&2) { + switch(addr&3) { case 0: r[rt] = (tmp>>>16)&0xffff; break; case 2: r[rt] = (tmp>>> 0)&0xffff; break; + default: throw new ReadFaultException(addr); } break; } case 38: { // LWR addr = r[rs] + signedImmediate; try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + tmp = readPages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)]; } catch(RuntimeException e) { tmp = memRead(addr&~3); } @@ -528,7 +549,7 @@ public class Interpreter extends UnixRuntime { case 40: { // SB addr = r[rs] + signedImmediate; try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + tmp = readPages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)]; } catch(RuntimeException e) { tmp = memRead(addr&~3); } @@ -539,7 +560,7 @@ public class Interpreter extends UnixRuntime { case 3: tmp = (tmp&0xffffff00) | ((r[rt]&0xff)<< 0); break; } try { - writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp; + writePages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)] = tmp; } catch(RuntimeException e) { memWrite(addr&~3,tmp); } @@ -548,16 +569,17 @@ public class Interpreter extends UnixRuntime { case 41: { // SH addr = r[rs] + signedImmediate; try { - tmp = readPages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)]; + tmp = readPages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)]; } catch(RuntimeException e) { tmp = memRead(addr&~3); } - switch(addr&2) { + switch(addr&3) { case 0: tmp = (tmp&0x0000ffff) | ((r[rt]&0xffff)<<16); break; case 2: tmp = (tmp&0xffff0000) | ((r[rt]&0xffff)<< 0); break; + default: throw new WriteFaultException(addr); } try { - writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp; + writePages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)] = tmp; } catch(RuntimeException e) { memWrite(addr&~3,tmp); } @@ -573,7 +595,7 @@ public class Interpreter extends UnixRuntime { case 3: tmp=(tmp&0xffffff00)|(r[rt]>>>24); break; } try { - writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = tmp; + writePages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)] = tmp; } catch(RuntimeException e) { memWrite(addr&~3,tmp); } @@ -582,7 +604,7 @@ public class Interpreter extends UnixRuntime { case 43: // SW addr = r[rs] + signedImmediate; try { - writePages[addr>>>PAGE_SHIFT][(addr>>>2)&(PAGE_WORDS-1)] = r[rt]; + writePages[addr>>>pageShift][(addr>>>2)&(PAGE_WORDS-1)] = r[rt]; } catch(RuntimeException e) { memWrite(addr&~3,r[rt]); } @@ -599,14 +621,14 @@ public class Interpreter extends UnixRuntime { memWrite(addr&~3,tmp); break; } - // FEATURE: Needs to be atomic w/ threads + // Needs to be atomic w/ threads case 48: // LWC0/LL r[rt] = memRead(r[rs] + signedImmediate); break; case 49: // LWC1 f[rt] = memRead(r[rs] + signedImmediate); break; - // FEATURE: Needs to be atomic w/ threads + // Needs to be atomic w/ threads case 56: memWrite(r[rs] + signedImmediate,r[rt]); r[rt] = 1; @@ -632,37 +654,47 @@ public class Interpreter extends UnixRuntime { return sym == null ? -1 : sym.addr; } + private int gp; + protected int gp() { return gp; } + + private ELF.Symbol userInfo; + protected int userInfoBae() { return userInfo == null ? 0 : userInfo.addr; } + protected int userInfoSize() { return userInfo == null ? 0 : userInfo.size; } + + private int entryPoint; + protected int entryPoint() { return entryPoint; } + + private int heapStart; + protected int heapStart() { return heapStart; } + // Image loading function private void loadImage(Seekable data) throws IOException { - if(state != UNINITIALIZED) throw new IllegalStateException("loadImage called on initialized runtime"); - ELF elf = new ELF(data); symtab = elf.getSymtab(); - 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"); - if(elf.ident.data != ELF.ELFIdent.ELFDATA2MSB) throw new IOException("Binary is not big endian"); + if(elf.header.type != ELF.ET_EXEC) throw new IOException("Binary is not an executable"); + if(elf.header.machine != ELF.EM_MIPS) throw new IOException("Binary is not for the MIPS I Architecture"); + if(elf.ident.data != ELF.ELFDATA2MSB) throw new IOException("Binary is not big endian"); entryPoint = elf.header.entry; ELF.Symtab symtab = elf.getSymtab(); if(symtab == null) throw new IOException("No symtab in binary (did you strip it?)"); - ELF.Symbol userInfo = symtab.getGlobalSymbol("user_info"); + userInfo = symtab.getGlobalSymbol("user_info"); ELF.Symbol gpsym = symtab.getGlobalSymbol("_gp"); if(gpsym == null) throw new IOException("NO _gp symbol!"); gp = gpsym.addr; - if(userInfo != null) { - userInfoBase = userInfo.addr; - userInfoSize = userInfo.size; - } + entryPoint = elf.header.entry; ELF.PHeader[] pheaders = elf.pheaders; int brk = 0; + int pageSize = (1<> 2; for(int i=0;i>> PAGE_SHIFT; + for(int j=0;j>> pageShift; if(readPages[page] == null) - readPages[page] = new int[PAGE_WORDS]; + readPages[page] = new int[pageWords]; 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(); + readPages[addr >>> pageShift][(addr >>> 2)&(pageWords-1)] = dis.readInt(); addr+=4; filesize-=4; } while(filesize > 0); dis.close(); } } - brkAddr = (brk+PAGE_SIZE-1)&~(PAGE_SIZE-1); - state = INITIALIZED; + heapStart = (brk+pageSize-1)&~(pageSize-1); } protected void setCPUState(CPUState state) { @@ -699,18 +730,17 @@ public class Interpreter extends UnixRuntime { pc=state.pc; } - protected CPUState getCPUState() { - CPUState state = new CPUState(); + protected void getCPUState(CPUState state) { for(int i=1;i<32;i++) state.r[i] = registers[i]; for(int i=0;i<32;i++) state.f[i] = fpregs[i]; state.hi=hi; state.lo=lo; state.fcsr=fcsr; state.pc=pc; - return state; } - // This is package private for fork() which does all kinds of ugly things behind the scenes - Interpreter() { super(4096,65536,true); } - public Interpreter(Seekable data) throws IOException { this(); loadImage(data); } + public Interpreter(Seekable data) throws IOException { + super(4096,65536); + loadImage(data); + } public Interpreter(String filename) throws IOException { this(new Seekable.File(filename,false)); image = filename;