commit f6f85900fbb46b930230a7be2d6f08e6cd99d116
parent cf81d5d9c011fe1233ee5307adfeabcfa6da2ebc
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 7 Oct 2022 20:14:09 -0400
cc/vm/forth: fix bug in binop=
Calling it with a TOS argument generated a PS imbalance error. Moreover, with
struct offsets, it didn't generate proper code when came the time to write the
mutated value back. The whole logic has changed.
Diffstat:
5 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/fs/app/cos/cvm.c b/fs/app/cos/cvm.c
@@ -113,7 +113,6 @@ static void sw(word addr, word val) {
}
static word peek() { return gw(vm.SP); }
/* pop word from SP */
-// Compiles up to this point!
static word pop() { word n = peek(); vm.SP+=2; return n; }
word VM_PS_pop() { return pop(); }
@@ -190,7 +189,8 @@ static void SUB() {
word b = pop(); word a = pop(); push(a-b); }
static void BR() {
word off = vm.mem[vm.IP];
- if (off > 0x7f) off |= 0xff00; vm.IP += off; }
+ if (off > $7f) off |= $ff00; vm.IP += off; }
+// Compiles up to this point!
static void CBR() { if (pop()) vm.IP++; else BR(); }
static void NEXT() {
word n = popRS()-1;
diff --git a/fs/cc/vm/forth.fs b/fs/cc/vm/forth.fs
@@ -178,13 +178,10 @@ binop vm||, or and
\ a binop= is like a unop in the sense that it operates directly on op1, but
\ with the participation of op2.
: binop= doer ' , does> @ ( w )
- >r vmop :keep r> ( ... w )
- vmop :compile \ op1 is TOS
- vmop^ :hasop# vmop^ :compile \ op2 is TOS
- ( w ) execute, PS- \ result on TOS
- vmop :forgetTOS
- vmop :popNoChk vmop :&op vmop :compile
- vmop :forgetTOS vmop^ :forgetTOS compile ! PS- PS- ;
+ vmop :compile& vmop :&op \ op1 is TOS
+ compile dup PS+ vmop :typesz! compile @ vmop^ :compile \ op2 is TOS
+ ( w ) execute, PS- vmop^ :forgetTOS \ result on TOS
+ compile swap vmop :typesz! compile ! vmop :forgetTOS PS- PS- ;
binop= vm<<=, lshift
binop= vm>>=, rshift
diff --git a/fs/tests/cc/cc.fs b/fs/tests/cc/cc.fs
@@ -67,6 +67,7 @@ globdata 4 + 16b @ 42 #eq
2 3 binop1 1 #eq
'2' binop2 44 #eq
binop3 $605 #eq
+structop1 44 #eq
\ and what about inline functions?
:cfunc int myinline() { return 42; }
diff --git a/fs/tests/cc/test.c b/fs/tests/cc/test.c
@@ -268,3 +268,7 @@ int binop2(int n) {
int binop3() {
return global2[2] << 8 | global2[1];
}
+short structop1() {
+ globdata.bar += 2;
+ return globdata.bar;
+}
diff --git a/posix/dis.c b/posix/dis.c
@@ -143,12 +143,13 @@ struct call {
int arg;
};
-#define CALLCNT 8
+#define CALLCNT 9
struct call calls[CALLCNT] = {
{0x9e, "(br)", ARGINT},
{0xae, "(?br)", ARGINT},
{0x138, "swap", ARGNONE},
{0x1c7, "@", ARGNONE},
+ {0x1cf, "16b @", ARGNONE},
{0x1d7, "8b @", ARGNONE},
{0x1e9, "!", ARGNONE},
{0x1f9, "8b !", ARGNONE},