Author: wmb
Date: 2008-01-17 10:17:08 +0100 (Thu, 17 Jan 2008)
New Revision: 777
Modified:
cpu/x86/assem.fth
cpu/x86/disassem.fth
Log:
x86 assembler/disassembler - Fixed several bugs in 16-bit mode.
Modified: cpu/x86/assem.fth
===================================================================
--- cpu/x86/assem.fth 2008-01-12 17:22:24 UTC (rev 776)
+++ cpu/x86/assem.fth 2008-01-17 09:17:08 UTC (rev 777)
@@ -119,7 +119,7 @@
10 2 32REGS [EAX] [ECX] [EDX] [EBX] [ESP] [EBP] [ESI] [EDI]
3 2 pmREGS [AX] [CX] [DX]
- 2 4 pmreg [SP]
+ 2 4 32reg [SP]
6 3 REGS ES CS SS DS FS GS
3 4 REGS # #) S#)
@@ -240,7 +240,7 @@
\ Assemble mod-r/m byte and s-i-b byte if necessary
: SOP, ( mr rmid mod -- )
- protected? if
+ 16bit? 0= if
2 pick [SIB] = if ( [SIB] rmid mod )
[ESP] -rot mod-rm, ( [SIB] ) \ Scaled index mode
drop ( )
@@ -263,11 +263,11 @@
\ (nonexistent) "<no-displacement> [EBP]" mode.
OVER #) = IF
- protected? if 5 else 6 then
+ 16bit? if 6 else 5 then
swap 0 mod-rm, DROP ADR, EXIT
THEN ( disp mr rmid )
- protected? if
+ 16bit? 0= if
\ Special case for "0 [EBP]" ; use short 0 displacement
\ instead of [EBP] (there is no [EBP] addressing mode
\ because that encoding is used for 32-bit displacement.)
@@ -329,6 +329,8 @@
\ 2MI define ascii adjust instructions.
: 2MI CREATE C, DOES> C@ ASM8, 12 ASM8, normal ;
+: prefix-0f h# 0f asm8, ;
+
\ 3MI define branch instructions, with one or two bytes of offset.
: 3MI \ conditional branches
( op -- ) create c,
@@ -337,7 +339,7 @@
dup small? if ( op disp8 )
swap asm8, asm8,
else ( op disp )
- h# 0f asm8, swap h# 10 + asm8,
+ prefix-0f swap h# 10 + asm8,
real? if 2 else 4 then - adr,
then
normal
@@ -345,7 +347,7 @@
\ 4MI define LDS, LEA, LES instructions.
: 4MI CREATE C,
- DOES> C@ dup h# b2 h# b5 between if h# 0f asm8, then ASM8, MEM,
+ DOES> C@ dup h# b2 h# b5 between if prefix-0f then ASM8, MEM,
normal
;
@@ -455,7 +457,7 @@
ELSE ( dst apf )
1+ OVER SEG? IF ( dst apf' ) \ Segment register
OVER FS >= IF ( dst apf' ) \ FS or GS
- H# 0F ASM8, 3 + C@ ( dst opcode )
+ prefix-0f 3 + C@ ( dst opcode )
SWAP GS = IF 10 OR THEN ( opcode' )
ASM8, ( )
ELSE ( dst apf' ) \ CS, DS, ES, or SS
@@ -528,7 +530,7 @@
2 1 15mi lgdt 3 1 15mi lidt 2 0 15mi lldt 3 0 15mi ltr
\ LSS, LFS, LGS
-: 16MI CREATE C, DOES> C@ H# 0F ASM8, ASM8, MEM, normal ;
+: 16MI CREATE C, DOES> C@ prefix-0f ASM8, MEM, normal ;
\ TEST bits in dest
: TEST (S source dest -- )
@@ -580,7 +582,7 @@
\ 0x22 for normal->special direction, 0x20 for special->normal direction
\ or with 0 for CRx, 1 for DRx, 4 for TRx
: special-mov ( s d -- )
- h# 0f asm8,
+ prefix-0f
[ also forth ]
dup spec? if h# 22 else swap h# 20 then ( norm-reg spec-reg opcode )
over o# 7000 and case
@@ -634,6 +636,10 @@
;
: MOV (MOV) normal ;
+\ Use "byte movsx" for the r8 form, "movsx" for the r16 form
+: movsx ( r/m r -- ) prefix-0f h# be size, r/m, ;
+: movzx ( r/m r -- ) prefix-0f h# b6 size, r/m, ;
+
\ Most instructions are defined here. Those mnemonics in
\ parenthetic comments are defined earlier or not at all.
@@ -681,12 +687,12 @@
9B 1MI WAIT ( XCHG ) D7 1MI XLAT 30 13MI XOR
C2 14MI +RET
-: invd ( -- ) h# 0f asm8, h# 08 asm8, ;
-: wbinvd ( -- ) h# 0f asm8, h# 09 asm8, ;
-: wrmsr ( -- ) h# 0f asm8, h# 30 asm8, ;
-: rdtsc ( -- ) h# 0f asm8, h# 31 asm8, ;
-: rdmsr ( -- ) h# 0f asm8, h# 32 asm8, ;
-: cpuid ( -- ) h# 0f asm8, h# a2 asm8, ; \ Arg in %eax, results in ax,bx,dx,cx
+: invd ( -- ) prefix-0f h# 08 asm8, ;
+: wbinvd ( -- ) prefix-0f h# 09 asm8, ;
+: wrmsr ( -- ) prefix-0f h# 30 asm8, ;
+: rdtsc ( -- ) prefix-0f h# 31 asm8, ;
+: rdmsr ( -- ) prefix-0f h# 32 asm8, ;
+: cpuid ( -- ) prefix-0f h# a2 asm8, ; \ Arg in %eax, results in ax,bx,dx,cx
\ Structured Conditionals
\ single pass forces fixed size. optimize for small, fast structures:
@@ -720,7 +726,7 @@
drop here 2+ + ( addr )
#) jmp
else
- h# 0f asm8, h# 10 + asm8, ( offset )
+ prefix-0f h# 10 + asm8, ( offset )
real? if 2 else 4 then - adr,
then
then
@@ -739,7 +745,7 @@
dup h# eb = if
drop h# e9 asm8,
else
- h# 0f asm8, h# 10 + asm8,
+ prefix-0f h# 10 + asm8,
then
real? if 0 asm16, else 0 asm32, then
else
Modified: cpu/x86/disassem.fth
===================================================================
--- cpu/x86/disassem.fth 2008-01-12 17:22:24 UTC (rev 776)
+++ cpu/x86/disassem.fth 2008-01-17 09:17:08 UTC (rev 777)
@@ -28,7 +28,7 @@
true value op32?
: opv@ ( -- l | w ) op32? if op32@ else op16@ then ;
true value ad32?
-: adv@ ( -- l | w ) ad32? if op32@ else op16@ wext then ;
+: adv@ ( -- l | w ) ad32? if op32@ else op16@ then ;
: dis16 ( -- ) false is op32? false is ad32? ;
: dis32 ( -- ) true is op32? true is ad32? ;
\ XXX We should also change the register names e.g. from "eax" to "ax"
@@ -60,7 +60,7 @@
case
0 of " " exit endof
1 of op8@ bext dup 0>= if ?+ then endof
- 2 of ?+ adv@ endof
+ 2 of ?+ adv@ wext endof
endcase
(u.) disp-buf pack count
;
@@ -80,7 +80,7 @@
," eax" ," ecx" ," edx" ," ebx" ," esp" ," ebp" ," esi" ," edi"
end-string-array
-: >reg ( -- adr len ) >regw count ;
+: >reg ( -- adr len ) >regw count op32? 0= if 1 /string then ;
: >greg ( -- adr len ) wbit if >reg else >reg8 count then ;
@@ -101,8 +101,10 @@
>scale count $add-text ( )
then ( )
;
+: .[ " [" $add-text ;
+: .] " ]" $add-text ;
: add-disp ( sib? reg mod -- )
- " [" $add-text ( sib? reg mod )
+ .[ ( sib? reg mod )
2dup 0<> swap 5 <> or if ( sib? reg mod ) \ D32
swap >reg $add-text ( sib? mod )
else ( sib? reg mod )
@@ -110,9 +112,53 @@
then ( sib? mod )
swap if get-scaled then ( mod )
get-disp $add-text ( )
- " ]" $add-text ( )
+ .] ( )
;
+: .ea32 ( reg mod -- )
+ >r ( reg r: mod )
+ dup 4 = if ( reg ) \ s-i-b
+ drop get-op true lowbits ( true reg )
+ else ( reg ) \ displaced
+ false swap ( false reg )
+ then ( sib? reg )
+ r> add-disp
+;
+
+string-array modes16
+ ," [bx+si]"
+ ," [bx+di]"
+ ," [bp+si]"
+ ," [bp+di]"
+ ," [si]"
+ ," [di]"
+ ," [bp]"
+ ," [bx]"
+end-string-array
+
+: add-disp16 ( disp -- )
+ h# ffff and (u.) disp-buf pack count $add-text
+;
+: +disp16 ( disp -- )
+ dup 0< if
+ " -" $add-text negate
+ else
+ " +" $add-text
+ then
+ add-disp16
+;
+
+: .ea16 ( reg mod -- )
+ over 6 = over 0= and if ( reg mod )
+ \ disp16 only, takes the place of the [bp] mode
+ 2drop op16@ .[ add-disp16 .] exit
+ then ( reg mod )
+ swap modes16 count $add-text ( mod )
+ case
+ 1 of op8@ +disp16 endof
+ 2 of op16@ +disp16 endof
+ endcase
+;
: .ea ( -- )
" " ea-text place
lowbits hibits >r ( reg ) ( r: mod )
@@ -120,12 +166,7 @@
>greg $add-text ( )
r> drop ea-text ". exit
then ( reg )
- dup 4 = if ( reg ) \ s-i-b
- drop get-op true lowbits ( true reg )
- else ( reg ) \ displaced
- false swap ( false reg )
- then ( sib? reg )
- r> add-disp
+ r> ad32? if .ea32 else .ea16 then
ea-text ".
;
: ,ea ( -- ) ., .ea ;
@@ -133,7 +174,7 @@
\ Display formatting
variable start-column
-: op-col ( -- ) start-column @ d# 8 + #out @ - 0 max spaces ;
+: op-col ( -- ) start-column @ d# 9 + #out @ - 1 max spaces ;
string-array >segment
," es" ," cs" ," ss" ," ds" ," fs" ," gs"
@@ -164,7 +205,7 @@
: iub ( -- ) op8@ (.) type ;
: iw ( -- ) op16@ (.) type ;
: iv ( -- ) opv@ (.) type ;
-: iuv ( -- ) opv@ (u.) type ;
+: iuv ( -- ) adv@ (u.) type ;
: ,ib/v ( -- ) ., wbit if opv@ else op8@ then (u.) type ;
: al/x ( -- ) wbit if ." eax" else ." al" then ;
: ,al/x ( -- ) ., al/x ;
@@ -186,8 +227,18 @@
," s" ," ns" ," pe" ," po" ," l" ," ge" ," le" ," g"
end-string-array
-: jb ( -- ) op8@ bext pc @ + dup branch-target ! showaddr ;
-: jv ( -- ) adv@ pc @ + dup branch-target ! showaddr ;
+: showbranch ( offset -- )
+ pc @ ad32? if ( offset pc )
+ + ( pc' )
+ else ( offset pc )
+ lwsplit -rot ( pc.high offset pc.low )
+ + h# ffff and ( pc.high pc.low' )
+ swap wljoin ( pc' )
+ then ( pc' )
+ dup branch-target ! showaddr
+;
+: jb ( -- ) op8@ bext showbranch ;
+: jv ( -- ) adv@ showbranch ;
: .jcc ( -- ) ." j" low4bits >cond ". op-col jb ;
: ea,g ( -- ) get-ea .ea ., gb/v ;
@@ -404,7 +455,12 @@
endcase
;
-: ap ( -- ) adv@ ." far " op16@ .x ." :" showaddr ;
+: .4x ( n -- ) push-hex <# u# u# u# u# u#> type pop-base ;
+: ap ( -- )
+ adv@ ." far "
+ op16@ push-hex (.) type pop-base
+ ." :" ad32? if showaddr else .4x then
+;
string-array >8line-ops
," cwde" ," cdq" ," call" ," wait" ," pushfd" ," popfd" ," sahf" ," lahf"