From 78d4d15fcfa5ba5b8db7bc08a51e576cedd5f9ca Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Fri, 7 Aug 2020 21:57:25 -0400 Subject: [PATCH] cvm: implement stack overflow error condition --- blk/091 | 12 ++++++------ blk/381 | 2 ++ cvm/forth.bin | Bin 5238 -> 5269 bytes cvm/vm.c | 23 +++++++++++++++++++---- cvm/vm.h | 5 +++++ 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/blk/091 b/blk/091 index 0e9bde4..dc6eb36 100644 --- a/blk/091 +++ b/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.) diff --git a/blk/381 b/blk/381 index 002cfe4..8df37ff 100644 --- a/blk/381 +++ b/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 ; diff --git a/cvm/forth.bin b/cvm/forth.bin index 8d84cefa726b00e02f96e5348c9482fc8d8a02b8..c5cdc0e42bcac7f90ee90c7528152670045d1d15 100644 GIT binary patch delta 586 zcmXX@Ur3Wt6hCLvWq$YjbH7bVW;tBO#ur7}gMBW>S}UY&pE(Orr;KnCtu0$L>dolS z#3(GFc|pYOA!bwVvo)RK1C1Ot0QPZ=hF^c?vH!U@1Ec9oK~O`>;Z~v`ggYM zvC%>NVIO*S*vUdRR|*~n7aE`xA7pOb@f98}-p}R=rM5$YKq;RMdc|*+G)Cnr%sYNK zcd!mKD8ZS*0eFJbvLDiH-6cWfk~KLs$l*CY7R&N1z7pT$6SysY$)PK{5@Plt)^r~@ z&<}uD(Ns)Df&~Q-tKbI{LaYj=@}Bvj13u#jR3Y`hv`+7)$Sc=zNqkgRyr)&0(G9)M zFdW$=C{r<4!_c`W=G0+Kh_ZSP--=J_dHf<;YJh|cXnlBAT+p_#AvkwqMGWy|e_N9v zZbdFnYS4*WBxhURU~N(6K71|K_%Wi?c>mZwPvILNuLFD$O?7MX{z^*j#ld(GZq9;BD%M>xjiuF*iJ=Z^mHVRl|v{ zvRHLTB2E1(E$2pZYCPTx&nO+H^t@vf4->OGtYC#^kap1;Ucx4+j#`O{@i_T=flFP6 M@OXx(m+1-p1FDIS`v3p{ delta 555 zcmYk3&ubG=5XWcIW{K|GpGnlPp_ML5LZo2hL2WR^G-@H6tx1*In3fz=gc=Kh1QC>q zKMo=k2LA(ZYM~G)=^h28DD15jq|rkUBAyg_cGC9Xz~c??J3l`2=5=y65e2qW<~LD} z^t}UHjrK&a-MF2M(@~|AiYXnK3+xQ^(1%%+VRU2|p5QsfhMHKDWXN4~%hMwUJjW_6 zD^+|%zm*|eCt1y0`m1C_|8Uk!3<78a;AON_OO;_>1;h^6a2_(E1D5(;*f0nmFby53 z9EAG(ZqY0CDqf-Q>Jlnc*CNs%H4DKn^iUhaQCiVX<4gLXox!&h)f3$Lf*wPiX7sIS zSGOSqa=^h2E-3AJEt)V&@oim(qMMs2>kz~(9xV-Rrdd}!u}v$+aePd^aSXfk(}<66 z8Wns4JgVbfFQ}Z*hx8e@~Nc zj$OlHm|5K9`#&tbr=?(UzWJbe^H2&7=kG5p)EAq#+)7P&Vu*axMURHVB^1;MCoIq0 zUq_)>DTLuER~&~mX#=N1i?kZfijI&y-0-H2rV0U4`;&;S4c diff --git a/cvm/vm.c b/cvm/vm.c index 021a404..33ffa63 100644 --- a/cvm/vm.c +++ b/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; diff --git a/cvm/vm.h b/cvm/vm.h index b14834b..215bd9e 100644 --- a/cvm/vm.h +++ b/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();