// Copyright 2003 Brian Alliet
// Based on org.xwt.imp.MIPS by Adam Megacz
// Portions Copyright 2003 Adam Megacz
// Copyright 2003 Brian Alliet
// Based on org.xwt.imp.MIPS by Adam Megacz
// Portions Copyright 2003 Adam Megacz
/** True to write useful diagnostic information to stderr when things go wrong */
final static boolean STDERR_DIAG = true;
/** True to write useful diagnostic information to stderr when things go wrong */
final static boolean STDERR_DIAG = true;
/** Prgram has been started but is paused */
public final static int PAUSED = 2;
/** Program is executing a callJava() method */
/** Prgram has been started but is paused */
public final static int PAUSED = 2;
/** Program is executing a callJava() method */
public ExecutionException exitException;
/** Table containing all open file descriptors. (Entries are null if the fd is not in use */
public ExecutionException exitException;
/** Table containing all open file descriptors. (Entries are null if the fd is not in use */
/** Subclasses should set the CPUState to the state held in <i>state</i> */
protected abstract void setCPUState(CPUState state);
/** Subclasses should set the CPUState to the state held in <i>state</i> */
protected abstract void setCPUState(CPUState state);
+ /** True to enabled a few hacks to better support the win32 console */
+ final static boolean win32Hacks;
+
+ static {
+ String os = Platform.getProperty("os.name");
+ String prop = Platform.getProperty("nestedvm.win32hacks");
+ if(prop != null) { win32Hacks = Boolean.valueOf(prop).booleanValue(); }
+ else { win32Hacks = os != null && os.toLowerCase().indexOf("windows") != -1; }
+ }
+
- protected Runtime(int pageSize, int totalPages) {
+ protected Runtime(int pageSize, int totalPages) { this(pageSize, totalPages,false); }
+ protected Runtime(int pageSize, int totalPages, boolean exec) {
if(pageSize <= 0) throw new IllegalArgumentException("pageSize <= 0");
if(totalPages <= 0) throw new IllegalArgumentException("totalPages <= 0");
if((pageSize&(pageSize-1)) != 0) throw new IllegalArgumentException("pageSize not a power of two");
if(pageSize <= 0) throw new IllegalArgumentException("pageSize <= 0");
if(totalPages <= 0) throw new IllegalArgumentException("totalPages <= 0");
if((pageSize&(pageSize-1)) != 0) throw new IllegalArgumentException("pageSize not a power of two");
-
- InputStream stdin = Boolean.valueOf(getSystemProperty("nestedvm.textstdin")).booleanValue() ? new TextInputStream(System.in) : System.in;
- addFD(new TerminalFD(stdin));
- addFD(new TerminalFD(System.out));
- addFD(new TerminalFD(System.err));
+
+ if(!exec) {
+ fds = new FD[OPEN_MAX];
+ closeOnExec = new boolean[OPEN_MAX];
+
+ InputStream stdin = win32Hacks ? new Win32ConsoleIS(System.in) : System.in;
+ addFD(new TerminalFD(stdin));
+ addFD(new TerminalFD(System.out));
+ addFD(new TerminalFD(System.err));
+ }
if(page == null) throw new WriteFaultException(a<<2);
int index = a&pageWordMask;
int n = min(c,pageWords-index);
if(page == null) throw new WriteFaultException(a<<2);
int index = a&pageWordMask;
int n = min(c,pageWords-index);
- Arrays.fill(page,index,index+n,fourBytes);
+ /* Arrays.fill(page,index,index+n,fourBytes);*/
+ for(int i=index;i<index+n;i++) page[i] = fourBytes;
private void __execute() {
try {
_execute();
} catch(FaultException e) {
if(STDERR_DIAG) e.printStackTrace();
private void __execute() {
try {
_execute();
} catch(FaultException e) {
if(STDERR_DIAG) e.printStackTrace();
if((flags & ~(3|O_CREAT|O_EXCL|O_APPEND|O_TRUNC)) != 0) {
if(STDERR_DIAG)
System.err.println("WARNING: Unsupported flags passed to open(\"" + f + "\"): " + toHex(flags & ~(3|O_CREAT|O_EXCL|O_APPEND|O_TRUNC)));
if((flags & ~(3|O_CREAT|O_EXCL|O_APPEND|O_TRUNC)) != 0) {
if(STDERR_DIAG)
System.err.println("WARNING: Unsupported flags passed to open(\"" + f + "\"): " + toHex(flags & ~(3|O_CREAT|O_EXCL|O_APPEND|O_TRUNC)));
} catch(FileNotFoundException e) {
if(e.getMessage() != null && e.getMessage().indexOf("Permission denied") >= 0) throw new ErrnoException(EACCES);
return null;
} catch(FileNotFoundException e) {
if(e.getMessage() != null && e.getMessage().indexOf("Permission denied") >= 0) throw new ErrnoException(EACCES);
return null;
/** The open syscall */
private int sys_open(int addr, int flags, int mode) throws ErrnoException, FaultException {
/** The open syscall */
private int sys_open(int addr, int flags, int mode) throws ErrnoException, FaultException {
int stat(FStat fs, int addr) throws FaultException {
memWrite(addr+0,(fs.dev()<<16)|(fs.inode()&0xffff)); // st_dev (top 16), // st_ino (bottom 16)
memWrite(addr+4,((fs.type()&0xf000))|(fs.mode()&0xfff)); // st_mode
int stat(FStat fs, int addr) throws FaultException {
memWrite(addr+0,(fs.dev()<<16)|(fs.inode()&0xffff)); // st_dev (top 16), // st_ino (bottom 16)
memWrite(addr+4,((fs.type()&0xf000))|(fs.mode()&0xfff)); // 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+8,fs.nlink()<<16|fs.uid()&0xffff); // st_nlink (top 16) // st_uid (bottom 16)
+ memWrite(addr+12,fs.gid()<<16|0); // st_gid (top 16) // st_rdev (bottom 16)
memWrite(addr+16,fs.size()); // st_size
memWrite(addr+20,fs.atime()); // st_atime
// memWrite(addr+24,0) // st_spare1
memWrite(addr+16,fs.size()); // st_size
memWrite(addr+20,fs.atime()); // st_atime
// memWrite(addr+24,0) // st_spare1
ret = callJavaCB.call(a,b,c,d);
} catch(RuntimeException e) {
System.err.println("Error while executing callJavaCB");
ret = callJavaCB.call(a,b,c,d);
} catch(RuntimeException e) {
System.err.println("Error while executing callJavaCB");
- private int sys_exit(int status) {
+ void exit(int status, boolean fromSignal) {
+ if(fromSignal && fds[2] != null) {
+ try {
+ byte[] msg = getBytes("Process exited on signal " + (status - 128) + "\n");
+ fds[2].write(msg,0,msg.length);
+ } catch(ErrnoException e) { }
+ }
/** 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 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
protected final int syscall(int syscall, int a, int b, int c, int d, int e, int f) {
try {
int n = _syscall(syscall,a,b,c,d,e,f);
protected final int syscall(int syscall, int a, int b, int c, int d, int e, int f) {
try {
int n = _syscall(syscall,a,b,c,d,e,f);
case SYS_getpagesize: return sys_getpagesize();
case SYS_fcntl: return sys_fcntl(a,b,c);
case SYS_sysconf: return sys_sysconf(a);
case SYS_getpagesize: return sys_getpagesize();
case SYS_fcntl: return sys_fcntl(a,b,c);
case SYS_sysconf: return sys_sysconf(a);
case SYS_memcpy: memcpy(a,b,c); return a;
case SYS_memset: memset(a,b,c); return a;
case SYS_memcpy: memcpy(a,b,c); return a;
case SYS_memset: memset(a,b,c); return a;
public int xmalloc(int size) { int p=malloc(size); if(p==0) throw new RuntimeException("malloc() failed"); return p; }
public int xrealloc(int addr,int newsize) { int p=realloc(addr,newsize); if(p==0) throw new RuntimeException("realloc() failed"); return p; }
public int realloc(int addr, int newsize) { try { return call("realloc",addr,newsize); } catch(CallException e) { return 0; } }
public int xmalloc(int size) { int p=malloc(size); if(p==0) throw new RuntimeException("malloc() failed"); return p; }
public int xrealloc(int addr,int newsize) { int p=realloc(addr,newsize); if(p==0) throw new RuntimeException("realloc() failed"); return p; }
public int realloc(int addr, int newsize) { try { return call("realloc",addr,newsize); } catch(CallException e) { return 0; } }
public int getdents(byte[] a, int off, int length) throws ErrnoException { throw new ErrnoException(EBADFD); }
public int getdents(byte[] a, int off, int length) throws ErrnoException { throw new ErrnoException(EBADFD); }
/** Return a Seekable object representing this file descriptor (can be read only)
This is required for exec() */
Seekable seekable() { return null; }
/** Return a Seekable object representing this file descriptor (can be read only)
This is required for exec() */
Seekable seekable() { return null; }
public TerminalFD(OutputStream os) { this(null,os); }
public TerminalFD(InputStream is, OutputStream os) { super(is,os); }
public void _close() { /* noop */ }
public TerminalFD(OutputStream os) { this(null,os); }
public TerminalFD(InputStream is, OutputStream os) { super(is,os); }
public void _close() { /* noop */ }
- // FEATURE: TextInputStream: This is pretty inefficient but it is only used for reading from the console on win32
- static class TextInputStream extends InputStream {
+ // This is pretty inefficient but it is only used for reading from the console on win32
+ static class Win32ConsoleIS extends InputStream {
public int read() throws IOException {
if(pushedBack != -1) { int c = pushedBack; pushedBack = -1; return c; }
int c = parent.read();
public int read() throws IOException {
if(pushedBack != -1) { int c = pushedBack; pushedBack = -1; return c; }
int c = parent.read();
- public static class FStat {
- public static final int S_IFIFO = 0010000;
- public static final int S_IFCHR = 0020000;
- public static final int S_IFDIR = 0040000;
- public static final int S_IFREG = 0100000;
+ public abstract static class FStat {
+ public static final int S_IFIFO = 0010000;
+ public static final int S_IFCHR = 0020000;
+ public static final int S_IFDIR = 0040000;
+ public static final int S_IFREG = 0100000;
+ public static final int S_IFSOCK = 0140000;
public int nlink() { return 0; }
public int uid() { return 0; }
public int gid() { return 0; }
public int nlink() { return 0; }
public int uid() { return 0; }
public int gid() { return 0; }
public int ctime() { return 0; }
public int blksize() { return 512; }
public int blocks() { return (size()+blksize()-1)/blksize(); }
public int ctime() { return 0; }
public int blksize() { return 512; }
public int blocks() { return (size()+blksize()-1)/blksize(); }
+
+ public abstract int dev();
+ public abstract int type();
+ public abstract int inode();
+ }
+
+ public static class SocketFStat extends FStat {
+ public int dev() { return -1; }
+ public int type() { return S_IFSOCK; }
+ public int inode() { return hashCode() & 0x7fff; }
/** Decode a packed string */
protected static final int[] decodeData(String s, int words) {
if(s.length() % 8 != 0) throw new IllegalArgumentException("string length must be a multiple of 8");
/** Decode a packed string */
protected static final int[] decodeData(String s, int words) {
if(s.length() % 8 != 0) throw new IllegalArgumentException("string length must be a multiple of 8");
+ static byte[] getNullTerminatedBytes(String s) {
+ byte[] buf1 = getBytes(s);
+ byte[] buf2 = new byte[buf1.length+1];
+ System.arraycopy(buf1,0,buf2,0,buf1.length);
+ return buf2;
+ }
+
final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
final static int min(int a, int b) { return a < b ? a : b; }
final static int max(int a, int b) { return a > b ? a : b; }
final static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
final static int min(int a, int b) { return a < b ? a : b; }
final static int max(int a, int b) { return a > b ? a : b; }