commit 34d5f6375a2a57d6cb5d55fff6fedf235122830c
parent df2a6f97cd432cbd79a6936abfd3c45691bf6c64
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 22 Jul 2022 07:57:30 -0400
asm/i386: add ability to MOV to/from special (CR*, DR*, TR*) registers
Diffstat:
1 file changed, 19 insertions(+), 10 deletions(-)
diff --git a/fs/asm/i386.fs b/fs/asm/i386.fs
@@ -12,7 +12,7 @@
4 const SIB \ mod 0/1/2 + r/m 4 == SIB
0 value op8b \ is current op in 8bit mode?
-0 value opsreg \ is current op an Sreg?
+0 value opsreg \ if we have a "special" reg, this contains the override opcode.
1 value opdirec \ 1: reg=tgt r/m=src 0: reg=src r/m=tgt
3 value opmod \ by default, we're in "direct reg" mode
-1 value opreg \ -1 = unset
@@ -33,6 +33,7 @@
: is16bit? realmode ;
\ in 16bit, abs mem = mod0 + rm 6, in 32-bit, it's rm 5
: memoprm 5 is16bit? + ;
+: maybe8b ( opcode -- opcode ) op8b not or ;
: dw, is16bit? if w, else , then ;
: dwc, op8b if c, else dw, then ;
@@ -53,7 +54,7 @@
\ "opcode" needs to habe bits 1 and 0 *unset*
: op, ( opcode -- ) \ write "opcode", mixing it with opdirec and op8b
- opdirec << or op8b not or dup $ff > if w, else c, then ;
+ opdirec << or dup 8 rshift $ff and ?dup if c, then c, ;
: 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, ;
@@ -78,7 +79,7 @@
: opimm, ( opcode opreg -- ) \ write the operation in "immediate" mode
0 to opdirec \ TODO: allow sign-extend by making this logic variable
- opreg! op, msd, imm, asm$ ;
+ opreg! maybe8b op, msd, imm, asm$ ;
\ Setting arguments
@@ -111,9 +112,18 @@ AX _ ax BX _ bx CX _ cx DX _ dx SP _ sp BP _ bp SI _ si DI _ di
: _ doer ( reg -- ) c, does> c@ ( reg ) r! 1 to op8b ;
AL _ al BL _ bl CL _ cl DL _ dl AH _ ah BH _ bh CH _ ch DH _ dh
-: _ doer ( reg -- ) c, does> c@ ( reg ) opreg! 1 to opsreg ;
+: _ doer ( reg -- ) c, does> c@ ( reg ) opreg! $8c to opsreg ;
ES _ es SS _ ss DS _ ds FS _ fs GS _ gs
+: _ doer ( reg -- ) c, does> c@ ( reg ) opreg! $0f20 to opsreg ;
+0 _ cr0 2 _ cr2 3 _ cr3
+
+: _ doer ( reg -- ) c, does> c@ ( reg ) opreg! $0f21 to opsreg ;
+0 _ dr0 1 _ dr1 2 _ dr2 3 _ dr3 6 _ dr6 7 _ dr7
+
+: _ doer ( reg -- ) c, does> c@ ( reg ) opreg! $0f24 to opsreg ;
+6 _ tr6 7 _ tr7
+
: i) ( imm -- ) 1 to imm? to imm ;
: 16breg>[oprm] ( reg ) case
@@ -163,7 +173,7 @@ $c3 op ret, $fa op cli, $fc op cld,
\ Conditional jumps
: op ( opcode -- ) doer , does> ( rel32-or-16 a -- ) @ op, rel, ;
-$840f op jz, $850f op jnz,
+$0f84 op jz, $0f85 op jnz,
\ JMP and CALL
\ These are special. They can either be called with a modrm tgt, or with *no
@@ -186,8 +196,8 @@ $04e9 op jmp, $02e8 op call,
dup 16 rshift opreg! $ffff and opmodrm, ;
$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,
+$000f9f op setg, $000f9c op setl, $000f94 op setz, $000f95 op setnz,
+$020f01 op lgdt, $030f01 op lidt,
\ Two operands
\ opcode format 00000000 ssssssss iiiiirrr mmmmmm00
@@ -198,7 +208,7 @@ $02010f op lgdt, $03010f op lidt,
: op ( opcode -- ) doer , does> @ ( opcode )
imm? if
8 rshift dup >> $fc and $80 or swap 7 and ( opcode opreg ) opimm,
- else $ff and opmodrm, then ;
+ else $ff and maybe8b opmodrm, then ;
$040000 op add, $3c0738 op cmp, $2c0528 op sub, $a8f084 op _test,
$240420 op and, $0c0108 op or, $340630 op xor,
@@ -231,8 +241,7 @@ $58 op pop, $50 op _push,
$b0 op8b not 3 lshift or ( b0 or b8 ) opreg or c, imm, asm$
else $c7 c, 0 opreg! msd, imm, asm$ then
else
- opsreg if $8c opdirec << or c, msd, asm$ else
- $88 opmodrm, then then ;
+ opsreg if opsreg else $88 maybe8b then opmodrm, then ;
\ INT is special
: int, ( n -- ) $cd c, c, ;