diff --git a/src/vm/Context.java b/src/vm/Context.java new file mode 100644 index 0000000..4bae0eb --- /dev/null +++ b/src/vm/Context.java @@ -0,0 +1,12 @@ +package vm; + +/** To call, push one of these and pop to return */ +public class Context { + int returnip; + int[] locals; // args + locals, indexed from 0 + + public Context(int returnip, int nlocals) { + this.returnip = returnip; + locals = new int[nlocals]; + } +} diff --git a/src/vm/Test.java b/src/vm/Test.java index fed3886..33b48ee 100644 --- a/src/vm/Test.java +++ b/src/vm/Test.java @@ -24,6 +24,14 @@ public class Test { HALT }; + /* + iconst(1); + iconst(2); + iadd(); + print(); + halt(); + */ + static int[] loop = { // .GLOBALS 2; N, I // N = 10 ADDRESS @@ -49,10 +57,11 @@ public class Test { HALT // 24 }; + static int fact = 0; static int[] factorial = { //.def fact: ARGS=1, LOCALS=0 ADDRESS // IF N < 2 RETURN 1 - LOAD, -3, // 0 + LOAD, 0, // 0 ICONST, 2, // 2 ILT, // 4 BRF, 10, // 5 @@ -60,17 +69,17 @@ public class Test { RET, // 9 //CONT: // RETURN N * FACT(N-1) - LOAD, -3, // 10 - LOAD, -3, // 12 + LOAD, 0, // 10 + LOAD, 0, // 12 ICONST, 1, // 14 ISUB, // 16 - CALL, 0, 1, // 17 + CALL, fact, 1, // 17 IMUL, // 20 RET, // 21 //.DEF MAIN: ARGS=0, LOCALS=0 -// PRINT FACT(10) +// PRINT FACT(1) ICONST, 5, // 22 <-- MAIN METHOD! - CALL, 0, 1, // 24 + CALL, fact, 1, // 24 PRINT, // 27 HALT // 28 }; diff --git a/src/vm/VM.java b/src/vm/VM.java index ca9207a..570cc3e 100644 --- a/src/vm/VM.java +++ b/src/vm/VM.java @@ -25,13 +25,14 @@ /** A simple stack-based interpreter */ public class VM { public static final int DEFAULT_STACK_SIZE = 1000; + public static final int DEFAULT_CALL_STACK_SIZE = 1000; public static final int FALSE = 0; public static final int TRUE = 1; // registers int ip; // instruction pointer register int sp = -1; // stack pointer register - int fp = -1; // frame pointer register + int callsp = -1; // call stack pointer register int startip = 0; // where execution begins @@ -39,6 +40,7 @@ public class VM { int[] code; // word-addressable code memory but still bytecodes. int[] globals; // global variable space int[] stack; // Operand stack, grows upwards + Context[] callstack;// call stack, grows upwards public boolean trace = false; @@ -47,6 +49,7 @@ public VM(int[] code, int startip, int nglobals) { this.startip = startip; globals = new int[nglobals]; stack = new int[DEFAULT_STACK_SIZE]; + callstack = new Context[DEFAULT_CALL_STACK_SIZE]; } public void exec() { @@ -57,7 +60,7 @@ public void exec() { /** Simulate the fetch-decode execute cycle */ protected void cpu() { int opcode = code[ip]; - int a,b,addr,offset; + int a,b,addr,regnum; while (opcode!= HALT && ip < code.length) { if ( trace ) System.err.printf("%-35s", disInstr()); ip++; //jump to next instruction or to operand @@ -102,16 +105,15 @@ protected void cpu() { stack[++sp] = code[ip++]; // push operand break; case LOAD : // load local or arg; 1st local is fp+1, args are fp-3, fp-4, fp-5, ... - offset = code[ip++]; - stack[++sp] = stack[fp+offset]; + load(); break; case GLOAD :// load from global memory addr = code[ip++]; stack[++sp] = globals[addr]; break; case STORE : - offset = code[ip++]; - stack[fp+offset] = stack[sp--]; + regnum = code[ip++]; + callstack[callsp].locals[regnum] = stack[sp--]; break; case GSTORE : addr = code[ip++]; @@ -127,21 +129,17 @@ protected void cpu() { // expects all args on stack addr = code[ip++]; // target addr of function int nargs = code[ip++]; // how many args got pushed - stack[++sp] = nargs; // save num args - stack[++sp] = fp; // save fp - stack[++sp] = ip; // push return address - fp = sp; // fp points at ret addr on stack + callstack[++callsp] = new Context(ip,nargs); + // copy args into new context + for (int i=0; i