@@ 257,21 257,23 @@ $e2 op loop, $e1 op loopz, $e0 op loopnz,
\ W=ax A=di PSP=si RSP=sp
: A>) ( halop -- halop ) $40000 or ;
+: A>? $40000 and bool ;
: <>) ( halop -- halop ) $80000 xor ;
+: <>? $80000 and bool ;
: &) ( halop -- halop ) $10000 or ;
+: &? $10000 and bool ;
: +) d) ;
: RSP) sp 0 d) ;
: _& ( opmod -- opmod )
- dup indirect? if dup ismem? if bank@ i) else
- dup mod@ 0 = if ( indirect no disp ) $c0 or else ( indirect + disp )
- abort" TODO: &) lea," then then then ;
+ dup &? if
+ $fffeffff and dup indirect? if dup ismem? if bank@ i) else
+ dup mod@ 0 = if ( indirect no disp ) $c0 or else ( indirect + disp )
+ bx swap lea, bx then then then then ;
: halop>dstsrc ( halop -- dst src )
- dup 16 rshift >r $fff2ffff and ( src ) \ V1=flags
- r@ 1 and ( & ) if _& then ( src )
- r@ 4 and ( A> ) if di else ax then ( src dst )
- r> 8 and not if swap then ;
+ _& dup A>? if di else ax then ( src dst )
+ over <>? not if swap then ;
: op doer ' , does> @ ( halop w ) dip halop>dstsrc | execute ;
op @, ?movzx, op @!, xchg, op addr, lea,
@@ 280,10 282,16 @@ op @, ?movzx, op @!, xchg, op addr, lea,
: op doer ' , does> @ ( halop w ) dip halop>dstsrc ( dst src )
bi+ 16b? | 8b? or if bx swap ?movzx, bx then | execute ;
op +, add, op -, sub, op compare, cmp,
+op &, and, op |, or, op ^, xor,
-: *,
- halop>dstsrc over AX? not if over ax mov, then ( dst src )
- mul, ( dst ) dup AX? if drop else ax xchg, then ;
+: _pre ( op -- op src )
+ _& dup <>? if ax over xchg, then dup A>? if di ax mov, then dup
+ dup imm? if bx swap mov, bx then ;
+: _post ( op -- )
+ dup A>? if di ax xchg, then dup <>? if ax xchg, else drop then ;
+: *, _pre mul, _post ;
+: /, _pre dx dx xor, div, _post ;
+: %, _pre dx dx xor, div, ax dx mov, _post ;
: op doer ' , does> @ dip halop>dstsrc ( dst src )
dup imm? not if cx swap mov, cl then | execute ;
@@ 296,15 304,14 @@ op <<, shl, op >>, shr,
bx 0 d) r> if 8b) then r> if 16b) then ;
: [@], _ mov, ; : [!], _ swap mov, ;
-$2 const C)
-$3 const NC)
-$4 const Z)
-$5 const NZ)
-$2 const <)
-$3 const >=)
-$6 const <=)
-$7 const >)
-$c const s<)
-$d const s>=)
-$e const s<=)
-$f const s>)
+\ These are used so often that it's worth redefining them in their more
+\ efficient version.
+: _ ?dup if swap dup 0< if neg i) sub, else i) add, then then ;
+: ps+, si _ ; : rs+, sp _ ;
+: dup, -4 ps+, PSP) !, ;
+: nip, 4 ps+, ;
+: drop, PSP) @, nip, ;
+
+$2 const C) $3 const NC) $4 const Z) $5 const NZ)
+$2 const <) $3 const >=) $6 const <=) $7 const >)
+$c const s<) $d const s>=) $e const s<=) $f const s>)
@@ 185,4 185,10 @@ code test19 ( a b -- n )
PSP) 16b) +, nip, exit,
1 $1ffff test19 $20000 #eq
+
+\ test <>) with *, which was problematic on i386
+code test20 ( a b -- n )
+ PSP) <>) *, drop, exit,
+
+4 5 test20 20 #eq
testend
@@ 996,7 996,7 @@ static void buildsysdict() {
entry("|,"); compbinopwr(0x09); retwr();
entry("^,"); compbinopwr(0x0a); retwr();
entry("addr,"); compopwr(0x17); retwr();
- entry("negate,"); compileop(0x4e); retwr();
+ entry("-W,"); compileop(0x4e); retwr();
entry("W=0>Z,"); compileop(0x5d); retwr();
entry("C>W,"); compileop(0x5e); cwritewr(); retwr();
entry("A=0>Z,"); compileop(0x5f); retwr();
@@ 1014,6 1014,8 @@ static void buildsysdict() {
entry("xor"); binopwr(0x0a, OPPSP); nipwr(); retwr();
entry("lshift"); wopwr(0x12 /* @! */, OPPSP); binopwr(0x05, OPPSP); nipwr(); retwr();
entry("rshift"); wopwr(0x12 /* @! */, OPPSP); binopwr(0x06, OPPSP); nipwr(); retwr();
+ entry("<<"); litwr(1); callwr(find("lshift")); retwr();
+ entry(">>"); litwr(1); callwr(find("rshift")); retwr();
entry("16b)"); litwr(OP16B); callwr(find("or")); retwr();
entry("8b)"); litwr(OP8B); callwr(find("or")); retwr();
entry("32b)"); litwr((OP8B|OP16B)^0xffffffff); callwr(find("and")); retwr();
@@ 1022,8 1024,6 @@ static void buildsysdict() {
entry("&)"); litwr(OPDIRECT); callwr(find("or")); retwr();
entry("i)"); callwr(find("m)")); callwr(find("&)")); retwr();
entry("!,"); callwr(find("<>)")); callwr(find("@,")); retwr();
- entry("<<n,"); callwr(find("i)")); callwr(find("<<,")); retwr();
- entry(">>n,"); callwr(find("i)")); callwr(find(">>,")); retwr();
entry("dup,");
litwr(0xfffffffc); callwr(find("ps+,"));
callwr(find("PSP)")); callwr(find("!,")); retwr();