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"