2004/01/18 03:55:10
[org.ibex.core.git] / src / org / xwt / mips / Runtime.java
diff --git a/src/org/xwt/mips/Runtime.java b/src/org/xwt/mips/Runtime.java
deleted file mode 100644 (file)
index be050bf..0000000
+++ /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 <i>allowEmptyPages</i> is set */
-    public Runtime(boolean allowEmptyPages) {
-        this.allowEmptyPages = allowEmptyPages;
-        readPages = new int[TOTAL_PAGES][];
-        writePages = new int[TOTAL_PAGES][];
-        for(int i=0;i<STACK_PAGES;i++)
-            readPages[TOTAL_PAGES-1-i] = writePages[TOTAL_PAGES-1-i] = emptyPage();
-    }
-    
-    /** Copy everything from <i>src</i> to <i>addr</i> initializing uninitialized pages if required. 
-       Newly initalized pages will be marked read-only if <i>ro</i> is set */
-    protected final void initPages(int[] src, int addr, boolean ro) {
-        for(int i=0;i<src.length;) {
-            int page = addr >>> 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 <i>words</i> of pages starting at <i>addr</i> to 0 */
-    protected final void clearPages(int addr, int words) {
-        for(int i=0;i<words;) {
-            int page = addr >>> 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;j<start+elements;j++) writePages[page][j] = 0;
-            }
-            i += elements;
-            addr += elements*4;
-        }
-    }
-    
-    /** Copies <i>length</i> bytes from the processes memory space starting at
-        <i>addr</i> INTO a java byte array <i>a</i> */
-    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<end;i++,addr+=4) {
-                int word = page[i];
-                a[n++] = (byte)((word>>>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 <i>length</i> bytes OUT OF the java array <i>a</i> into the processes memory
-        space at <i>addr</i> */
-    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<end;i++,addr+=4) {
-                int word = ((a[n+0]&0xff)<<24)|((a[n+1]&0xff)<<16)|((a[n+2]&0xff)<<8)|((a[n+3]&0xff)<<0); n+=4;
-                page[i] = word;
-            }
-        }
-        if(length-n > 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 <i>addr</i> */
-    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 <i>addr</i> */
-    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 <i>page</i> */
-    private final void initPage(int page) { initPage(page,false); }
-    /** Created a new non-empty page at page number <i>page</i>. If <i>ro</i> 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, <i>args</i>, 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<count;i++) total += args[i].length() + 1/*null terminator*/ + 4/*table entry*/;
-        if(total >= 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;i<count;i++) {
-            byte[] a;
-            try { a = args[i].getBytes("US-ASCII"); } catch(UnsupportedEncodingException e){ throw new Error(e.getMessage()); }
-            table[i] = addr;
-            copyout(a,addr,a.length);
-            addr += a.length;
-            copyout(nullTerminator,addr,1);
-            addr += 1;
-        }
-        addr=start;
-        for(int i=0;i<count;i++) {
-            memWrite(addr,table[i]);
-            addr += 4;
-        }
-    }
-    
-    /** Sets word number <i>index</i> in the _user_info table to <i>word</i> 
-        _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 <i>index</i>
-        @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 <i>fileName</i>. 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 <i>fd</i> 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<OPEN_MAX;i++) if(fds[i] == null) break;
-        if(i==OPEN_MAX) return -1;
-        fds[i] = fd;
-        return i;
-    }
-
-    /** The open syscall */
-    private int sys_open(int addr, int flags, int mode) {
-        final int O_RDONLY = 0;
-        final int O_WRONLY = 1;
-        final int O_RDWR = 2;
-        final int O_APPEND = 0x0008;
-        final int O_CREAT = 0x0200;
-        final int O_NONBLOCK = 0x4000;
-        final int O_EXCL = 0x0800;
-        
-        if((flags & O_APPEND) != 0) {
-            System.err.println("WARNING: O_APPEND not supported");
-            return -EOPNOTSUPP;
-        }
-        if((flags & O_NONBLOCK) != 0) {
-            System.err.println("WARNING: O_NONBLOCK not supported");
-            return -EOPNOTSUPP;
-        }
-
-        try {
-            String fileName = cstring(addr);
-            if(!allowFileAccess(fileName,(flags&3)!=0)) return -EACCES;
-
-            File f = new File(fileName);
-            if((flags & O_EXCL) != 0 && (flags & O_CREAT) != 0)
-                if(!f.createNewFile()) return -EEXIST;
-            if(f.exists()) {
-                if(f.length() >= 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.
-        <i>incr</i> is how much to increase the break by */
-    public int sbrk(int incr) {
-        if(incr==0) return brk<<PAGE_SHIFT;
-        int oldBrk = brk;
-        int newBrk = oldBrk + ((incr+PAGE_SIZE-1)>>PAGE_SHIFT);
-        if(newBrk >= BRK_LIMIT) {
-            System.err.println("Hit BRK_LIMIT");
-            return -ENOMEM;
-        }
-        for(int i=oldBrk;i<newBrk;i++)
-            readPages[i] = writePages[i] = emptyPage();
-        brk = newBrk;
-        return oldBrk<<PAGE_SHIFT;
-    }
-        
-    /** The kill syscall.
-       SIGSTOP, SIGTSTO, SIGTTIN, and SIGTTOUT pause the process.
-       SIGCONT, SIGCHLD, SIGIO, and SIGWINCH are ignored.
-       Anything else terminates the process. */
-    private int sys_kill(int pid, int signal) {
-        // This will only be called by raise() in newlib to invoke the default handler
-        // We don't have to worry about actually delivering the signal
-        if(pid != PID) return -ESRCH;
-        if(signal < 0 || signal >= 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.
-        <i>syscall</i> should be the contents of V0 and <i>a</i>, <i>b</i>, <i>c</i>, and <i>d</i> 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; }
-}