commit a680f1ecf8953f05f92d55ff0b508fb79dd03c5b
parent ee0beaf1bbed9779c107ea59d4ca605400dd4e56
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Thu, 21 Jul 2022 19:51:42 -0400
asm/i386: improve modrm handling in 16bit mode
Also add LGDT and LIDT.
Diffstat:
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/fs/asm/i386.fs b/fs/asm/i386.fs
@@ -7,7 +7,6 @@
4 const SP 5 const BP 6 const SI 7 const DI
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
0 value op8b \ is current op in 8bit mode?
@@ -23,11 +22,13 @@
\ Utilities
: asm$ 0 to op8b 1 to opdirec 3 to opmod -1 to opreg -1 to oprm 0 to imm? ;
-: _err abort" argument error" ;
+: _err asm$ abort" argument error" ;
: _assert not if _err then ;
: w, here w! 2 allot ;
: isbyte? ( n -- f ) $100 < ;
: is16bit? realmode ;
+\ in 16bit, abs mem = mod0 + rm 6, in 32-bit, it's rm 5
+: memoprm 5 is16bit? + ;
: dw, is16bit? if w, else , then ;
: dwc, op8b if c, else dw, then ;
@@ -57,7 +58,7 @@
: disp, ( -- ) \ write down displacement if needed.
opmod case
- 0 of = oprm MEM = if disp dw, then endof
+ 0 of = oprm memoprm = if disp dw, then endof
1 of = disp c, endof
2 of = disp dw, endof
endcase ;
@@ -107,15 +108,24 @@ AL _ al BL _ bl CL _ cl DL _ dl AH _ ah BH _ bh CH _ ch DH _ dh
: i) ( imm -- ) 1 to imm? to imm ;
+: 16breg>[oprm] ( reg ) case
+ SI of = 4 endof
+ DI of = 5 endof
+ BP of = 6 endof
+ BX of = 7 endof
+ _err
+ endcase ;
+
: d) ( disp -- ) to disp
oprm 0< if \ first argument. we need to move it to oprm and change direction
opreg to oprm
-1 to opreg
0 to opdirec
then
+ is16bit? if oprm 16breg>[oprm] to oprm 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
+ of not oprm memoprm = to opmod endof \ mod = 0 except if rm==MEM
of isbyte? 1 to opmod endof
2 to opmod
endcase ;
@@ -124,7 +134,7 @@ AL _ al BL _ bl CL _ cl DL _ dl AH _ ah BH _ bh CH _ ch DH _ dh
oprm 0< _assert \ can't have m) with second argument
opreg 0< if \ first argument, we invert direction
0 to opdirec then
- 0 to opmod MEM to oprm ;
+ 0 to opmod memoprm to oprm ;
\ Operations
@@ -161,7 +171,7 @@ $840f op jz, $850f op jnz,
$04e9 op jmp, $02e8 op call,
\ Single operand
-\ opcode format 00000000 00000rrr mmmmmmmm mmmmmm00
+\ opcode format 00000000 00000rrr mmmmmmmm mmmmmmmm
\ r = opreg override
\ m = modrm opcode
: op ( reg opcode -- ) doer , does> @ ( opcode -- )
@@ -169,6 +179,7 @@ $04e9 op jmp, $02e8 op call,
$0400f7 op mul, $0300f7 op neg, $0200f7 op not,
$0100ff op dec, $0000ff op inc,
$009f0f op setg, $009c0f op setl, $00940f op setz, $00950f op setnz,
+$02010f op lgdt, $03010f op lidt,
\ Two operands
\ opcode format 00000000 ssssssss iiiiirrr mmmmmm00