[G4 Mac OF] native code disassembler for ppc 7400 7450 7455...

  • Follow


\ "dis.of" Public Domain replacement dis revised 30-Jun-2008
\
\ Revision history. This final revision of "Basic Form" dis.of 
\ contains the following improvements:
\ 
\ * dcba included in G4 instruction set.
\ * 'dasm' & '+dasm' variants added which stop at end of code bloc.
\ * Fields defined 'rA|0' now rendered '0' instead of 'r0' when A=0.
\ * Instructions with invalid operand combinations decode as 'data'.
\ * Global 'opcode' == 0 signals unrecognized or invalid instruction
\ * 'dis-help' removed, as 0 not a valid operand for all instructns.
\
\ Future addition of Alternative Form and Preferred Form instructions
\ will be referred to as "customisations" rather than "versions"
\
\ Tested only on 2003-2004 G4 eMacs with Open Firmware v4.6.4.fi 
\ and v4.88.8f0. Anyone trying it out, please report whether
\ compatible or incompatible, and/or any extra steps needed to make
\ it work on your particular model of ppc Macintosh.
\
\ To use, place an all-user-readable file named 'dis.of' containing
\ this source in the root directory of your Mac's Startup Volume
\ (boot disk). Make sure the backslash beginning the first line is
\ the first character in the file. Restart, holding down the
\ Cmd-Option-O-F key combination. When Open Firmware's '0 > ' prompt
\ appears type:
\
\ boot hd:\dis.of
\
\ **** IF YOU COPIED THIS TEXT FROM A WEB-BASED NEWSREADER 
\ AND GET COMPILE ERRORS caused by some weird-looking chars, 
\ load it into BBEdit or TextWrangler and choose "Zap Gremlins..."
\ from the Text Menu. Nominate a single space char to replace them.
\
\ This revised 'dis' differs from bult-in original in that 'dis1' 
\ (renamed 'disasm1' in this source) does the screen output. It 
\ also jumps to the next-lowest 32-bit aligned address without
\ comment when requested to disassemble a non-aligned address.
\ Numbers longer than 4 digits default to hexadecimal.

align hex     \ just in case

0 value ADDR  \ address of current (or next) ppc instruction

\ 021 proxies for other secondary opcodes with same validation case
: prep-rA=rT-rejection ( u -- u|021 )
    CASE 
       023 OF  021 >r  ENDOF
       029 OF  021 >r  ENDOF
       02b OF  021 >r  ENDOF
       DUP >r
    ENDCASE
    r>
;
: prep-rA=r0-rejection ( u -- u|025 )  \ group together to validate
    CASE
       027 OF  025 >r  ENDOF
       02d OF  025 >r  ENDOF
       031 OF  025 >r  ENDOF
       033 OF  025 >r  ENDOF
       035 OF  025 >r  ENDOF
       037 OF  025 >r  ENDOF
       DUP >r
    ENDCASE
    r>
; 
: ?rA=0-averse ( -- flag ) 
    addr @   ( instruction with Secondary Mask = 07ff )
         07e AND   06e =
;
: ?rA=rT-averse ( -- flag ) 
    addr @   ( instruction with Secondary Mask = 07ff )
         57e AND   06e =
; 
: @rT ( -- n )        \ extract contents of ppc instruction field rT
    addr @ 015 >> 0000001f AND
;
: @rA ( -- n )        \ get contents of field rA
    addr @ 010 >> 0000001f AND
;
: @nB ( -- n )        \ get contents of field nB
    addr @ 0b >> 0000001f AND  
;
: @nR ( -- n )  ( rT+n = last reg in range needed to hold nB bytes )
     @nB 0= IF d# 32  ( result matches 'lswi','lswx' instruction's )
     ELSE  @nB  THEN  ( Power ISA v2.05 p.59 refers )
     1-               
     4 /   \ this rslt + the T in rT gives # of last gpr overwritten
;

variable last-reg    \ temp for roughmask 'lswi' validation

