commit 8f6bdeded1bb580d98408d823d39da293f4fdd31
parent 30d0c77ad9412022cdee7bca84978eeb4eeab47f
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Thu, 13 Oct 2022 20:45:24 -0400
cc/vm/i386: fix opwidth bug
Diffstat:
3 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/fs/cc/vm/i386.fs b/fs/cc/vm/i386.fs
@@ -80,7 +80,10 @@ struct+[ VMOp
VM_*STACKFRAME of = V1 :>reg endof
VM_*ARGSFRAME of = V1 :>reg endof
VM_*REGISTER of =
- V1 arg r! V1 arg r! 0 d) movclr, VM_REGISTER V1 to loc endof
+ V1 type typesize 4 < if
+ V1 :typesz! dx V1 arg r! 0 d) movclr, V1 arg r! dx mov, else
+ V1 arg r! V1 arg r! 0 d) mov, then
+ VM_REGISTER V1 to loc endof
endcase rdrop ;
\ Before doing an operation on two operands, we verify that they are
@@ -104,6 +107,12 @@ struct+[ VMOp
\ Verify that we're in "neutral" position with regards to registers
: neutral# reglvl if abort" unbalanced reg allot/free" then ;
+\ If one op is larger than the other, copy the smaller one to a register and
+\ copy the type of the larger op to the smaller.
+: harmonizeops vmop type typesize vmop^ type typesize 2dup < if
+ 2drop vmop :>reg vmop^ type to vmop type else > if
+ vmop^ :>reg vmop type to vmop^ type then then ;
+
\ Code generation - Functions, calls, ret, pspush, pspop
\ generate function prelude code by allocating "locsz" bytes on RS.
@@ -148,7 +157,7 @@ struct+[ VMOp
\ Code generation - Binary ops
: binop doer ' , does> ( 'w ) @
- vmop :>res vmop :compileDest vmop^ :compile execute vmop^ :init ;
+ vmop :>res harmonizeops vmop :compile vmop^ :compile execute vmop^ :init ;
binop vm+, add,
binop vm-, sub,
binop vm&, and,
@@ -218,7 +227,7 @@ unaryop vmnot, not, ( ~ )
: vm+n, ( n -- ) vmop :loclo VM_CONSTANT = if
to+ vmop arg
- else vmop :compileDest i) add, then ;
+ else vmop :>res vmop :compile i) add, then ;
\ post-inc/dec op1
\ It's a bit complicated here. Before we inc/dec, we need a copy of the current
diff --git a/fs/tests/cc/cc.fs b/fs/tests/cc/cc.fs
@@ -70,6 +70,7 @@ globdata 4 + 16b @ 42 #eq
'2' binop2 44 #eq
binop3 $605 #eq
binop5 1 #eq
+binop6 $1fe #eq
structop1 44 #eq
structop2 45 #eq
opwidth1 42 #eq
diff --git a/fs/tests/cc/test.c b/fs/tests/cc/test.c
@@ -291,6 +291,12 @@ int binop5() {
int x = 2;
return x && 1;
}
+// the i386 VM performed this add in 8b mode, not carrying the $100.
+unsigned int binop6() {
+ unsigned int x = $ff;
+ unsigned char y = $ff;
+ return x + y;
+}
short structop1() {
globdata.bar += 2;
return globdata.bar;