f



Replacement dis command for G4 Macintosh Open Firmware

\ "dis.of" 17-Apr-2008
\ 
\ Tested only on development platform: 2003 G4 eMac w/ Open Firmware
\ v4.6.4.fi and 500 Mb RAM. Should also be useful with 603, 604, G3.
\ Feedback welcome on any corrections needed to make it work or
\ perform bettter on your own PowerPC Macintosh's Open Firmware.
\
\ 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 very 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.
\ The file should then not only compile, but also be fully restored
\ to its original state as a transmittable ASCII text file ****
\
\ 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 from a non aligned address.

hex           \ just in case

0 value ADDR  \ make addr of ppc inst'n being disassembled global

\ Rough mask sufficient to uniquely identify candidate G4 instr'n
: 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 reverts to stack in use prior to CASE
   010 OF  fc000003 >r  ENDOF  \ 'bc' group (4 instructions)
   011 OF  fc000003 >r  ENDOF  \ 'sc'       (1 instruction)
   012 OF  fc000003 >r  ENDOF  \ 'b' (branch unconditional) (4)
   013 OF  fc0007ff >r  ENDOF  \  CR etc group (15 instructions)
   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  
\ ----------------------- Part One of mftb Patch -------------------
\ Sample patch: how Alternative Forms of instr'n may be implemented
( untidy code makes data placement independent of search direction )
     \ the next 2 IFs move cryptic TBR spec fm operand to mnemonic
       addr @ ( instr'n) fc1fffff ( mask ) AND 7c0c42e6 ( opcode ) =
         IF  fc1fffff >r  ELSE  \ mftb r0,268 becomes 'mftb  r0'
       addr @ ( instr'n) fc1fffff ( mask ) AND 7c0d42e6 ( opcode ) =
         IF  fc1fffff >r  ELSE \ mftb r0,269 becomes 'mftbu r0'
\ -------------- (Part 2 of patch is in data table below) ----------
            fc0007ff >r     \ Load, Store, Arithmetic, Logic (151+2)
              THEN    THEN \ (--- this line belongs to Patch ---)
       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
   fc000000 >r    \ Default: Major opcode alone identifies remainder
         \ majority of load, store, plus some int arith & logic (39)
ENDCASE               ( TOTAL PPC INSTRN'S = 285 + 2 aliases = 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.
\
: .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 ... n
: .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 -- )  ( no trimming actually required)
     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-target ( branch-addr -- aligned-branch-addr )
-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 base)
    swap
    03fffffc AND dup   ( + 2 alignment bits -> 26 bits )
    02000000 AND       ( most 32-bit G4 addr start with 00 or ff )
    if fc000000  OR  then  \ if hi bit = 1, keep address hi
    +                  \ add the base address    
;

\ 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
\ instruction tells disasm1 how to display its 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        \ use zero base-addr with absolute source field
    .hexdump ;
: T*4r ( ppc-instruction -- ) \ 'b','bl' ( r=relative src fld )
    addr btarget ( base-addr = instrn-addr converts rel to absolute)
   .hexdump
;
: cCbNT*4a ( ppc-instruction -- )  \ eg 'bcla'
    align-target 
    dup 010 rshift dup 5 rshift
    .xx .comma .nbr .comma sign-extend 
   .hexdump  ;
: cCbNT*4r ( ppc-instruction -- )  \ eg 'bc'
    align-target
    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
;

: rAB  ( ppc-instruction -- )  \ eg, 'dcbf'
    0b rshift         \ discard all to right of right-most operand
    dup 5 rshift      \ push, then do similar for next operand
    .gpr .comma .gpr  \ pop and print opnd fields in orig. order
;
: 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 rT ( ppc-instruction -- ) ;
: 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 first 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'
: 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 register 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'
: nTAB ( ppc-instruction -- )   \ eg 'crxor'
    0b rshift
    dup 5 rshift dup 5 rshift
    .nbr .comma .nbr .comma .nbr ;
: rTAnB ( ppc-instruction -- ) 
    0b rshift
    dup 5 rshift dup 5 rshift
    .gpr .comma .gpr .comma .nbr ;
  : rSAnB ( ppc-instruction -- ) rTAnB ; \ 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 ; 
  : fpSx(rA)sD ( ppc-instruction -- ) fpTx(rA)sD \ eg, 'stfdu'
;

: 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'
;
: rTAsI ( ppc-instruction -- )  \ eg, 'subfic'
  dup 010 rshift dup 5 rshift
  .gpr .comma .gpr .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 
;

\ Works like , (comma) but appends string not number to dictionary 
: s, ( fm-addr len -- ) \ NB: " string" in source puts 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 \ address to start building ppc-instr'n array on stack

\ The 'operands' fields below have names which are a form of 
\ shorthand describing their composition. These tags are also 
\ 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
\ tags 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,0x7e ,depending  on the contents extracted from the
\ nominated fields within the fields so nominated.
\ There are a few infrequently encountered exceptions however. Eg a 
\ lower-case exception is a single 'x' which augments but does not
\ supercede the following lower-case modifiers. 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
\ are 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 located
\ within the machine code instruction being disassembled.
\
\ 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 when writing this disassembler. 
\
\ 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, prefixed to affected reg.
\   a  = absolute address (as near as you can get with the major
\        opcode occupying the six lhs bits of the 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 only be '1' on 64-bit ppc's)
\
table d# 288 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. 287 records (-2 aliases in mftb patch) = G4 instr 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, ' rTAsI  ,
30000000 , fc000000 , " addic" s, ' rTAsI  ,
34000000 , fc000000 , " addic." s, ' rTAsI  ,
3c000000 , fc000000 , " addis" s, ' rTAsI  ,
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  ,
7c0000ac , ffe007ff , " dcbf" s, ' rAB  ,
7c0003ac , ffe007ff , " dcbi" s, ' rAB  ,
7c00006c , ffe007ff , " dcbst" s, ' rAB  ,
7c00022c , ffe007ff , " dcbt" s, ' rAB  ,
7c0001ec , ffe007ff , " dcbtst" s, ' rAB  ,
7c0007ec , ffe007ff , " dcbz" s, ' rAB  ,
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, ' rTAB  ,
7c00036c , fc0007ff , " ecowx" s, ' rSAB  ,
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, ' rAB  ,
4c00012c , ffffffff , " isync" s, ' nil  ,
88000000 , fc000000 , " lbz" s, ' rTx(A)sD  ,
8c000000 , fc000000 , " lbzu" s, ' rTx(A)sD  ,
7c0000ee , fc0007ff , " lbzux" s, ' rTAB  ,
7c0000ae , fc0007ff , " lbzx" s, ' rTAB  ,
c8000000 , fc000000 , " lfd" s, ' fpTx(rA)sD  ,
cc000000 , fc000000 , " lfdu" s, ' fpTx(rA)sD  ,
7c0004ee , fc0007ff , " lfdux" s, ' fpTrAB  ,
7c0004ae , fc0007ff , " lfdx" s, ' fpTrAB  ,
c0000000 , fc000000 , " lfs" s, ' fpTx(rA)sD  ,
c4000000 , fc000000 , " lfsu" s, ' fpTx(rA)sD  ,
7c00046e , fc0007ff , " lfsux" s, ' fpTrAB  ,
7c00042e , fc0007ff , " lfsx" s, ' fpTrAB  ,
a8000000 , fc000000 , " lha" s, ' rTx(A)sD  ,
ac000000 , fc000000 , " lhau" s, ' rTx(A)sD  ,
7c0002ee , fc0007ff , " lhaux" s, ' rTAB  ,
7c0002ae , fc0007ff , " lhax" s, ' rTAB  ,
7c00062c , fc0007ff , " lhbrx" s, ' rTAB  ,
a0000000 , fc000000 , " lhz" s, ' rTx(A)sD  ,
a4000000 , fc000000 , " lhzu" s, ' rTx(A)sD  ,
7c00026e , fc0007ff , " lhzux" s, ' rTAB  ,
7c00022e , fc0007ff , " lhzx" s, ' rTAB  ,
b8000000 , fc000000 , " lmw" s, ' rTx(A)sD  ,
7c0004aa , fc0007ff , " lswi" s, ' rTAnB  ,
7c00042a , fc0007ff , " lswx" s, ' rTAB  ,
7c000028 , fc0007ff , " lwarx" s, ' rTAB  ,
7c00042c , fc0007ff , " lwbrx" s, ' rTAB  ,
80000000 , fc000000 , " lwz" s, ' rTx(A)sD  ,
84000000 , fc000000 , " lwzu" s, ' rTx(A)sD  ,
7c00006e , fc0007ff , " lwzux" s, ' rTAB  ,
7c00002e , fc0007ff , " lwzx" s, ' rTAB  ,
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  ,
\ comment out next line to reject non-documented MFR operands
7c0002e6 , fc0007ff , " mftb" s, ' rTxLH  ,
\ ------------------------------------------------------------------
\ Part 2 of mftb Patch.Next 2 records are Extended Form alternatives
7c0c42e6 , fc1fffff , " mftb" s, ' rT  , \ alias of mftb rX,268
7c0d42e6 , fc1fffff , " mftbu" s, ' rT , \ alias of mftb rX,269
( Const. data is duplicated in Part 1 of patch in 'roughmask' abv. )
\ ------------------------ (mftb Patch ends) -----------------------
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(A)sD  ,
9c000000 , fc000000 , " stbu" s, ' rSx(A)sD  ,
7c0001ee , fc0007ff , " stbux" s, ' rSAB  ,
7c0001ae , fc0007ff , " stbx" s, ' rSAB  ,
d8000000 , fc000000 , " stfd" s, ' fpSx(rA)sD  ,
dc000000 , fc000000 , " stfdu" s, ' fpSx(rA)sD  ,
7c0005ee , fc0007ff , " stfdux" s, ' fpSrAB  ,
7c0005ae , fc0007ff , " stfdx" s, ' fpSrAB  ,
7c0007ae , fc0007ff , " stfiwx" s, ' fpSrAB  ,
d0000000 , fc000000 , " stfs" s, ' fpSx(rA)sD  ,
d4000000 , fc000000 , " stfsu" s, ' fpSx(rA)sD  ,
7c00056e , fc0007ff , " stfsux" s, ' fpSrAB  ,
7c00052e , fc0007ff , " stfsx" s, ' fpSrAB  ,
b0000000 , fc000000 , " sth" s, ' rSx(A)sD  ,
7c00072c , fc0007ff , " sthbrx" s, ' rSAB  ,
b4000000 , fc000000 , " sthu" s, ' rSx(A)sD  ,
7c00036e , fc0007ff , " sthux" s, ' rSAB  ,
7c00032e , fc0007ff , " sthx" s, ' rSAB  ,
bc000000 , fc000000 , " stmw" s, ' rSx(A)sD  ,
7c0005aa , fc0007ff , " stswi" s, ' rSAnB  ,
7c00052a , fc0007ff , " stswx" s, ' rSAB  ,
90000000 , fc000000 , " stw" s, ' rSx(A)sD  ,
7c00052c , fc0007ff , " stwbrx" s, ' rSAB  ,
7c00012d , fc0007ff , " stwcx." s, ' rSAB  ,
94000000 , fc000000 , " stwu" s, ' rSx(A)sD  ,
7c00016e , fc0007ff , " stwux" s, ' rSAB  ,
7c00012e , fc0007ff , " stwx" s, ' rSAB  ,
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" err

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 --) ( or use 'dis' with ret-key to single-step)
     hex
     fffffffc ( -4 ) and 
       \ enforces cell alignment so branch operands always accurate
     dup to addr
     .hexdump 3a emit BL emit   ( print instruction address )
     ( addr @ .hexdump 2 spaces ) \ uncomment to include raw code
     addr dup @ swap roughmask AND to opcode ( save candidate opc )
     find-record to record-> 
     record-> cell+ @      ( instr'n-nominated mask combined with )
     addr @ AND            ( instruction gives exact opcode )
     opcode <> IF    ( does it match initially calculated opcode ? )
        table to record-> THEN ( invalid inst'n, re-assign "data" )
     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)
     addr cell+ to addr    ( pre-increment for next instruction )
     cr 
;


: 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

: dis-help \ For now it just disassembles start of each instr record
   cr ."    G4 Instruction Set with zero-filled operand fields "
   cr ."    default is hexadecimal for numbers > 4 digits "
   cr
   last-record 1 records + table
      do i disasm1
      exit?
      if leave then
   1 records +loop
;    
cr
.." Public Domain replacement 'dis' for G4 Macintosh Open Firmware"
cr
.." dis, +dis, & dis-help await your command. Usage: <address> dis"
cr
.." by Neville Duguid (The Tinkerer) Brisbane Australia, April,2008"
cr
 
0
tinkerer (32)
4/17/2008 10:06:24 AM
comp.sys.powerpc.tech 819 articles. 1 followers. Post Follow

1 Replies
501 Views

Similar Articles

[PageSpeed] 45

On Apr 17, 8:06=A0pm, tinke...@optusnet.com.au (The Tinkerer) posted:
> \ "dis.of" 17-Apr-2008

An upgraded version of "dis.of" dated 21-April-2008 is now available
from the author.

It incorporates the following improvements:

 * dcba included in G4 instruction set.
 * Fields defined 'rA|0' now rendered '0' instead of 'r0' when A=3D0.
 * Instructions with invalid operands now decode as 'data'.
 * 'dis-help' removed, as 0 not a valid operand for all instructions.

An example roll-your-own one line assembler is also included to show
how easy its source code components may be adapted to your own
purposes.

The program is already in the Public Domain. You are free to tinker
with it to your heart's content.

Anyone interested may request a copy via this newsgroup or by mailing
 mailto:tinkerer@optusnet.com.au

Cheers

Tink
0
tinkerer
5/21/2008 7:01:50 AM
Reply: