commit fbabbf4b2048261a8fad01ed9e789dfb94a37d1a
parent c9a4ed1808b072963a5a8104a06eb1c66415d7f4
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 15 Jul 2022 10:50:16 -0400
asm/i386: add d) support to sp register
Diffstat:
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/fs/asm/i386.fs b/fs/asm/i386.fs
@@ -8,6 +8,7 @@
0 const AL 1 const CL 2 const DL 3 const BL
4 const AH 5 const CH 6 const DH 7 const BH
5 const MEM \ mod 0 + r/m 5 == abs memory
+4 const SIB \ mod 0/1/2 + r/m 4 == SIB
\ Size modes
0 const SZ32
@@ -22,6 +23,7 @@ SZ32 value opsz
0 value imm? \ are we in immediate mode?
0 value imm \ value of current immediate, if set
0 value disp \ displacement value
+0 value sib \ value of the SIB byte
\ Utilities
: asm$ SZ32 to opsz 1 to opdirec 3 to opmod -1 to opreg -1 to oprm 0 to imm? ;
@@ -51,6 +53,9 @@ SZ32 value opsz
: modrm, ( -- ) \ write down modrm, errors out if not all parts are there.
opmod 3 lshift opreg or 3 lshift oprm or dup $100 < _assert c, ;
+: sib, ( -- ) \ write down the SIB byte if needed.
+ oprm SIB = opmod 3 < and if sib c, then ;
+
: disp, ( -- ) \ write down displacement if needed.
opmod case
0 of = oprm MEM = if disp , then endof
@@ -58,6 +63,8 @@ SZ32 value opsz
2 of = disp , endof
endcase ;
+: msd, modrm, sib, disp, ;
+
: imm, ( -- ) \ write down an immediate
imm opsz case
SZ32 of = , endof
@@ -67,11 +74,11 @@ SZ32 value opsz
endcase ;
: opmodrm, ( opcode -- ) \ write the operation in "modrm" mode
- op, modrm, disp, asm$ ;
+ op, msd, asm$ ;
: opimm, ( opcode opreg -- ) \ write the operation in "immediate" mode
0 to opdirec \ TODO: allow sign-extend by making this logic variable
- opreg! op, modrm, disp, imm, asm$ ;
+ opreg! op, msd, imm, asm$ ;
\ Setting arguments
@@ -112,9 +119,10 @@ AL _ al BL _ bl CL _ cl DL _ dl AH _ ah BH _ bh CH _ ch DH _ dh
-1 to opreg
0 to opdirec
then
+ oprm SP = if $24 to sib then \ special case for ESP
disp case
of not oprm MEM = to opmod endof \ mod = 0 except if rm==MEM
- $100 of > 1 to opmod endof
+ of isbyte? 1 to opmod endof
2 to opmod
endcase ;
@@ -176,11 +184,11 @@ $240420 op and, $0c0108 op or, $340630 op xor,
\ Shifts. They come in 2 versions. The "naked" version is imm-only. The "cl"
\ versions has CL as an inherent argument.
: op ( opcode -- ) doer , does> @ dup 8 rshift ( opcode opreg )
- imm? _assert opreg! c, modrm, disp, imm c, asm$ ;
+ imm? _assert opreg! c, msd, imm c, asm$ ;
$04c1 op shl, $05c1 op shr,
: op ( opcode -- ) doer , does> @ dup 8 rshift ( opcode opreg )
- imm? not _assert opreg! c, modrm, disp, asm$ ;
+ imm? not _assert opreg! c, msd, asm$ ;
$04d3 op shlcl, $05d3 op shrcl,
\ Push/Pop
@@ -190,13 +198,13 @@ $58 op pop, $50 op _push,
\ PUSH can also push an immediate
: push, imm? if
- imm isbyte? if $6a c, SZ8 to opsz else $68 c, then imm, asm$ else
+ opsz SZ8 = if $6a else $68 then c, imm, asm$ else
_push, then ;
\ MOV has this special reg<-imm shortcut
: mov,
imm? if opmod 3 = if \ mov reg, imm shortcut
$b0 opsz SZ8 = not 3 lshift or ( b0 or b8 ) opreg or c, imm, asm$
- else $c7 c, 0 opreg! modrm, disp, imm, asm$ then
+ else $c7 c, 0 opreg! msd, imm, asm$ then
else $88 opmodrm, then ;
diff --git a/fs/tests/asm/i386.fs b/fs/tests/asm/i386.fs
@@ -71,4 +71,15 @@ code foo7
ret,
foo7 42 #eq
+
+\ ESP+disp
+code foo8
+ 42 i) push,
+ ax sp 0 d) mov,
+ sp 4 i) add,
+ bp 4 i) sub,
+ bp 0 d) ax mov,
+ ret,
+
+foo8 42 #eq
testend