Skip to content

Commit

Permalink
split stack to have separate call stack
Browse files Browse the repository at this point in the history
  • Loading branch information
parrt committed Apr 13, 2015
1 parent 97fb6c6 commit da25c7b
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 25 deletions.
12 changes: 12 additions & 0 deletions src/vm/Context.java
Original file line number Diff line number Diff line change
@@ -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];
}
}
21 changes: 15 additions & 6 deletions src/vm/Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -49,28 +57,29 @@ 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
ICONST, 1, // 7
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
};
Expand Down
42 changes: 23 additions & 19 deletions src/vm/VM.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,22 @@
/** 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

// memory
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;

Expand All @@ -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() {
Expand All @@ -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
Expand Down Expand Up @@ -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++];
Expand All @@ -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<nargs; i++) {
callstack[callsp].locals[i] = stack[sp-i];
}
sp -= nargs;
ip = addr; // jump to function
// code preamble of func must push space for locals
// TODO: code preamble of func must push space for locals
break;
case RET:
int rvalue = stack[sp--]; // pop return value
sp = fp; // jump over locals to fp which points at ret addr
ip = stack[sp--]; // pop return address, jump to it
fp = stack[sp--]; // restore fp
nargs = stack[sp--]; // how many args to throw away?
sp -= nargs; // pop args
stack[++sp] = rvalue; // leave result on stack
ip = callstack[callsp--].returnip;
break;
default :
throw new Error("invalid opcode: "+opcode+" at ip="+(ip-1));
Expand All @@ -154,7 +152,13 @@ protected void cpu() {
if ( trace ) dumpDataMemory();
}

protected String stackString() {
private void load() {
int regnum;
regnum = code[ip++];
stack[++sp] = callstack[callsp].locals[regnum];
}

protected String stackString() {
StringBuilder buf = new StringBuilder();
buf.append("stack=[");
for (int i = 0; i <= sp; i++) {
Expand Down

0 comments on commit da25c7b

Please sign in to comment.