cvm: implement stack overflow error condition

This commit is contained in:
Virgil Dupras 2020-08-07 21:57:25 -04:00
parent 25f4312523
commit 78d4d15fcf
5 changed files with 32 additions and 10 deletions

12
blk/091
View File

@ -5,12 +5,12 @@ sets that don't change (well, not without some binary manipu-
lation). Here's the complete list of these references: lation). Here's the complete list of these references:
04 BOOT addr 06 (uflw) addr 08 LATEST 04 BOOT addr 06 (uflw) addr 08 LATEST
2b (s) wordref 33 2>R wordref 42 EXIT wordref 13 (oflw) addr 2b (s) wordref 33 2>R wordref
53 (br) wordref 67 (?br) wordref 80 (loop) wordref 42 EXIT wordref 53 (br) wordref 67 (?br) wordref
bf (n) wordref 80 (loop) wordref bf (n) wordref
BOOT and (uflw) exist because they are referred to before those BOOT, (uflw) and (oflw) exist because they are referred to
words are defined (in core words). LATEST is a critical part before those words are defined (in core words). LATEST is a
of the initialization sequence. critical part of the initialization sequence.
(cont.) (cont.)

View File

@ -7,4 +7,6 @@
: NL 0x0a RAM+ @ ( NLPTR ) ?DUP IF EXECUTE ELSE CRLF THEN ; : NL 0x0a RAM+ @ ( NLPTR ) ?DUP IF EXECUTE ELSE CRLF THEN ;
: (uflw) LIT" stack underflow" ERR ; : (uflw) LIT" stack underflow" ERR ;
XCURRENT @ _xapply ORG @ 0x06 ( stable ABI uflw ) + ! 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 ; : (wnf) (print) SPC LIT" word not found" ERR ;

Binary file not shown.

View File

@ -76,23 +76,33 @@ static void sw(word addr, word val) {
// pop word from SP // pop word from SP
static word pop() { static word pop() {
if (vm.uflw) return 0; 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; return vm.mem[vm.SP++] | vm.mem[vm.SP++] << 8;
} }
// push word to SP // push word to SP
static void push(word x) { 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; } if (vm.SP < vm.minSP) { vm.minSP = vm.SP; }
} }
// pop word from RS // pop word from RS
static word popRS() { static word popRS() {
if (vm.uflw) return 0; 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; word x = gw(vm.RS); vm.RS -= 2; return x;
} }
// push word to RS // push word to RS
static void pushRS(word val) { 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; } if (vm.RS > vm.maxRS) { vm.maxRS = vm.RS; }
} }
@ -358,6 +368,7 @@ VM* VM_init() {
sw(SYSVARS+0x02, gw(0x08)); // CURRENT sw(SYSVARS+0x02, gw(0x08)); // CURRENT
sw(SYSVARS+0x04, gw(0x08)); // HERE sw(SYSVARS+0x04, gw(0x08)); // HERE
vm.uflw = false; vm.uflw = false;
vm.oflw = false;
vm.running = true; vm.running = true;
return &vm; return &vm;
} }
@ -380,6 +391,10 @@ bool VM_steps(int n) {
vm.uflw = false; vm.uflw = false;
execute(gw(0x06)); /* uflw */ execute(gw(0x06)); /* uflw */
} }
if (vm.oflw) {
vm.oflw = false;
execute(gw(0x13)); /* oflw */
}
n--; n--;
} }
return vm.running; return vm.running;

View File

@ -39,6 +39,11 @@ typedef struct {
// execute cycle. The goal is to avoid over-popping in native words that // execute cycle. The goal is to avoid over-popping in native words that
// pop more than once and thus corrupt memory. // pop more than once and thus corrupt memory.
bool uflw; 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* VM_init(); VM* VM_init();