\ 'lswi' only. ('lswx' similar but can't utilize test as nB dynamic)
: incompatible-operands ( lswi-instruction -- flag )
      @rT @nR +  last-reg !
      last-reg @ d# 32 <     \ will there be wrap-around ?
      IF    @rA @rT  >=   @rA last-reg @ <=   AND
      ELSE  @rA @rT  >=   @rA d# 32 +  last-reg @ <=   OR 
      THEN
;

: wildbits ( bc-instr'n -- flag ) \ spurious bits in br-condition?
      addr @ DUP DUP
      03000000 AND   03000000 =  -ROT
      00c00000 AND   00c00000 =  SWAP
      02a00000 AND   02a00000 =  OR OR
;

0 constant INVALID   \ 0 to roughmask invalidates any instruction
0 value casemask     \ to pass result fm internal to external CASE
   
\ Rough mask sufficient to uniquely identify candidate G4 instr'n
( Alternative Form instrns singled out for more distinctive masks)
( Also, invalid operands need detecting here b4 mnemonic printed )

: roughmask ( addr -- mask ) ( instruction address also in addr )
                             
@ d# 26 >>  \ isolate hi 6-bit major opcode by shifting to far right
CASE    
\ use return stack, as ENDCASE removes top item from stack
   010 OF                      \ 'bc' group (4 instructions)
      wildbits IF  INVALID >r  ELSE fc000003 >r  THEN ENDOF 
   011 OF  fc000003 >r  ENDOF  \ 'sc'       (1 instruction)
   012 OF  fc000003 >r  ENDOF  \ 'b' (branch unconditional) (4)
   013 OF                      \  CR etc group (15 instructions)
      addr @ 000003fe AND DUP  \ extract secondary opcode
      020 =  SWAP  420 =   OR  \ = 020 ( bclr ) or 420 ( bcctr ) ?
      IF wildbits 
         IF  INVALID >r  ELSE fc0007ff >r  THEN 
      THEN              ENDOF
   014 OF  fc000001 >r  ENDOF  \ 'rlwimi' 'rlwimi.'  (2)
   015 OF  fc000001 >r  ENDOF  \ 'rlwinm' 'rlwinm.'  (2)
   017 OF  fc000001 >r  ENDOF  \ 'rlwnm' 'rlwnm.'    (2)
   01f OF                \ Load, Store, Arithmetic, Logic (151-1+2)
      fc0007ff to casemask ( subject to amendment in foll. bloc)
      ?rA=rT-averse   @rA @rT =   AND
      ?rA=0-averse    @rA 0=      AND    OR
      IF   
        INVALID to casemask
      ELSE
        addr @ casemask AND
        CASE 
          7c0004aa ( 'lswi' ) OF  incompatible-operands IF 
                                    INVALID to casemask  THEN  ENDOF
          7c00042a ( 'lswx' ) OF  @rA @rT =  IF
                                    INVALID to casemask  THEN  ENDOF
          7c0002e6 ( 'mftb' ) OF  addr @ fc1effff AND  7c0c42e6 = IF
         \ combine distinguishing operand with 'mftb','mftbu' opcode
                                    fc1fffff to casemask THEN  ENDOF
         ENDCASE
       THEN  casemask >r 
     ENDOF
   03b OF  fc00003f >r  ENDOF  \ First Floating-point group (18)
\  03e OF  fc0007ff >r  ENDOF  ( needed only for 64-bit cpu's )
   03f OF  addr @ d# 32 AND    \ 2nd Floating-point group (47)
      IF   fc00003f >r  ELSE fc0007ff >r  THEN ENDOF
\ Major opcode alone identifies remaining instructions =
\    majority of Load, Store, plus some int arith & logic (39)
   prep-rA=r0-rejection \ CASE 025 proxy for 027,02d,031,033,035,037
   025 OF  @rA IF fc000000 >r ELSE  INVALID >r  THEN  ( rA <> r0 ? )  
   ENDOF   
   prep-rA=rT-rejection \ CASE 021 proxies for CASEs 023, 029, 02b
   021 OF  @rA DUP   0=   SWAP   @rT =  OR  ( rA==r0 OR rA==rT ? )
      IF   INVALID >r   ELSE   fc000000 >r   THEN
   ENDOF
   02e OF  @rA @rT >= 
      IF   INVALID >r   ELSE   fc000000 >r   THEN  \ 'lmw' 
   ENDOF
   ( Remainder ) fc000000 >r
ENDCASE               ( TOTAL PPC INSTRUCTIONS = 287 )
r>
;


\ In the operand-extraction functions which follow, "trimmed-
\ instruction" means the progressively reduced ppc instruction
\ remnant, after all bits to the right of the current operand
\ (if any) have been shifted out.

\ Single operand primitives. If they start with '.' they output to
\ screen. Otherwise they pass the result back to the instruction-
\ nominated calling routine which then has to do the output itself.
\
: .comma ( -- ) 2c emit ;
: .0x ( -- ) [CHAR] 0 emit [CHAR] x emit ;
: .hexdump ( u -- )  0 <# # # # # # # # # #> type ;
  \ can substitute '8 u.r' if it pads with 0's instead of blanks
: .nbr ( trimmed-instruction -- ) 
   01f AND  0 <# decimal #s hex #> \ prints rhs 5 bits in decimal
   type ;
: .gpr ( trimmed-instruction -- )  
     [CHAR] r emit  .nbr ;   \ outputs one of r0 r1 r2 ... r31
: .fpr ( trimmed-instruction -- )   
     [CHAR] f emit  .gpr ;   \ outputs one of fr0 fr1 fr2 ... fr31
: .fld ( trimmed-instruction -- )  
      07 AND  0 <# decimal #s hex #> type ; \ one of 0 1 2 ... 7
: .segr ( trimmed-instruction -- )  
      0f AND  0 <# decimal #s hex #> type ; \ one of 0 1 2 ... 15
: .imm ( trimmed-instruction -- )  0 <# # #> type ; \ 0 1 2 ... f
: .xx ( trimmed-instruction -- ) 
      ff AND .0x 0 <# # # #> type ; \ one of 0x00 0x01 0x02 ... 0xff
: .cc ( trimmed-instruction -- ) 1f AND .xx ;
: .ui ( trimmed-instruction -- )  ( zero trimming in this case )
     ffff AND .0x 0 <# # # # # #> type ; \ 0xXXXX where X = hexdigit
: sign-extend ( ppc-instr'n -- immed-data-field-expanded-to-32-bits)
  lwsplit drop       ( works with rhs 16-bit immediate fields only )
  dup  8000 AND 
  if ffff else 0000 then   \ put sign extension on stack
  wljoin
;
\ 0 alignment assumes code being disassembled fm executable location
: align-address ( address -- address|address-1|address-2|address-3 )
-4 AND
; 
: .si                \ output signed immedate data as 4 hex digits
      sign-extend dup abs 0
      <# # # # #s [char] x hold [char] 0 hold rot sign #> 
      type ;
\ : .si  \ more flexible if your computer's (.) output matches mine
\      sign-extend dup (.) rot dup 0< IF
\          swap 1- rot 1+  \ skip 1st char '-' and reduce length
\          swap rot        \ unscramble stack
\          [char] - emit   \ send a minus sign to output
\      THEN
\      -9 9 between NOT 
\          IF .0x THEN     \ only 1 numeric digit, so skip .0x
\      type
\ ;
: .sd ( trimmed-instruction -- ) .si ; 
: .spr ( trimmed-instruction -- )  \ as in 'mtspr'.
     0 <# decimal #s hex #> type ; \ output matches documentation

: btarget ( offset ppc-instr'n -- to-address ) ( 24-bit abs. field )
( for relative result,supply instrn addr;absolute rslt use 0 offset)
    swap
    03fffffc AND dup   ( + 2 alignment bits -> 26 bits )
    02000000 AND       ( most G4 32-bit addr start with 00 or ff )
    if fc000000  OR  then  \ if hi bit = 1, keep address hi
    +                  \ add the offset    
;

\ These extract-and-display-multiple-operands routines are nominated
\ within the individual ppc instruction records which make up the 
\ data table near the end of this source. By that means, individual
\ ppc instructions tell disasm1 how to display their operands.

: nil ( instruction -- ) DROP \ instr'ns with no operands eg 'rfi'
    9 spaces ;
: all ( instruction -- )    \ used by "data" pseudo-instruction only
   .hexdump ;
: T*4a ( ppc-instruction -- ) \ used by 'ba' and 'bla'
    0 btarget               \ zero offset keeps it absolute
    .hexdump ;
: T*4r ( ppc-instruction -- ) \ 'b','bl' ( r=relative src fld )
    addr btarget \ offset = instrn-addr changes absolute to relative
   .hexdump
;
: cCbNT*4a ( ppc-instruction -- )  \ eg 'bcla'
    align-address 
    dup 010 rshift dup 5 rshift
    .xx .comma .nbr .comma sign-extend .hexdump  ;
: cCbNT*4r ( ppc-instruction -- )  \ eg 'bc'
    align-address
    dup 010 rshift dup 5 rshift
    .xx .comma .nbr .comma sign-extend 
    addr +  ( rel. field + curr. instr'n addr -> final target addr )
   .hexdump  ; 
: cCrAsI ( ppc-instruction -- )    \ 'twi' only
    dup 010 rshift dup 5 rshift
    .cc .comma .gpr .comma .si
; 

: cCbN ( ppc-instruction -- ) \ eg 'bcctr' ("branch to addr in CTR")
    010 rshift dup 5 rshift 
    .cc .comma .nbr
;
: cCrAB ( ppc-instruction -- )     \ 'tw' only
    0b rshift dup 5 rshift dup 5 rshift
    .nbr .comma .gpr .comma .gpr
;

: r@B  ( ppc-instruction -- )  \ eg, 'dcba'
    0b rshift         \ discard all to right of right-most operand
    dup 5 rshift      \ push, then do similar for next operand
    dup 01f and IF .gpr ELSE .nbr THEN .comma .gpr  
;
: rB ( ppc-instruction -- )    \ eg, 'tlbie'
    0b rshift         \ re-position field to rhs for processing
    .gpr              \ output field as a general purpose register
; 

: rT ( ppc-instruction -- ) 
    015 rshift .gpr ;
  : rS ( ppc-instruction -- ) rT ;
: fpT ( ppc-instruction -- )    \ eg 'mffs.'
    015 rshift .fpr ;     
: nT ( ppc-instruction -- )     \ eg 'mtfsb0' 
    015 rshift .nbr
;
: rTA ( ppc-instruction -- )    \ eg, 'neg.'
    010 rshift  
    dup 5 rshift
    .gpr .comma .gpr ;
: rxSA ( ppc-instruction -- ) 
    010 rshift
    dup 5 rshift SWAP
    .gpr .comma .gpr
;
: rTAB  ( ppc-instruction -- )  \ eg, 'mullw'
    0b rshift                   \ position last 5-bit field to rhs
    dup 5 rshift dup 5 rshift   \ push remainder fields in rvs order
    .gpr .comma .gpr .comma .gpr ;  \ pop and print them
  : rSAB ( ppc-instruction -- ) rTAB ; \ eg 'stbx'
: rT@B ( ppc-instruction -- )   \ eg, 'lbzx'
    0b rshift dup 5 rshift dup 5 rshift
    .gpr .comma dup 1f and IF .gpr ELSE .nbr THEN .comma .gpr ;
  : rS@B ( ppc-instruction -- ) rT@B ; \ eg 'ecowx'
: rxSAB ( ppc-instruction -- )         \ eg. 'andc'
    0b rshift
    dup 5 rshift dup 5 rshift SWAP
    .gpr .comma .gpr .comma .gpr
; 
: fpTAB  ( ppc-instruction -- ) \ eg 'fsubs'
    0b rshift       \ bring registers to chopping block for trimming
    dup 5 rshift dup 5 rshift
    .fpr .comma .fpr .comma .fpr ;
  : fpTrAB ( ppc-instruction -- )  \ eg,'lfsux'
    0b rshift \ shift right til only operands (and major opc) remain
    dup 5 rshift dup 5 rshift \ copy & push after prev oprnd removed
    .fpr .comma .gpr .comma .gpr ; 
  : fpSrAB ( ppc-instruction -- ) fpTrAB ; \ eg 'stfsx'
  : fpTr@B ( ppc-instruction -- )  \ eg 'lfdx'
    0b rshift dup 5 rshift dup 5 rshift
    .fpr .comma dup 1f and IF .gpr ELSE .nbr THEN .comma .gpr ;
   : fpSr@B ( ppc-instruction -- ) fpTr@B ; \ eg 'lfdx'
: nTAB ( ppc-instruction -- )   \ eg 'crxor'
    0b rshift
    dup 5 rshift dup 5 rshift
    .nbr .comma .nbr .comma .nbr ;
: rT@nB ( ppc-instruction -- )  \ eg 'lswi'
    0b rshift
    dup 5 rshift dup 5 rshift
    .gpr .comma dup 1f and IF .gpr ELSE .nbr THEN .comma .nbr ;
  : rS@nB ( ppc-instruction -- ) rT@nB ; \ eg 'stswi'
  : rxSAnB ( ppc-instruction -- )        \ eg 'srw'
    0b rshift
    dup 5 rshift dup 5 rshift SWAP
    .gpr .comma .gpr .comma .nbr
;
: fpTAxBC ( ppc-instruction -- )  \ eg, 'fmadds'
    06 rshift 
    dup 5 rshift dup 5 rshift dup 5 rshift \ xBC = output C before B
    .fpr .comma .fpr .comma SWAP .fpr .comma .fpr
;
: rxSAnBCD ( ppc-instruction -- ) \ eg, 'rlwimi'
    01 rshift
    dup 5 rshift dup 5 rshift dup 5 rshift dup 5 rshift
    SWAP .gpr .comma .gpr .comma .nbr .comma .nbr .comma .nbr ;
: rxSABnCD ( ppc-instruction -- ) \ eg, 'rlwinm.'
    01 rshift
    dup 5 rshift dup 5 rshift dup 5 rshift dup 5 rshift
    SWAP .gpr .comma .gpr .comma .gpr .comma .nbr .comma .nbr 
;

: fpTAC ( ppc-instruction -- )   \ eg, 'fmuls.'
    06 rshift
    dup 0a rshift dup 5 rshift
    .fpr .comma .fpr .comma .fpr
;
: rTB ( ppc-instruction -- ) 
    0b rshift                        \ eg, 'mfsrin'
    dup 0a rshift  ( skips register-B and unused reg-A at same time)
    .gpr .comma .gpr ;
  : rSB ( ppc-instruction -- ) rTB ; \ eg, 'fctiwz'
: fpTB ( ppc-instruction -- ) 
    0b rshift
    dup 0a rshift  
    .fpr .comma .fpr
;
: fpTx(rA)sD ( ppc-instruction -- ) \ eg 'lfd'
    dup 10 rshift dup 5 rshift
    .fpr .comma  SWAP  .sd  [CHAR] ( emit .gpr [CHAR] ) emit ;
: fpTx(r@)sD ( ppc-instruction -- )
    dup 10 rshift dup 5 rshift
    .fpr .comma SWAP .sd [CHAR] ( emit dup 1f and IF .gpr ELSE .nbr
        THEN  [CHAR] ) emit ; 
  : fpSx(rA)sD ( ppc-instruction -- ) fpTx(rA)sD ; \ eg, 'stfdu'
  : fpSx(r@)sD ( ppc-instruction -- ) fpTx(r@)sD   \ eg, 'lfd'
;

: fT ( ppc-instruction -- )     \ 'mcrxr' only
    017 rshift                
    .fld
;     
: fTS ( ppc-instruction -- ) 
    012 rshift dup 5 rshift
    .fld .comma .fld
;
: fT.rAB ( ppc-instruction -- )  \ eg, 'cmp'
    0b rshift
    dup 5 rshift dup 7 rshift 0 SWAP
    .fld .comma .nbr .comma .gpr .comma .gpr ;
: fTfpAB ( ppc-instruction -- ) \ eg, 'fcmpo'
    0b rshift
    dup 5 rshift dup 7 rshift
    .fld .comma .fpr .comma .fpr 
;
: fT.rAsI ( ppc-instruction -- )   \ 'cmpi' only
   dup 010 rshift dup 7 rshift 0 SWAP
   .fld .comma .nbr .comma .gpr .comma .si ;
: fT.rAuI ( ppc-instruction -- )   \ 'cmpli' only
   dup 010 rshift dup 7 rshift 0 SWAP
   .fld .comma .nbr .comma .gpr .comma .ui
;
: fThB ( ppc-instruction -- )  \ eg 'mtfsfi.' 
   0c rshift dup 0b rshift  .fld .comma .imm ;
: rTgR ( ppc-instruction -- ) \ 'mfsr' only
   010 rshift dup 5 rshift  .gpr .comma .segr 
;

: rTx(A)sD ( ppc-instruction -- )  \ eg, 'lwzu'
   dup 010 rshift dup 5 rshift 
   .gpr .comma  SWAP .si [CHAR] ( emit .gpr [CHAR] ) emit ;
  : rSx(A)sD ( ppc-instruction -- ) rTx(A)sD ; \ eg 'stbu'
 : rTx(@)sD ( ppc-instruction -- ) 
   dup 010 rshift dup 5 rshift .gpr .comma SWAP .si 
     [CHAR] ( emit dup 1f AND IF .gpr ELSE .nbr THEN [CHAR] ) emit ;
   : rSx(@)sD ( ppc-instruction -- ) rTx(@)sD
;
: rTAsI ( ppc-instruction -- )  \ eg, 'subfic'
  dup 010 rshift dup 5 rshift
  .gpr .comma .gpr .comma .si ;
: rT@sI ( ppc-instruction -- )  \ @ = A|0 as in (eg) 'addis'
   dup 010 rshift dup 5 rshift
   .gpr .comma 
   dup 01f and IF .gpr ELSE .nbr THEN  \ rA == 0 -> '0' not 'r0'
   .comma .si ;
: rxSAuI ( ppc-instruction -- ) \ eg, 'ori'
   dup 010 rshift dup 5 rshift SWAP
   .gpr .comma .gpr .comma .ui ;
: mMfpB ( ppc-instruction -- )  \ eg, 'mtfsf'
    0b rshift dup 6 rshift \ trim to reg B, push; ditto 8-bit mask
    .xx .comma .fpr
; 
: xrSmM ( ppc-instruction -- )  \ 'mtcrf' only )
    0c rshift dup 9 rshift SWAP \ ignore hi 0 to left of 8-bit field
    .xx .comma .gpr ;
: xrSgS ( ppc-instruction -- )      \ 'mtsr' only ) 
    010 rshift dup 5 rshift 
    .gpr .comma .segr ;

\ swap halves of spr/tbr spec field lo-hi to hi-lo order for display
: swap-ends ( ppc-instruction -- spr-specification )
    001ff800 AND     \ trim extraneous data from spr spec
    lwsplit          \ separate hi and lo halves
    swap             \ reverse their order
    6 rshift         \ reposition hi half to 5 of 10 most sig. bits
    +                \ recombine
;
: rTxLH ( ppc-instruction -- )   \ 'mfspr' and 'mftb'
dup swap-ends
swap
015 rshift .gpr .comma .spr ;
: xrSxLH ( ppc-instruction -- )   \ 'mtspr' only
dup swap-ends
..spr .comma 015 rshift .gpr 
;
\ ----------( end of extract-and-display-operand functions )-------


\ s, works like , (comma) but appends string not nbr to dictionary
: s, ( fm-addr len -- ) ( " string" in source leaves args on stack )
here swap move
2 cells allot
;

: records cells 5 * ;

0 value record->             
0 value table
0 value last-record
here to table  \ addr to start appending instr'n array to dictionary

\ The 'operands' fields below have names which are a form of 
\ shorthand describing their composition. These same tags are  
\ used to name and implement their extraction functions. Eg, 
\ the most common register combinations derive from 5-bit fields
\ in fixed positions immediately following the obligatory six-bit
\ 'Major Opcode' on the far left of every 32-bit ppc instruction.
\ These most common operand fields are designated herein as T, A,
\ B, C.  Any lower-case letters preceding those upper-case register
\ names apply as modifiers to all following register names until
\ another lower-case letter supercedes it. Thus fpTrABnC would 
\ represent one floating-point register (T), two general purpose 
\ registers (A and B) and a five-bit number (C).  The function
\ "fpTrABnC" developed to implement it would thus output (eg)
\ fr1,r31,r2,23 , depending  on the contents extracted from the
\ fields so nominated.
\ There are a few infrequently encountered exceptions however. Eg a
\ single 'x' augments but does not supercede the preceding 
\ lower-case modifier. It means that the two registers to its right
\ are displayed in the opposite order to their relative positions
\ within the 32-bit ppc instruction they were extracted from. 
\ (Such an 'x' transcribes directly to the forth word SWAP the way
\ it is implemented here). Note that these tags refer to their
\ relative position within 32-bit ppc instructions. The disassembler
\ syntax usually BUT NOT ALWAYS displays the operands in the same
\ left-to-right order they were extracted.
\
\ For more insights into the meanings of the uppercase designators,
\ refer to "Optimising PowerPC Code" by Gary Kacmarcik (Addison-
\ Wesley 1995). That book is the source of much of the ppc data
\ utilized for writing this disassembler. ('@' = short for 'rA|0')
\ Online documention, since discovered, substitutes 'rD' for 'rT'
\
\ The lower-case modifier-prefixes are:
\
\   r  = general purpose register
\   fp = floating point register
\   m  = mask
\   n  = a number extracted from the same fields as abv, no prefix
\   f  = a 3-bit field nbr, typically upper 3 of normal 5-bit field
\   g  = 4-bit number, eg seGment register id (displayed in decimal)
\   h  = 4-bit immediate data, eg bitmap of field (displayed in Hex)
\   c  = a code,eg, cC = a code of type 'condition'="condition code"
\   i  = immediate data (often the rhs half-word of the ppc instr'n)
\   s  = signed (to the ppc & optionally displayed as such by 'dis')
\   u  = unsigned (applies to immed. data copied direct fm instr'n)
\   d  = a displacement or fixed offset fm number in associated reg.
\   a  = absolute address (as near as you can get with the major
\        opcode occupying the six lhs bits of the instruction).
\   r  = relative to address of current instruction.
\   (  = operand to be separated from prev one by '(' instead of ','
\   )  = Ignore. It is just there to make the meaning of '(' clearer
\   x  = display the following two registers in reverse order
\   .  = Display a constant '0' at this point without affecting
\        anything else. (It can also be a '1' on 64-bit ppc's only)
\

table d# 289 records BL fill \ pre-pad count must be >= #records

\ opcode   final mask  mnemonic  operands  (commas do the poking)
\ --------------------------------------------
00000000 , 00000000 , " data" s, ' all , ( the only pseudo-op)
\ The foll. 288 records = G4 Instruction Set
7c000214 , fc0007ff , " add" s, ' rTAB  ,
7c000215 , fc0007ff , " add." s, ' rTAB  ,
7c000014 , fc0007ff , " addc" s, ' rTAB  ,
7c000015 , fc0007ff , " addc." s, ' rTAB  ,
7c000414 , fc0007ff , " addco" s, ' rTAB  ,
7c000415 , fc0007ff , " addco." s, ' rTAB  ,
7c00008a , fc0007ff , " adde" s, ' rTAB  ,
7c00008b , fc0007ff , " adde." s, ' rTAB  ,
7c00048a , fc0007ff , " addeo" s, ' rTAB  ,
7c00048b , fc0007ff , " addeo." s, ' rTAB  ,
38000000 , fc000000 , " addi" s, ' rT@sI  ,
30000000 , fc000000 , " addic" s, ' rTAsI  ,
34000000 , fc000000 , " addic." s, ' rTAsI  ,
3c000000 , fc000000 , " addis" s, ' rT@sI  ,
7c0001d4 , fc00ffff , " addme" s, ' rTA  ,
7c0001d5 , fc00ffff , " addme." s, ' rTA  ,
7c0005d4 , fc00ffff , " addmeo" s, ' rTA  ,
7c0005d5 , fc00ffff , " addmeo." s, ' rTA  ,
7c000614 , fc0007ff , " addo" s, ' rTAB  ,
7c000615 , fc0007ff , " addo." s, ' rTAB  ,
7c000194 , fc00ffff , " addze" s, ' rTA  ,
7c000195 , fc00ffff , " addze." s, ' rTA  ,
7c000594 , fc00ffff , " addzeo" s, ' rTA  ,
7c000595 , fc00ffff , " addzeo." s, ' rTA  ,
7c000038 , fc0007ff , " and" s, ' rxSAB  ,
7c000039 , fc0007ff , " and." s, ' rxSAB  ,
7c000078 , fc0007ff , " andc" s, ' rxSAB  ,
7c000079 , fc0007ff , " andc." s, ' rxSAB  ,
70000000 , fc000000 , " andi." s, ' rxSAuI  ,
74000000 , fc000000 , " andis." s, ' rxSAuI  ,
48000000 , fc000003 , " b" s, ' T*4r  ,
48000002 , fc000003 , " ba" s, ' T*4a  ,
40000000 , fc000003 , " bc" s, ' cCbNT*4r  ,
40000002 , fc000003 , " bca" s, ' cCbNT*4a  ,
4c000420 , fc00ffff , " bcctr" s, ' cCbN  ,
4c000421 , fc00ffff , " bcctrl" s, ' cCbN  ,
40000001 , fc000003 , " bcl" s, ' cCbNT*4r  ,
40000003 , fc000003 , " bcla" s, ' cCbNT*4a  ,
4c000020 , fc00ffff , " bclr" s, ' cCbN  ,
4c000021 , fc00ffff , " bclrl" s, ' cCbN  ,
48000001 , fc000003 , " bl" s, ' T*4r  ,
48000003 , fc000003 , " bla" s, ' T*4a  ,
7c000000 , fc6007ff , " cmp" s, ' fT.rAB  ,
2c000000 , fc600000 , " cmpi" s, ' fT.rAsI  ,
7c000040 , fc6007ff , " cmpl" s, ' fT.rAB  ,
28000000 , fc600000 , " cmpli" s, ' fT.rAuI  ,
7c000034 , fc00ffff , " cntlzw" s, ' rxSA  ,
7c000035 , fc00ffff , " cntlzw." s, ' rxSA  ,
4c000202 , fc0007ff , " crand" s, ' nTAB  ,
4c000102 , fc0007ff , " crandc" s, ' nTAB  ,
4c000242 , fc0007ff , " creqv" s, ' nTAB  ,
4c0001c2 , fc0007ff , " crnand" s, ' nTAB  ,
4c000042 , fc0007ff , " crnor" s, ' nTAB  ,
4c000382 , fc0007ff , " cror" s, ' nTAB  ,
4c000342 , fc0007ff , " crorc" s, ' nTAB  ,
4c000182 , fc0007ff , " crxor" s, ' nTAB  ,
7c0002f6 , ffe007ff , " dcba" s, ' r@B  ,
7c0000ac , ffe007ff , " dcbf" s, ' r@B  ,
7c0003ac , ffe007ff , " dcbi" s, ' r@B  ,
7c00006c , ffe007ff , " dcbst" s, ' r@B  ,
7c00022c , ffe007ff , " dcbt" s, ' r@B  ,
7c0001ec , ffe007ff , " dcbtst" s, ' r@B  ,
7c0007ec , ffe007ff , " dcbz" s, ' r@B  ,
7c0003d6 , fc0007ff , " divw" s, ' rTAB  ,
7c0003d7 , fc0007ff , " divw." s, ' rTAB  ,
7c0007d6 , fc0007ff , " divwo" s, ' rTAB  ,
7c0007d7 , fc0007ff , " divwo." s, ' rTAB  ,
7c000396 , fc0007ff , " divwu" s, ' rTAB  ,
7c000397 , fc0007ff , " divwu." s, ' rTAB  ,
7c000796 , fc0007ff , " divwuo" s, ' rTAB  ,
7c000797 , fc0007ff , " divwuo." s, ' rTAB  ,
7c00026c , fc0007ff , " eciwx" s, ' rT@B  ,
7c00036c , fc0007ff , " ecowx" s, ' rS@B  ,
7c0006ac , ffffffff , " eieio" s, ' nil  ,
7c000238 , fc0007ff , " eqv" s, ' rxSAB  ,
7c000239 , fc0007ff , " eqv." s, ' rxSAB  ,
7c000774 , fc00ffff , " extsb" s, ' rxSA  ,
7c000775 , fc00ffff , " extsb." s, ' rxSA  ,
7c000734 , fc00ffff , " extsh" s, ' rxSA  ,
7c000735 , fc00ffff , " extsh." s, ' rxSA  ,
fc000210 , fc1f07ff , " fabs" s, ' fpTB  ,
fc000211 , fc1f07ff , " fabs." s, ' fpTB  ,
fc00002a , fc00003f , " fadd" s, ' fpTAB  ,
fc00002b , fc00003f , " fadd." s, ' fpTAB  ,
ec00002a , fc00003f , " fadds" s, ' fpTAB  ,
ec00002b , fc00003f , " fadds." s, ' fpTAB  ,
fc000040 , fc6007ff , " fcmpo" s, ' fTfpAB  ,
fc000000 , fc6007ff , " fcmpu" s, ' fTfpAB  ,
fc00001c , fc1f07ff , " fctiw" s, ' fpTB  ,
fc00001d , fc1f07ff , " fctiw." s, ' fpTB  ,
fc00001e , fc1f07ff , " fctiwz" s, ' fpTB  ,
fc00001f , fc1f07ff , " fctiwz." s, ' fpTB  ,
fc000024 , fc00003f , " fdiv" s, ' fpTAB  ,
fc000025 , fc00003f , " fdiv." s, ' fpTAB  ,
ec000024 , fc0007ff , " fdivs" s, ' fpTAB  ,
ec000025 , fc0007ff , " fdivs." s, ' fpTAB  ,
fc00003a , fc00003f , " fmadd" s, ' fpTAxBC  ,
fc00003b , fc00003f , " fmadd." s, ' fpTAxBC  ,
ec00003a , fc00003f , " fmadds" s, ' fpTAxBC  ,
ec00003b , fc00003f , " fmadds." s, ' fpTAxBC  ,
fc000090 , fc1f07ff , " fmr" s, ' fpTB  ,
fc000091 , fc1f07ff , " fmr." s, ' fpTB  ,
fc000038 , fc00003f , " fmsub" s, ' fpTAxBC  ,
fc000039 , fc00003f , " fmsub." s, ' fpTAxBC  ,
ec000038 , fc00003f , " fmsubs" s, ' fpTAxBC  ,
ec000039 , fc00003f , " fmsubs." s, ' fpTAxBC  ,
fc000032 , fc00f83f , " fmul" s, ' fpTAC  ,
fc000033 , fc00003f , " fmul." s, ' fpTAC  ,
ec000032 , fc00f83f , " fmuls" s, ' fpTAC  ,
ec000033 , fc00f83f , " fmuls." s, ' fpTAC  ,
fc000110 , fc1f07ff , " fnabs" s, ' fpTB  ,
fc000111 , fc1f07ff , " fnabs." s, ' fpTB  ,
fc000050 , fc1f07ff , " fneg" s, ' fpTB  ,
fc000051 , fc1f07ff , " fneg." s, ' fpTB  ,
fc00003e , fc00003f , " fnmadd" s, ' fpTAxBC  ,
fc00003f , fc00003f , " fnmadd." s, ' fpTAxBC  ,
ec00003e , fc00003f , " fnmadds" s, ' fpTAxBC  ,
ec00003f , fc00003f , " fnmadds." s, ' fpTAxBC  ,
fc00003c , fc00003f , " fnmsub" s, ' fpTAxBC  ,
fc00003d , fc00003f , " fnmsub." s, ' fpTAxBC  ,
ec00003c , fc00003f , " fnmsubs" s, ' fpTAxBC  ,
ec00003d , fc00003f , " fnmsubs." s, ' fpTAxBC  ,
ec000030 , fc1f07ff , " fres" s, ' fpTB  ,
ec000031 , fc1f07ff , " fres." s, ' fpTB  ,
fc000018 , fc1f07ff , " frsp" s, ' fpTB  ,
fc000019 , fc1f07ff , " frsp." s, ' fpTB  ,
fc000034 , fc1f003f , " frsqrte" s, ' fpTB  ,
fc000035 , fc1f003f , " frsqrte." s, ' fpTB  ,
fc00002e , fc00003f , " fsel" s, ' fpTAxBC  ,
fc00002f , fc00003f , " fsel." s, ' fpTAxBC  ,
fc000028 , fc00003f , " fsub" s, ' fpTAB  ,
fc000029 , fc00003f , " fsub." s, ' fpTAB  ,
ec000028 , fc00003f , " fsubs" s, ' fpTAB  ,
ec000029 , fc00003f , " fsubs." s, ' fpTAB  ,
7c0007ac , ffe007ff , " icbi" s, ' r@B  ,
4c00012c , ffffffff , " isync" s, ' nil  ,
88000000 , fc000000 , " lbz" s, ' rTx(@)sD  ,
8c000000 , fc000000 , " lbzu" s, ' rTx(A)sD  ,
7c0000ee , fc0007ff , " lbzux" s, ' rTAB  ,
7c0000ae , fc0007ff , " lbzx" s, ' rT@B  ,
c8000000 , fc000000 , " lfd" s, ' fpTx(r@)sD  ,
cc000000 , fc000000 , " lfdu" s, ' fpTx(rA)sD  ,
7c0004ee , fc0007ff , " lfdux" s, ' fpTrAB  ,
7c0004ae , fc0007ff , " lfdx" s, ' fpTr@B  ,
c0000000 , fc000000 , " lfs" s, ' fpTx(r@)sD  ,
c4000000 , fc000000 , " lfsu" s, ' fpTx(rA)sD  ,
7c00046e , fc0007ff , " lfsux" s, ' fpTrAB  ,
7c00042e , fc0007ff , " lfsx" s, ' fpTr@B  ,
a8000000 , fc000000 , " lha" s, ' rTx(A)sD  ,
ac000000 , fc000000 , " lhau" s, ' rTx(@)sD  ,
7c0002ee , fc0007ff , " lhaux" s, ' rTAB  ,
7c0002ae , fc0007ff , " lhax" s, ' rT@B  ,
7c00062c , fc0007ff , " lhbrx" s, ' rT@B  ,
a0000000 , fc000000 , " lhz" s, ' rTx(@)sD  ,
a4000000 , fc000000 , " lhzu" s, ' rTx(A)sD  ,
7c00026e , fc0007ff , " lhzux" s, ' rTAB  ,
7c00022e , fc0007ff , " lhzx" s, ' rT@B  ,
b8000000 , fc000000 , " lmw" s, ' rTx(@)sD  ,
7c0004aa , fc0007ff , " lswi" s, ' rT@nB  ,
7c00042a , fc0007ff , " lswx" s, ' rT@B  ,
7c000028 , fc0007ff , " lwarx" s, ' rT@B  ,
7c00042c , fc0007ff , " lwbrx" s, ' rT@B  ,
80000000 , fc000000 , " lwz" s, ' rTx(@)sD  ,
84000000 , fc000000 , " lwzu" s, ' rTx(A)sD  ,
7c00006e , fc0007ff , " lwzux" s, ' rTAB  ,
7c00002e , fc0007ff , " lwzx" s, ' rT@B  ,
4c000000 , fc63ffff , " mcrf" s, ' fTS  ,
fc000080 , fc63ffff , " mcrfs" s, ' fTS  ,
7c000400 , fc7fffff , " mcrxr" s, ' fT  ,
7c000026 , fc1fffff , " mfcr" s, ' rT  ,
fc00048e , fc1fffff , " mffs" s, ' fpT  ,
fc00048f , fc1fffff , " mffs." s, ' fpT  ,
7c0000a6 , fc1fffff , " mfmsr" s, ' rT  ,
7c0002a6 , fc0007ff , " mfspr" s, ' rTxLH  ,
7c0004a6 , fc10ffff , " mfsr" s, ' rTgR  ,
7c000526 , fc1f07ff , " mfsrin" s, ' rTB  ,
7c0c42e6 , fc1fffff , " mftb" s, ' rT  , \ Alt Form 'mftb rT,268'
7c0d42e6 , fc1fffff , " mftbu" s, ' rT , \ Alt Form 'mftb rT,269'
\ Basic Form 'mftb' removed as 268 & 269 are its only valid operands
7c000120 , fc100fff , " mtcrf" s, ' xrSmM  ,
fc00008c , fc1fffff , " mtfsb0" s, ' nT  ,
fc00008d , fc1fffff , " mtfsb0." s, ' nT  ,
fc00004c , fc1fffff , " mtfsb1" s, ' nT  ,
fc00004d , fc1fffff , " mtfsb1." s, ' nT  ,
fc00058e , fe0107ff , " mtfsf" s, ' mMfpB  ,
fc00058f , fe0107ff , " mtfsf." s, ' mMfpB  ,
fc00010c , fc7f0fff , " mtfsfi" s, ' fThB  ,
fc00010d , fc7f0fff , " mtfsfi." s, ' fThB  ,
7c000124 , fc1fffff , " mtmsr" s, ' rS  ,
7c0003a6 , fc0007ff , " mtspr" s, ' xrSxLH  ,
7c0001a4 , fc0007ff , " mtsr" s, ' xrSgS  ,
7c0001e4 , fc1f07ff , " mtsrin" s, ' rSB  ,
7c000092 , fc0007ff , " mulhw" s, ' rTAB  ,
7c000093 , fc0007ff , " mulhw." s, ' rTAB  ,
7c000016 , fc0007ff , " mulhwu" s, ' rTAB  ,
7c000017 , fc0007ff , " mulhwu." s, ' rTAB  ,
1c000000 , fc000000 , " mulli" s, ' rTAsI  ,
7c0001d6 , fc0007ff , " mullw" s, ' rTAB  ,
7c0001d7 , fc0007ff , " mullw." s, ' rTAB  ,
7c0005d6 , fc0007ff , " mullwo" s, ' rTAB  ,
7c0005d7 , fc0007ff , " mullwo." s, ' rTAB  ,
7c0003b8 , fc0007ff , " nand" s, ' rxSAB  ,
7c0003b9 , fc0007ff , " nand." s, ' rxSAB  ,
7c0000d0 , fc00ffff , " neg" s, ' rTA  ,
7c0000d1 , fc00ffff , " neg." s, ' rTA  ,
7c0004d0 , fc00ffff , " nego" s, ' rTA  ,
7c0004d1 , fc00ffff , " nego." s, ' rTA  ,
7c0000f8 , fc0007ff , " nor" s, ' rxSAB  ,
7c0000f9 , fc0007ff , " nor." s, ' rxSAB  ,
7c000378 , fc0007ff , " or" s, ' rxSAB  ,
7c000379 , fc0007ff , " or." s, ' rxSAB  ,
7c000338 , fc0007ff , " orc" s, ' rxSAB  ,
7c000339 , fc0007ff , " orc." s, ' rxSAB  ,
60000000 , fc000000 , " ori" s, ' rxSAuI  ,
64000000 , fc000000 , " oris" s, ' rxSAuI  ,
4c000064 , ffffffff , " rfi" s, ' nil  ,
50000000 , fc000001 , " rlwimi" s, ' rxSAnBCD  ,
50000001 , fc000001 , " rlwimi." s, ' rxSAnBCD  ,
54000000 , fc000001 , " rlwinm" s, ' rxSAnBCD  ,
54000001 , fc000001 , " rlwinm." s, ' rxSAnBCD  ,
5c000000 , fc000001 , " rlwnm" s, ' rxSABnCD  ,
5c000001 , fc000001 , " rlwnm." s, ' rxSABnCD  ,
44000002 , fc000003 , " sc" s, ' nil  ,
7c000030 , fc0007ff , " slw" s, ' rxSAB  ,
7c000031 , fc0007ff , " slw." s, ' rxSAB  ,
7c000630 , fc0007ff , " sraw" s, ' rxSAB  ,
7c000631 , fc0007ff , " sraw." s, ' rxSAB  ,
7c000670 , fc0007ff , " srawi" s, ' rxSAnB  ,
7c000671 , fc0007ff , " srawi." s, ' rxSAnB  ,
7c000430 , fc0007ff , " srw" s, ' rxSAB  ,
7c000431 , fc0007ff , " srw." s, ' rxSAB  ,
98000000 , fc000000 , " stb" s, ' rSx(@)sD  ,
9c000000 , fc000000 , " stbu" s, ' rSx(A)sD  ,
7c0001ee , fc0007ff , " stbux" s, ' rSAB  ,
7c0001ae , fc0007ff , " stbx" s, ' rS@B  ,
d8000000 , fc000000 , " stfd" s, ' fpSx(r@)sD  ,
dc000000 , fc000000 , " stfdu" s, ' fpSx(rA)sD  ,
7c0005ee , fc0007ff , " stfdux" s, ' fpSrAB  ,
7c0005ae , fc0007ff , " stfdx" s, ' fpSr@B  ,
7c0007ae , fc0007ff , " stfiwx" s, ' fpSr@B  ,
d0000000 , fc000000 , " stfs" s, ' fpSx(r@)sD  ,
d4000000 , fc000000 , " stfsu" s, ' fpSx(rA)sD  ,
7c00056e , fc0007ff , " stfsux" s, ' fpSrAB  ,
7c00052e , fc0007ff , " stfsx" s, ' fpSr@B  ,
b0000000 , fc000000 , " sth" s, ' rSx(@)sD  ,
7c00072c , fc0007ff , " sthbrx" s, ' rS@B  ,
b4000000 , fc000000 , " sthu" s, ' rSx(A)sD  ,
7c00036e , fc0007ff , " sthux" s, ' rSAB  ,
7c00032e , fc0007ff , " sthx" s, ' rS@B  ,
bc000000 , fc000000 , " stmw" s, ' rSx(@)sD  ,
7c0005aa , fc0007ff , " stswi" s, ' rS@nB  ,
7c00052a , fc0007ff , " stswx" s, ' rS@B  ,
90000000 , fc000000 , " stw" s, ' rSx(@)sD  ,
7c00052c , fc0007ff , " stwbrx" s, ' rS@B  ,
7c00012d , fc0007ff , " stwcx." s, ' rS@B  ,
94000000 , fc000000 , " stwu" s, ' rSx(A)sD  ,
7c00016e , fc0007ff , " stwux" s, ' rSAB  ,
7c00012e , fc0007ff , " stwx" s, ' rS@B  ,
7c000050 , fc0007ff , " subf" s, ' rTAB  ,
7c000051 , fc0007ff , " subf." s, ' rTAB  ,
7c000010 , fc0007ff , " subfc" s, ' rTAB  ,
7c000011 , fc0007ff , " subfc." s, ' rTAB  ,
7c000410 , fc0007ff , " subfco" s, ' rTAB  ,
7c000411 , fc0007ff , " subfco." s, ' rTAB  ,
7c000110 , fc0007ff , " subfe" s, ' rTAB  ,
7c000111 , fc0007ff , " subfe." s, ' rTAB  ,
7c000510 , fc0007ff , " subfeo" s, ' rTAB  ,
7c000511 , fc0007ff , " subfeo." s, ' rTAB  ,
20000000 , fc000000 , " subfic" s, ' rTAsI  ,
7c0001d0 , fc00ffff , " subfme" s, ' rTA  ,
7c0001d1 , fc00ffff , " subfme." s, ' rTA  ,
7c0005d0 , fc00ffff , " subfmeo" s, ' rTA  ,
7c0005d1 , fc00ffff , " subfmeo." s, ' rTA  ,
7c000450 , fc0007ff , " subfo" s, ' rTAB  ,
7c000451 , fc0007ff , " subfo." s, ' rTAB  ,
7c000190 , fc00ffff , " subfze" s, ' rTA  ,
7c000191 , fc00ffff , " subfze." s, ' rTA  ,
7c000591 , fc00ffff , " subfzeo" s, ' rTA  ,
7c000590 , fc00ffff , " subfzeo." s, ' rTA  ,
7c0004ac , ffffffff , " sync" s, ' nil  ,
7c000264 , ffff07ff , " tlbie" s, ' rB  ,
7c00046c , ffffffff , " tlbsync" s, ' nil  ,
7c000008 , fc0007ff , " tw" s, ' cCrAB  ,
0c000000 , fc000000 , " twi" s, ' cCrAsI  ,
7c000278 , fc0007ff , " xor" s, ' rxSAB  ,
7c000279 , fc0007ff , " xor." s, ' rxSAB  ,
68000000 , fc000000 , " xori" s, ' rxSAuI  ,
6c000000 , fc000000 , " xoris" s, ' rxSAuI  ,
\ ====================================
here 1 records - to last-record

here to addr \ garbage better than +dis : Illegal memory access

0 value opcode 

: find-record
    table last-record DO               \ search for opcode in table
       I @ opcode = IF  I leave  THEN  \ found: put index on stack
       I table = IF I leave THEN \ not found: make 'data' the instrn
    -1 records +LOOP
;

: disasm1 ( address --) ( on exit, opcode=FALSE for invalid instr'n)
     hex 
     align-address  \ force, so that branch operands always accurate
     dup to addr
     .hexdump 3a emit BL emit   ( print instruction address )
     addr @ .hexdump 2 spaces \ optional line:add raw code to output
     addr dup @ swap roughmask AND to opcode ( save candidate opc )
     find-record to record-> 
     record-> cell+ @      ( instr'n-nominated mask combined with )
     addr @ AND dup        (      instruction gives precise opcode)
     opcode <> IF       ( does it match initially calc'd opcode ? )
        table to record-> THEN   ( invalid instr'n becomes "data" )
     ( dup'd) to opcode    ( also doubles as return code )
     record-> 2 cells +    ( advance record pointer to mnemonic )
     8 type BL emit        ( output mnemonic )
     addr @
     record-> 4 cells + @  ( ppc instr'n rec. nominates routine to )
     execute               ( extract, format and print its operands)
     cr
     addr cell+ to addr    ( postincrement preps for next instr'n )
;


: dis ( address -- )      \ replaces built-in original 
    cr -1 swap 
      do i disasm1 
      exit? \ displays pagination prompt; use ret-key to single-step
      if leave then
    cell +loop
;

: +dis ( -- ) addr dis ;  \ replaces built-in original


: +dasm ( -- )    \ '+dis' variant stops at end of code bloc
    cr
    begin
      addr disasm1
      \ stop on any foll. unconditional return or non ret-saved jump
      opcode 48000000 ( b ) =
      opcode 48000002 ( ba ) = OR
      opcode 4c000064 ( rfi ) = OR
      addr cell - @ ffe0ffff AND 4e800020 ( blr, any crf ) = OR
      addr cell - @ ffe0ffff AND 4e800420 ( bctr, any crf) = OR
      addr cell - @ ffe00001 AND 42800000 ( bc unconditional ) = OR
      exit? OR 
    until
;

: dasm ( address -- ) \ dis halted by 'b' 'ba' 'rfi' 'blr' or 'bctr'
    to addr +dasm
;

cr
.." Public Domain replacement 'dis' for G4 Macintosh Open Firmware."
cr
.." Written and revised by Neville Duguid (Tinkerer), Apr-Jun 2008."
cr
.." dis, +dis, dasm, +dasm await your command. Usage: <address> dis"
cr


\ ---- Bonus Evaluation Kit. Delete when you've had your fun -----

\ Cheap and nasty one-note assembler to test 'lswi' "Load String
\ Word Immediate" - the instruction most likely to drive you nuts
\ trying to verify.(Actually 'lswx' is worse, but can't be tested
\ automatically by disassembler since its nB is runtime variable)

( It has been left here to show how easy it is to improvise a one- )
( line assembler using Forth and the resources in this source file )

\ Sample usage (incompatible operands downgrade "lswi" to "data"):
\ The args have to fit in 5-bit fields. Limit values to d# 0-31
\ 2 3 4 lswi         --> lswi   r2,r3,4   ( all 4 bytes fit in r2 )
\ 2 3 5 lswi         --> data   7c432caa  (5th byte zaps src reg r3)
\ d# 31 6 d# 31 lswi --> data   7fe6fcaa  (range wraps around to r6)
\ d# 31 7 d# 31 lswi --> lswi   r31,r7,31 (31 bytes fit in r31,r0-6)
\ d# 31 6 0 lswi     --> data   7fe604aa  (0 byte-count taken as 32)
\ ... and they call it RISC ! The fun is just beginning ...
\
: lswi ( rT rA nB -- ) \ assembles 'lswi' instructions only
  01f and   0b  <<  -rot
  01f and   010 <<  swap
  01f and   015 << 
  7c0004aa OR  OR  OR  \ 'lswi' instruction literally assembled
  align here !         ( '!' is Forth for 32-bit poke )
  cr
  here disasm1         ( 'here' points to start of free memory )
  opcode IF            \ FALSE (0) only if disasm1 output "data"
     cell allot        \ success, advance 'here' to next memory cell
  THEN                 \ else next attempt will overwrite this one
;
0
Reply tinkerer (31) 7/2/2008 12:41:25 AM


0 Replies
246 Views

(page loaded in 0.144 seconds)

Similiar Articles:








7/12/2012 4:26:11 PM


Reply: