cvm: implement stack overflow error condition
This commit is contained in:
parent
25f4312523
commit
78d4d15fcf
12
blk/091
12
blk/091
@ -5,12 +5,12 @@ sets that don't change (well, not without some binary manipu-
|
||||
lation). Here's the complete list of these references:
|
||||
|
||||
04 BOOT addr 06 (uflw) addr 08 LATEST
|
||||
2b (s) wordref 33 2>R wordref 42 EXIT wordref
|
||||
53 (br) wordref 67 (?br) wordref 80 (loop) wordref
|
||||
bf (n) wordref
|
||||
13 (oflw) addr 2b (s) wordref 33 2>R wordref
|
||||
42 EXIT wordref 53 (br) wordref 67 (?br) wordref
|
||||
80 (loop) wordref bf (n) wordref
|
||||
|
||||
BOOT and (uflw) exist because they are referred to before those
|
||||
words are defined (in core words). LATEST is a critical part
|
||||
of the initialization sequence.
|
||||
BOOT, (uflw) and (oflw) exist because they are referred to
|
||||
before those words are defined (in core words). LATEST is a
|
||||
critical part of the initialization sequence.
|
||||
|
||||
(cont.)
|
||||
|
2
blk/381
2
blk/381
@ -7,4 +7,6 @@
|
||||
: NL 0x0a RAM+ @ ( NLPTR ) ?DUP IF EXECUTE ELSE CRLF THEN ;
|
||||
: (uflw) LIT" stack underflow" ERR ;
|
||||
XCURRENT @ _xapply ORG @ 0x06 ( stable ABI uflw ) + !
|
||||
: (oflw) LIT" stack overflow" ERR ;
|
||||
XCURRENT @ _xapply ORG @ 0x13 ( stable ABI oflw ) + !
|
||||
: (wnf) (print) SPC LIT" word not found" ERR ;
|
||||
|
BIN
cvm/forth.bin
BIN
cvm/forth.bin
Binary file not shown.
23
cvm/vm.c
23
cvm/vm.c
@ -76,23 +76,33 @@ static void sw(word addr, word val) {
|
||||
// pop word from SP
|
||||
static word pop() {
|
||||
if (vm.uflw) return 0;
|
||||
if (vm.SP >= SP_ADDR) { vm.uflw = true; }
|
||||
if (vm.SP >= SP_ADDR) { vm.uflw = true; return 0; }
|
||||
return vm.mem[vm.SP++] | vm.mem[vm.SP++] << 8;
|
||||
}
|
||||
// push word to SP
|
||||
static void push(word x) {
|
||||
vm.SP -= 2; sw(vm.SP, x);
|
||||
vm.SP -= 2;
|
||||
if (vm.SP <= vm.RS) {
|
||||
vm.oflw = true; vm.SP = SP_ADDR; vm.RS = RS_ADDR;
|
||||
return;
|
||||
}
|
||||
sw(vm.SP, x);
|
||||
if (vm.SP < vm.minSP) { vm.minSP = vm.SP; }
|
||||
}
|
||||
// pop word from RS
|
||||
static word popRS() {
|
||||
if (vm.uflw) return 0;
|
||||
if (vm.RS <= RS_ADDR) { vm.uflw = true; }
|
||||
if (vm.RS <= RS_ADDR) { vm.uflw = true; return 0; }
|
||||
word x = gw(vm.RS); vm.RS -= 2; return x;
|
||||
}
|
||||
// push word to RS
|
||||
static void pushRS(word val) {
|
||||
vm.RS += 2; sw(vm.RS, val);
|
||||
vm.RS += 2;
|
||||
if (vm.SP <= vm.RS) {
|
||||
vm.oflw = true; vm.SP = SP_ADDR; vm.RS = RS_ADDR;
|
||||
return;
|
||||
}
|
||||
sw(vm.RS, val);
|
||||
if (vm.RS > vm.maxRS) { vm.maxRS = vm.RS; }
|
||||
}
|
||||
|
||||
@ -358,6 +368,7 @@ VM* VM_init() {
|
||||
sw(SYSVARS+0x02, gw(0x08)); // CURRENT
|
||||
sw(SYSVARS+0x04, gw(0x08)); // HERE
|
||||
vm.uflw = false;
|
||||
vm.oflw = false;
|
||||
vm.running = true;
|
||||
return &vm;
|
||||
}
|
||||
@ -380,6 +391,10 @@ bool VM_steps(int n) {
|
||||
vm.uflw = false;
|
||||
execute(gw(0x06)); /* uflw */
|
||||
}
|
||||
if (vm.oflw) {
|
||||
vm.oflw = false;
|
||||
execute(gw(0x13)); /* oflw */
|
||||
}
|
||||
n--;
|
||||
}
|
||||
return vm.running;
|
||||
|
5
cvm/vm.h
5
cvm/vm.h
@ -39,6 +39,11 @@ typedef struct {
|
||||
// execute cycle. The goal is to avoid over-popping in native words that
|
||||
// pop more than once and thus corrupt memory.
|
||||
bool uflw;
|
||||
// Same as uflw, but for stack overflow. However, we behave differently with
|
||||
// oflw than with uflw. We can't prevent push() and pushRS() because it
|
||||
// would prevent us from calling (oflw). Instead, we clear both stacks on
|
||||
// oflw conditions, which gives us the room to maneuver.
|
||||
bool oflw;
|
||||
} VM;
|
||||
|
||||
VM* VM_init();
|
||||
|
Loading…
Reference in New Issue
Block a user