Переглянути джерело

cvm: implement stack overflow error condition

master
Virgil Dupras 3 роки тому
джерело
коміт
78d4d15fcf
5 змінених файлів з 32 додано та 10 видалено
  1. +6
    -6
      blk/091
  2. +2
    -0
      blk/381
  3. BIN
      cvm/forth.bin
  4. +19
    -4
      cvm/vm.c
  5. +5
    -0
      cvm/vm.h

+ 6
- 6
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
- 0
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 ;


+ 19
- 4
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
- 0
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();


Завантаження…
Відмінити
Зберегти