;
;----------------------------------------------------------------------
;
;       Disassembler for the Motorola 68000
;
;       Written by Rich Page   Jan 25, 1982
;
;----------------------------------------------------------------------
;
;       DBUGEQU is included to get the address of USERA5
;
;        .INCLUDE DBUGEQU.TEXT   (* taken out for workshop - g.c.(4142) *)
usera5   EQU    0                ; address of usera5 equated to zero instead
;
        .PROC   DISASSEMBLER,6
;
;
FALSE   EQU     0
TRUE    EQU     ~FALSE
;
;       XJPW    table,index,dreg
;
        .MACRO  XJPW
        MOVE.W  %2,%3
        ADD.W   %2,%3
        MOVE.W  %1(%3),%3
        JMP     %1(%3)
        .ENDM
;
;       XJPB    table,index,areg,dreg,label
;
        .MACRO  XJPB
        LEA     %1,%3
        CLR.W   %4
        MOVE.B  0(%3,%2),%4
        LEA     %5,%3
        JMP     0(%3,%4)
        .ENDM
;
;       ILLEGAL
;
        .MACRO  ILLEGAL
        BSET    #16,D7
        .ENDM
;
;       NXTWORD
;
        .MACRO  NXTWORD
        MOVE.W  (A5)+,-(A7)
        .ENDM
;
;       APPCHAR char
;
        .MACRO  APPCHAR
        MOVE.W  #%1,D0
        BSR     APPCH
        .ENDM
;
;       USE8IF0 dreg
;
        .MACRO  USE8IF0
        MOVE.W  %1,D0
        TST.W   D0
        BNE.S   @1
        ADD.W   #8,D0
@1
        .ENDM
;
;       B6TO7   dreg
;
        .MACRO  B6TO7
        MOVE.W  D4,%1
        AND.W   #3,%1
        .ENDM
;
;       DATAREG dreg
;
        .MACRO  DATAREG
        MOVE.W  %1,-(A7)
        BSR     DR
        .ENDM
;
;       ADDRREG areg
;
        .MACRO  ADDRREG
        MOVE.W  %1,-(A7)
        BSR     AR
        .ENDM
;
;       MAKEIMM size
;
        .MACRO  MAKEIMM
        MOVE.W  %1,-(A7)
        BSR     MI
        .ENDM
;
;       SHORTIM value
;
        .MACRO  SHORTIM
        MOVE.W  %1,-(A7)
        BSR     SI
        .ENDM
;
;       EA      mode,reg,long
;
        .MACRO  EA
        MOVE.W  %1,-(A7)
        MOVE.W  %2,-(A7)
        .IF     '%3'='LONG'
        MOVE.W  D4,D0
        AND.W   #3,D0
        CMP.W   #2,D0
        SEQ     D0
        MOVE.W  D0,-(A7)
        .ELSE
        MOVE.W  %3,-(A7)
        .ENDC
        BSR     EFFADDR
        .ENDM
;
;       APPNDSZ size
;
        .MACRO  APPNDSZ
        MOVE.W  %1,-(A7)
        BSR     APPSIZE
        .ENDM
;
;       APPND   slen,string
;
        .MACRO  APPND
        MOVE.W  #%1,-(A7)
        BSR     APP
        .IF     %1&1 = 0
        .ASCII  %2
        .ELSE
        .ASCII  %2
        .ASCII  ' '
        .ENDC
        .ENDM
;
;       OPCODE  slen,string
;
        .MACRO  OPCODE
        MOVE.W  #%1,-(A7)
        BSR     OPC
        .IF     %1&1 = 0
        .ASCII  %2
        .ELSE
        .ASCII  %2
        .ASCII  ' '
        .ENDC
        .ENDM
;
; start here and follow the yellow brick road
;
        RORG    0
;       .INCLUDE MSHELL.TEXT
;
;        procedure disassembler(fudgedest:longint;
;                               addrlink:intptr;
;                               var numbytes:integer;
;                               var binary:buffer;
;                               var opcode:str80;
;                               var operand:str80;
;                               destlookup:intptr); external;
;
;       Stack:
;               32      fudge destination
;               28      pointer to addrlink routine       (normally 0)
;               24      @number of bytes consumed by disassembler
;               20      pointer to the code to disassemble
;               16      pointer to string for opcode      (max len is 8)
;               12      pointer to string for operand     (max len is 64)
;               8       pointer to lookup routine
;               4       return address
;               0       old A6
;              -4       saved pointer to code
;              -8       old A5
;              -12      old A4
;              -16      destination address if pc relative
;              -18      word flag to print dest or not
;
;       Registers:
;               D7 is first word of opcode
;               D6 is bits0to2
;               D5 is bits3to5
;               D4 is bits6to8
;               D3 is bits9to11
;
;               A6 is pointer to local frame
;               A5 is pointer to the code to disassemble
;               A4 is free
;               A3 is pointer to string for operand
;
;
;       Lookup is an externally supplied procedure
;
;               procedure lookup(lc,dest:longint; var name:alfa8);
;
;
DISASM  LINK    A6,#-18
        MOVEM.L D4-D7/A3,-(A7)
        MOVE.L  A5,-8(A6)
        MOVE.L  A4,-12(A6)
        MOVE.L  20(A6),A5
        MOVE.L  12(A6),A3
        MOVE.L  A5,-4(A6)
        MOVE.W  #0,-18(A6)
        BSR     TRY2DIS         ; return with D7 upper as validity flag
        SWAP    D7
        TST.W   D7              ; was diassembly valid ?
        BEQ.S   @1
        MOVE.L  -4(A6),A5       ; no, set A5 to old A5+2
        ADD.L   #2,A5
        MOVE.L  16(A6),A0       ; reset opcode and operand strings
        CLR.B   (A0)
        CLR.B   (A3)
        LEA     @2,A2
        OPCODE  4,'$$$$'
@1      TST.W   -18(A6)
        BEQ.S   @2
        BSR     TABDEST
        MOVE.L  -16(A6),-(A7)
        MOVE.L  32(A6),D0
        ADD.L   D0,(A7)
        BSR     HEX4
        BSR     HEX4
@2      MOVE.L  A5,D0
        SUB.L   -4(A6),D0
        MOVE.L  24(A6),A0
        MOVE.W  D0,(A0)
        MOVE.L  -8(A6),A5
        MOVE.L  -12(A6),A4
        MOVEM.L (A7)+,D4-D7/A3
        UNLK    A6
        MOVE.L  (A7)+,A0
        ADD.W   #28,A7
        JMP     (A0)
;
;       APPCH -- appends a character to the operand
;
APPCH   MOVE.B  D0,-(A7)
        MOVE.L  A3,A0
        MOVE.B  (A0)+,D0
        MOVE.B  (A7)+,0(A0,D0)
        ADD.B   #1,(A3)
        RTS
;
;       COMMA -- appends a comma to the operand
;
;       uses registers: A0 and D0
;
COMMA   APPCHAR 44
        RTS
;
;       TABDEST -- tabs to column 16 of operand and appends "; "
;
;       uses registers: A0 and D0
;
TABDEST APPCHAR 32
        MOVE.B  (A3),D0
        CMP.B   #16,D0
        BLT.S   TABDEST
        APPCHAR 59
        APPCHAR 32
        RTS
;
;       DR -- appends a data register to the operand
;
;       uses registers: A0, A1, D0 and D1
;
DR      MOVE.L  (A7)+,A1
        APPCHAR 68
DIGIT   CLR.W   D0
        MOVE.L  A3,A0
        MOVE.B  (A0)+,D0
        MOVE.W  (A7)+,D1
        AND.W   #7,D1
        ADD.W   #48,D1
        MOVE.B  D1,0(A0,D0)
        ADD.B   #1,(A3)
        JMP     (A1)
;
;       AR -- appends an address register to the operand
;
;       uses registers: A0, A1, D0 and D1
;
AR      MOVE.L  (A7)+,A1
        APPCHAR 65
        BRA.S   DIGIT
;
;       REGLIST -- make register list (called with word on tos)
;
;       uses registers: A0, A1, A2, D0, D1 and D2
;
REGLIST MOVE.L  (A7)+,A2
        MOVE.W  (A7)+,D2
        MOVEM.L D3-D7,-(A7)
        MOVE.W  D2,D3
        CMP.W   #4,D5
        BNE.S   PREDECR
        MOVE.W  D3,D0
        MOVE.W  #$10,D2
@1      LSR.W   #1,D1
        BTST    #15,D0
        BEQ.S   @2
        BSET    #15,D1
@2      LSL.W   #1,D0
        SUB.W   #1,D2
        BNE.S   @1
        MOVE.W  D1,D3
PREDECR CLR.W   D2
        MOVE.L  #1,D4
        MOVE.L  #$C0000000,D5
        MOVE.L  #1,D6
DLOOP   MOVE.W  D3,D0
        AND.W   D4,D0
        BEQ.S   @1
        BSR.S   LAST2B
        MOVE.W  D2,-(A7)
        BSR     DR
        APPCHAR 47
@1      LSL.L   #1,D4
        ROL.L   #1,D5
        ADD.W   #1,D2
        CMP.W   #$8,D2
        BNE.S   DLOOP
        MOVE.L  #9,D6
ALOOP   MOVE.W  D3,D0
        AND.W   D4,D0
        BEQ.S   @1
        BSR.S   LAST2B
        MOVE.W  D2,-(A7)
        BSR     AR
        APPCHAR 47
@1      LSL.L   #1,D4
        ROL.L   #1,D5
        ADD.W   #1,D2
        CMP.W   #$10,D2
        BNE.S   ALOOP
        TST.B   (A3)
        BEQ.S   REGLSTX
        SUB.B   #1,(A3)
REGLSTX MOVEM.L (A7)+,D3-D7
        JMP     (A2)
;
; if last two bits in this byte are set then scrub last three characters
;
LAST2B  CMP.W   D6,D2
        BLE.S   @1
        MOVE.W  D3,D0
        AND.W   D5,D0
        CMP.W   D5,D0
        BNE.S   @1
        SUB.B   #4,(A3)
        APPCHAR 45
@1      RTS
;
;       APP -- append string to operand
;
;       uses registers: A0, A1, D0 and D1
;
APP     MOVE.L  (A7)+,A0
        MOVE.W  (A7),D0
        ADD.W   #1,D0
        LSR.W   #1,D0
        MOVE.L  A3,A1
        TST.B   (A1)+
        CLR.W   D1
        MOVE.B  (A3),D1
        ADD.W   D1,A1
        BSR.S   APPLOOP
        MOVE.W  (A7)+,D0
        ADD.B   D0,(A3)
        JMP     (A0)
;
;       APPLOOP - actual append loop shared by APP and OPC
;
APPLOOP MOVE.W  (A0)+,D1
        ROR.W   #8,D1
        MOVE.B  D1,(A1)+
        ROR.W   #8,D1
        MOVE.B  D1,(A1)+
        SUB.W   #1,D0
        BNE.S   APPLOOP
        RTS
;
;       OPC -- append string to opcode
;
;       if A2<>0 then return using A2 else return using modified return address
;
;       uses registers: A0, A1, D0 and D1
;
OPC     MOVE.L  (A7)+,A0
        MOVE.W  (A7),D0
        ADD.W   #1,D0
        LSR.W   #1,D0
        MOVE.L  16(A6),A1
        CLR.W   D1
        MOVE.B  (A1)+,D1
        ADD.W   D1,A1
        BSR.S   APPLOOP
        MOVE.L  16(A6),A1
        MOVE.W  (A7)+,D0
        ADD.B   D0,(A1)
        MOVE.L  A2,D1
        BEQ.S   @1
        JMP     (A2)
@1      JMP     (A0)
;
;       APPSIZE -- append size to opcode
;
;       uses registers: A0, A1, A2, D0 and D1
;
APPSIZE MOVE.L  (A7)+,A2                ; used by OPC
        MOVE.W  (A7)+,D0
        AND.W   #3,D0
        BEQ.S   @1
        CMP.W   #2,D0
        BEQ.S   @2
        OPCODE  2,'.W'
@1      OPCODE  2,'.B'
@2      OPCODE  2,'.L'
;
;       HEX1 -- append a single hex digit to operand
;
;       uses registers: A0, D0 and D1
;
HEXCH   .ASCII  '0123456789ABCDEF'
HEX1    AND.W   #$F,D0
        LEA     HEXCH,A0
        MOVE.B  0(A0,D0),D1
        CLR.W   D0
        MOVE.L  A3,A0
        MOVE.B  (A0)+,D0
        MOVE.B  D1,0(A0,D0)
        ADD.B   #1,(A3)
        RTS
;
;       HEX2 -- append two hex digits to operand
;
;       uses registers: A0, A1, D0 and D1
;
HEX2    MOVE.L  (A7)+,A1
        MOVE.W  (A7),D0
        LSR.W   #4,D0
        BSR     HEX1
        MOVE.W  (A7)+,D0
        BSR     HEX1
        JMP     (A1)
;
;       HEX4 -- append four hex digits to operand
;
;       uses registers: A0, A1, A2, D0 and D1
;
HEX4    MOVE.L  (A7)+,A2
HEX4RA2 MOVE.W  (A7),D0
        LSR.W   #8,D0
        MOVE.W  D0,-(A7)
        BSR     HEX2
        BSR     HEX2
        JMP     (A2)
;
;       MI -- makeimmediate appends #$data to operand
;
;       uses registers: A0, A1, A2, D0 and D1
;
MI      MOVE.L  (A7)+,A2
        APPCHAR 35
        APPCHAR 36
        MOVE.W  (A7)+,D0
        MOVE.L  A2,-(A7)
        AND.W   #3,D0
        CMP.W   #2,D0
        BNE.S   @1
        NXTWORD
        BSR     HEX4
@1      NXTWORD
        BSR     HEX4
        RTS
;
;       SI -- shortimmediate appends #$data to operand
;
;       uses registers: A0, A1, A2, D0 and D1
;
SI      MOVE.L  (A7)+,A2
        APPCHAR 35
        APPCHAR 36
        MOVE.W  (A7)+,D0
        MOVE.L  A2,-(A7)
        BRA     HEX1
;
;       EFFADDR -- generates an effective address
;
EFFADDR MOVE.L  (A7)+,A0        ; pop return address in A0
        MOVE.W  (A7)+,D2
        MOVE.W  (A7)+,D1
        MOVE.W  (A7)+,D0
        MOVE.L  A0,-(A7)        ; push return address for RTS
        MOVEM.W D3/D4/D5,-(A7)
        MOVE.W  D0,D3
        MOVE.W  D1,D4
        MOVE.W  D2,D5
        XJPW    EAMAIN,D3,D1
;
EAMAIN  .WORD   EACAS0-EAMAIN,EACAS1-EAMAIN,EACAS2-EAMAIN,EACAS3-EAMAIN
        .WORD   EACAS4-EAMAIN,EACAS5-EAMAIN,EACAS6-EAMAIN,EACAS7-EAMAIN
;
MAKEREG MOVE.W  4(A7),D0
        AND.W   #$F,4(A7)
        LSL.B   #4,D0
        BMI     AR
        BRA     DR
;
LPARIRP APPCHAR 40
        MOVE.W  D4,-(A7)
        ADD.W   #8,(A7)
        BSR     MAKEREG
        BSR     COMMA
        MOVE.W  (A7),D0
        LSR.W   #8,D0
        LSR.W   #4,D0
        MOVE.W  D0,-(A7)
        BSR     MAKEREG
        BSR     APPDOTL
        APPCHAR 41
        BRA     EAXIT
;
LPANRP  APPCHAR 40
        MOVE.W  D4,-(A7)
        ADD.W   #8,(A7)
        BSR     MAKEREG
        APPCHAR 41
        RTS
;
APPDOTL MOVE.L  (A7)+,A0
        MOVE.W  (A7)+,D0
        MOVE.L  A0,-(A7)
        BTST    #11,D0
        BEQ.S   @1
        APPND   2,'.L'
        RTS
@1      APPND   2,'.W'
        RTS
;
EACAS0  DATAREG D4              ; Di
        BRA.S   BREAXIT
EACAS1  ADDRREG D4              ; Ai
        BRA.S   BREAXIT
EACAS2  BSR     LPANRP          ; (Ai)
        BRA.S   BREAXIT
EACAS3  BSR     LPANRP          ; (Ai)+
        APPCHAR 43
        BRA.S   BREAXIT
EACAS4  APPCHAR 45              ; -(Ai)
        BSR     LPANRP
        BRA.S   BREAXIT
EACAS5  APPCHAR 36              ; e(Ai)
        NXTWORD
        MOVE.W  (A7),-(A7)
        BSR     HEX4
        BSR     LPANRP
        MOVE.W  (A7)+,D0        ; if e >= 0 then
        BMI.S   BREAXIT
        TST.L   28(A6)          ;   if @ADDRLINK <> 0 then
        BEQ.S   BREAXIT
        TST.L   USERA5          ;     if USERA5 <> 0 then
        BEQ.S   BREAXIT
        CMP.W   #$4EAD,D7       ;       if OPCODE = JSR e(A5) then
        BNE.S   BREAXIT
        MOVE.L  USERA5,A0       ;         get users A5 saved by the Loader
        ADD.W   D0,A0           ;         compute address of JMP
        MOVEM.L D1-D7/A0-A6,-(A7)
        MOVE.L  -8(A6),A5       ;         set up the environment
        MOVE.L  -12(A6),A4
        CLR.L   -(A7)           ;         allocate function result
        MOVE.L  A0,-(A7)        ;         push @JMP
        MOVE.L  28(A6),A0
        JSR     (A0)            ;         call ADDRLINK to convert @JMP to @LINK
        MOVE.L  (A7)+,D0
        MOVEM.L (A7)+,D1-D7/A0-A6
        BEQ.S   BREAXIT         ;         if @LINK <> 0 then
        MOVE.L  D0,A0
        BSR     LKUP            ;           do the symbol table lookup
BREAXIT BRA     EAXIT
EACAS6  APPCHAR 36              ; e(Ai,Ri)
        NXTWORD
        MOVE.W  (A7),D0
        AND.W   #$FF,D0
        MOVE.W  D0,-(A7)
        BSR     HEX2
        BRA     LPARIRP
EACAS7  XJPW    EAC7,D4,D1
;
EAC7    .WORD   EAC7S0-EAC7,EAC7S1-EAC7,EAC7S2-EAC7,EAC7S3-EAC7
        .WORD   EAC7S4-EAC7,EAC7S5-EAC7,EAC7S6-EAC7,EAC7S7-EAC7
;
EAC7S0  APPCHAR 36              ; short absolute
        BRA.S   EAC7S1A
EAC7S1  APPCHAR 36              ; long absolute
        NXTWORD
        BSR     HEX4
EAC7S1A NXTWORD
        BSR     HEX4
        BRA.S   EAXIT
EAC7S2                          ; PC relative
        BSR     PCRELWD         ; leaves a copy of NXTWORD on the stack
        MOVE.L  A5,A0
        SUB.L   #2,A0
        MOVE.L  A0,A1
        ADD.W   (A7)+,A0
        BSR     LKUP
        BRA.S   EAXIT
EAC7S3                          ; PC relative with index
        BSR     PCRELBT         ; leaves two copies of NXTWORD on the stack
        MOVE.L  A5,A0
        SUB.L   #2,A0
        MOVE.L  A0,A1
        ADD.W   (A7)+,A0        ; top most copy was sign extended
        BSR     LKUP
        APPCHAR 40
        MOVE.W  (A7),D0         ; just looks at nextword to get Ri
        LSR.W   #8,D0
        LSR.W   #4,D0
        MOVE.W  D0,-(A7)
        BSR     MAKEREG
        BSR     APPDOTL         ; checks bit 11 and deletes nextword
        APPCHAR 41
        BRA.S   EAXIT
EAC7S4  TST.W   D5              ; immediate operand
        BEQ.S   @1
        MAKEIMM #2
        BRA.S   EAXIT
@1      MAKEIMM #1
        BRA.S   EAXIT
EAC7S5
EAC7S6
EAC7S7  ILLEGAL
EAXIT   MOVEM.W (A7)+,D3/D4/D5
        RTS
;
;       TRY2DIS -- try to disassemble
;
TRY2DIS MOVE.L  16(A6),A0       ; initialize opcode string
        CLR.B   (A0)
        CLR.B   (A3)            ; initialize operand string
        CLR.L   D7              ; validity flag false
        MOVE.W  (A5)+,D7        ; get first opcode word
        MOVE.W  D7,D6
        MOVE.W  D6,D5
        LSR.W   #3,D5
        MOVE.W  D5,D4
        LSR.W   #3,D4
        MOVE.W  D4,D3
        LSR.W   #3,D3
        MOVE.W  D3,D0
        LSR.W   #3,D0
        MOVE.L  #7,D2           ; field mask after shifts
        AND.W   D2,D6           ; D6 is bits0to2
        AND.W   D2,D5           ; D5 is bits3to5
        AND.W   D2,D4           ; D4 is bits6to8
        AND.W   D2,D3           ; D3 is bits9to11
        SUB.L   A2,A2
        XJPW    MAIN,D0,D1
;
MAIN    .WORD   CASE0-MAIN,CASE1-MAIN,CASE2-MAIN,CASE3-MAIN
        .WORD   CASE4-MAIN,CASE5-MAIN,CASE6-MAIN,CASE7-MAIN
        .WORD   CASE8-MAIN,CASE9-MAIN,CASEA-MAIN,CASEB-MAIN
        .WORD   CASEC-MAIN,CASED-MAIN,CASEE-MAIN,CASEF-MAIN
;
;       BITOPC -- generate opcodes for bit instructions
;
BITOPC  MOVE.W  D4,D0
        AND.W   #3,D0
        MOVE.L  (A7)+,A2
T0      XJPB    BITTBL,D0,A0,D1,T0
OPBTST  OPCODE  4,'BTST'
OPBCHG  OPCODE  4,'BCHG'
OPBCLR  OPCODE  4,'BCLR'
OPBSET  OPCODE  4,'BSET'
;
; bit manipulation, move peripheral, immediate instructions
;
CASE0   BTST    #8,D7
        BEQ.S   CASE0C
        CMP.W   #1,D5
        BEQ.S   CASE0A
        BSR.S   BITOPC
        BSR.S   DATARD3
COMMAEF BSR     COMMA
EA56F   EA      D5,D6,#FALSE
        RTS
CASE0A  SUB.L   A2,A2
        OPCODE  5,'MOVEP'
        MOVE.W  D4,D0
        AND.W   #1,D0
        ADD.W   #1,D0
        APPNDSZ D0
        TST.B   D7
        BPL.S   CASE0B
        BSR.S   DATARD3
        BSR     COMMA
        EA      #5,D6,#FALSE
        RTS
CASE0B  EA      #5,D6,#FALSE
COMMAD3 BSR     COMMA
DATARD3 DATAREG D3
        RTS
CASE0C  SUB.L   A2,A2
        XJPB    C0TBL,D3,A0,D1,CASE0C
C0S0    OPCODE  3,'ORI'
IMMELOG APPNDSZ D4
        MAKEIMM D4
        BSR     COMMA
        CMP.W   #7,D5
        BNE.S   EALONG
        CMP.W   #4,D6
        BNE.S   EALONG
        B6TO7   D0
        BNE     APPNDSR
        BRA     APPNCCR
C0S1    OPCODE  4,'ANDI'
        BRA.S   IMMELOG
C0S2    OPCODE  4,'SUBI'
IMMEARI APPNDSZ D4
        MAKEIMM D4
COMMALN BSR     COMMA
EALONG  EA      D5,D6,LONG
        RTS
C0S3    OPCODE  4,'ADDI'
        BRA.S   IMMEARI
C0S4    BSR.S   BITOPC
        EA      #7,#4,#FALSE
        BRA     COMMAEF
C0S5    OPCODE  4,'EORI'
        BRA.S   IMMELOG
C0S6    OPCODE  4,'CMPI'
        BRA.S   IMMEARI
C0S7    ILLEGAL
        RTS
;
; Move byte
;
CASE1   OPCODE  6,'MOVE.B'
EA2EA   BSR     EA56F
        BSR     COMMA
        EA      D4,D3,#FALSE
        RTS
;
; Move long
;
CASE2   OPCODE  6,'MOVE.L'
        EA      D5,D6,#TRUE
        BSR     COMMA
        EA      D4,D3,#TRUE
        RTS
;
; Move word
;
CASE3   OPCODE  6,'MOVE.W'
        BRA.S   EA2EA
;
; Misc.
;
CASE4   CMP.W   #6,D4
        BNE.S   @1
        OPCODE  3,'CHK'
        BRA     EA2D3
@1      CMP.W   #7,D4
        BNE.S   @2
        OPCODE  3,'LEA'
        EA      D5,D6,#TRUE
        BSR     COMMA
        ADDRREG D3
        RTS
@2      XJPW    C4TBL,D3,D1
;
C4TBL   .WORD   C4S0-C4TBL,C4S1-C4TBL,C4S2-C4TBL,C4S3-C4TBL
        .WORD   C4S4-C4TBL,C4S5-C4TBL,C4S6-C4TBL,C4S7-C4TBL
;
C4S0    B6TO7   D0
        CMP.W   #3,D0
        BNE.S   @1
        OPCODE  4,'MOVE'
        BSR     APPNDSR
        BRA     COMMAEF
@1      OPCODE  4,'NEGX'
D4EALNG APPNDSZ D4
        BRA     EALONG
C4S1    B6TO7   D0
        CMP.W   #3,D0
        BNE.S   @1
        ILLEGAL
        RTS
@1      OPCODE  3,'CLR'
        BRA     D4EALNG
C4S2    B6TO7   D0
        CMP.W   #3,D0
        BNE.S   C4S2A
        OPCODE  4,'MOVE'
        BSR     EA56F
        BSR     COMMA
APPNCCR APPND   3,'CCR'
        RTS
C4S2A   OPCODE  3,'NEG'
        BRA     D4EALNG
C4S3    B6TO7   D0
        CMP.W   #3,D0
        BNE.S   C4S3A
        OPCODE  4,'MOVE'
        BSR     EA56F
        BSR     COMMA
APPNDSR APPND   2,'SR'
        RTS
C4S3A   OPCODE  3,'NOT'
        BRA     D4EALNG
C4S4    B6TO7   D0
T1      XJPB    C4S4TBL,D0,A0,D1,T1
C4S4S0  OPCODE  4,'NBCD'
        BRA     EA56F
C4S4S1  TST.W   D5
        BNE.S   NOTSWAP
        OPCODE  4,'SWAP'
DATARD6 DATAREG D6
        RTS
NOTSWAP OPCODE  3,'PEA'
        BRA     EA56F
C4S4S2  TST.W   D5
        BNE.S   @1
        OPCODE  5,'EXT.W'
        BRA     DATARD6
@1      OPCODE  7,'MOVEM.W'
REGLSEA NXTWORD
        BSR     REGLIST
        BRA     COMMAEF
C4S4S3  TST.W   D5
        BNE.S   @1
        OPCODE  5,'EXT.L'
        BRA     DATARD6
@1      OPCODE  7,'MOVEM.L'
        BRA     REGLSEA
C4S5    B6TO7   D0
        CMP.W   #3,D0
        BNE.S   @1
        OPCODE  3,'TAS'
        BRA     EA56F
@1      OPCODE  3,'TST'
        BRA     D4EALNG
C4S6    OPCODE  5,'MOVEM'
        MOVE.W  D4,D0
        AND.W   #1,D0
        ADD.W   #1,D0
        APPNDSZ D0
        NXTWORD
        BSR     EA56F
        BSR     COMMA
        BSR     REGLIST
        RTS
C4S7    B6TO7   D0
T2      XJPB    C4S7TBL,D0,A0,D1,T2
C4S7S0  ILLEGAL
        RTS
C4S7S1  MOVE.W  D5,D0
        AND.W   #6,D0
        BNE.S   T3
        OPCODE  4,'TRAP'
        SHORTIM D7
        RTS
T3      XJPB    C4S7S1T,D5,A0,D1,T3
C4S7S2  OPCODE  3,'JSR'
        BRA     EA56F
C4S7S3  OPCODE  3,'JMP'
        BRA     EA56F
C4S7S10
C4S7S11
C4S7S17 ILLEGAL
        RTS
C4S7S12 OPCODE  4,'LINK'
        ADDRREG D6
        BSR     COMMA
        EA      #7,#4,#FALSE
        RTS
C4S7S13 OPCODE  4,'UNLK'
        ADDRREG D6
        RTS
C4S7S14 OPCODE  4,'MOVE'
        ADDRREG D6
        BSR     COMMA
        APPND   3,'USP'
        RTS
C4S7S15 OPCODE  4,'MOVE'
        APPND   3,'USP'
        BSR     COMMA
        ADDRREG D6
        RTS
C4S7S16 XJPB    MISC,D6,A0,D1,C4S7S16
MISC0   OPCODE  5,'RESET'
        RTS
MISC1   OPCODE  3,'NOP'
        RTS
MISC2   OPCODE  4,'STOP'
        EA      #7,#4,#FALSE
        RTS
MISC3   OPCODE  3,'RTE'
        RTS
MISC4   ILLEGAL
        RTS
MISC5   OPCODE  3,'RTS'
        RTS
MISC6   OPCODE  5,'TRAPV'
        RTS
MISC7   OPCODE  3,'RTR'
        RTS
;
; Add and subtract quick, set conditionally, decrements
;
CASE5   B6TO7   D0
        CMP.W   #3,D0
        BNE     CASE5A
        CMP.W   #1,D5
        BNE     SETCC
        MOVE.W  D7,D0
        LSR.W   #8,D0
        AND.W   #$F,D0
        LEA     DBOPNDS,A2
        XJPW    C5DBCC,D0,D1
;
C5DBCC  .WORD   C5DB0-C5DBCC,C5DB1-C5DBCC,C5DB2-C5DBCC,C5DB3-C5DBCC
        .WORD   C5DB4-C5DBCC,C5DB5-C5DBCC,C5DB6-C5DBCC,C5DB7-C5DBCC
        .WORD   C5DB8-C5DBCC,C5DB9-C5DBCC,C5DB10-C5DBCC,C5DB11-C5DBCC
        .WORD   C5DB12-C5DBCC,C5DB13-C5DBCC,C5DB14-C5DBCC,C5DB15-C5DBCC
;
C5DB0   OPCODE  3,'DBT'
C5DB1   OPCODE  3,'DBF'
C5DB2   OPCODE  4,'DBHI'
C5DB3   OPCODE  4,'DBLS'
C5DB4   OPCODE  4,'DBCC'
C5DB5   OPCODE  4,'DBCS'
C5DB6   OPCODE  4,'DBNE'
C5DB7   OPCODE  4,'DBEQ'
C5DB8   OPCODE  4,'DBVC'
C5DB9   OPCODE  4,'DBVS'
C5DB10  OPCODE  4,'DBPL'
C5DB11  OPCODE  4,'DBMI'
C5DB12  OPCODE  4,'DBGE'
C5DB13  OPCODE  4,'DBLT'
C5DB14  OPCODE  4,'DBGT'
C5DB15  OPCODE  4,'DBLE'
DBOPNDS BSR     DATARD6
        BSR     COMMA
        EA      #7,#2,#FALSE
        RTS
SETCC   MOVE.W  D7,D0
        LSR.W   #8,D0
        AND.W   #$F,D0
        LEA     SCOPNDS,A2
        XJPW    C5SCC,D0,D1
;
C5SCC   .WORD   C5SCC0-C5SCC,C5SCC1-C5SCC,C5SCC2-C5SCC,C5SCC3-C5SCC
        .WORD   C5SCC4-C5SCC,C5SCC5-C5SCC,C5SCC6-C5SCC,C5SCC7-C5SCC
        .WORD   C5SCC8-C5SCC,C5SCC9-C5SCC,C5SCC10-C5SCC,C5SCC11-C5SCC
        .WORD   C5SCC12-C5SCC,C5SCC13-C5SCC,C5SCC14-C5SCC,C5SCC15-C5SCC
;
C5SCC0  OPCODE  2,'ST'
C5SCC1  OPCODE  2,'SF'
C5SCC2  OPCODE  3,'SHI'
C5SCC3  OPCODE  3,'SLS'
C5SCC4  OPCODE  3,'SCC'
C5SCC5  OPCODE  3,'SCS'
C5SCC6  OPCODE  3,'SNE'
C5SCC7  OPCODE  3,'SEQ'
C5SCC8  OPCODE  3,'SVC'
C5SCC9  OPCODE  3,'SVS'
C5SCC10 OPCODE  3,'SPL'
C5SCC11 OPCODE  3,'SMI'
C5SCC12 OPCODE  3,'SGE'
C5SCC13 OPCODE  3,'SLT'
C5SCC14 OPCODE  3,'SGT'
C5SCC15 OPCODE  3,'SLE'
SCOPNDS BRA     EA56F
CASE5A  BTST    #8,D7
        BEQ.S   CASE5B
        OPCODE  4,'SUBQ'
        BRA.S   QUICK
CASE5B  OPCODE  4,'ADDQ'
QUICK   APPNDSZ D4
        USE8IF0 D3
        SHORTIM D0
        BRA     COMMALN
;
; Branch conditionally
;
CASE6   MOVE.W  D7,D0
        LSR.W   #8,D0
        AND.W   #$F,D0
        LEA     BCOPNDS,A2
        XJPW    C6BCC,D0,D1
;
C6BCC   .WORD   C6BCC0-C6BCC,C6BCC1-C6BCC,C6BCC2-C6BCC,C6BCC3-C6BCC
        .WORD   C6BCC4-C6BCC,C6BCC5-C6BCC,C6BCC6-C6BCC,C6BCC7-C6BCC
        .WORD   C6BCC8-C6BCC,C6BCC9-C6BCC,C6BCC10-C6BCC,C6BCC11-C6BCC
        .WORD   C6BCC12-C6BCC,C6BCC13-C6BCC,C6BCC14-C6BCC,C6BCC15-C6BCC
;
C6BCC0  OPCODE  3,'BRA'
C6BCC1  OPCODE  3,'BSR'
C6BCC2  OPCODE  3,'BHI'
C6BCC3  OPCODE  3,'BLS'
C6BCC4  OPCODE  3,'BCC'
C6BCC5  OPCODE  3,'BCS'
C6BCC6  OPCODE  3,'BNE'
C6BCC7  OPCODE  3,'BEQ'
C6BCC8  OPCODE  3,'BVC'
C6BCC9  OPCODE  3,'BVS'
C6BCC10 OPCODE  3,'BPL'
C6BCC11 OPCODE  3,'BMI'
C6BCC12 OPCODE  3,'BGE'
C6BCC13 OPCODE  3,'BLT'
C6BCC14 OPCODE  3,'BGT'
C6BCC15 OPCODE  3,'BLE'
BCOPNDS TST.B   D7
        BNE.S   SHORTBR
        BSR.S   PCRELWD         ; leaves a copy of NXTWORD on the stack
        MOVE.L  A5,A0
        SUB.L   #2,A0
        BRA.S   DOLOC
SHORTBR SUB.L   A2,A2
        OPCODE  2,'.S'
        MOVE.W  #2,D2           ; at other calls to PCRELTV we would set D2=0
        LEA     SHORTB2,A2
        MOVE.W  D7,D0           ; generate sign extended
        EXT.W   D0
        MOVE.W  D0,-(A7)
        BRA.S   PCRELTV
SHORTB2 MOVE.L  A5,A0
DOLOC   MOVE.L  A0,A1
        ADD.W   (A7)+,A0
        BSR     LKUP
        RTS
;
;       PCRELWD -- make pc relative word offset
;
PCRELWD MOVE.L  (A7)+,A2
        NXTWORD                 ; push the nextword onto the stack
PCRELZD CLR.W   D2
PCRELTV MOVE.W  (A7),-(A7)      ; duplicate the word on top of stack
        MOVE.L  A5,D0
        SUB.L   #2,D0
        SUB.L   -4(A6),D0       ; making the code buffer relative to zero
        ADD.W   D0,(A7)         ; modifying the relative offset
        BPL.S   @1
        APPND   3,'*-$'
        NEG.W   (A7)
        SUB.W   D2,(A7)         ; D2 = 2 for short branches only
        BRA.S   @2
@1      APPND   3,'*+$'
        ADD.W   D2,(A7)         ; D2 = 2 for short branches only
@2      BRA     HEX4RA2         ; call HEX4, ret addr in A2, copy is consumed
;
;       PCRELBT -- make pc relative byte offset
;
PCRELBT MOVE.L  (A7)+,A2
        NXTWORD                 ; push nextword
        MOVE.W  (A7),D0
        EXT.W   D0
        MOVE.W  D0,-(A7)        ; push a sign extended copy for LKUP
        BRA.S   PCRELZD
;
;       LKUP -- calls the external lookup routine
;
;       Enter with A0 equal to dest address
;
LKUP    MOVEM.L D0-D7/A0-A6,-(A7)
        MOVE.L  A0,-16(A6)
        MOVE.W  #1,-18(A6)
        MOVE.L  A1,-(A7)
        MOVE.L  A0,-(A7)
        MOVE.L  A3,-(A7)
        MOVE.L  -8(A6),A5
        MOVE.L  -12(A6),A4
        MOVE.L  8(A6),A0
        JSR     (A0)            ; CALL LOOKUP
        MOVEM.L (A7)+,D0-D7/A0-A6
        RTS
;
; Move quick
;
CASE7   BTST    #8,D7
        BEQ.S   @1
        ILLEGAL
        RTS
@1      OPCODE  5,'MOVEQ'
        TST.B   D7
        BPL.S   @2
        APPND   3,'#-$'
        BRA.S   @3
@2      APPND   2,'#$'
@3      MOVE.W  D7,D0
        AND.W   #$7F,D0
        MOVE.W  D0,-(A7)
        BSR     HEX2
        BRA     COMMAD3
;
; Or, divide, subtract decimal
;
CASE8   MOVE.W  D7,D0
        AND.W   #$1F0,D0
        CMP.W   #$100,D0
        BNE.S   SDIV
        OPCODE  4,'SBCD'
        BRA     AORSBCD
SDIV    CMP.W   #7,D4
        BNE.S   UDIV
        OPCODE  4,'DIVS'
EA2D3   BSR     EA56F
        BRA     COMMAD3
UDIV    CMP.W   #3,D4
        BNE.S   @1
        OPCODE  4,'DIVU'
        BRA     EA2D3
@1      OPCODE  2,'OR'
DEANEAD APPNDSZ D4
        BTST    #8,D7
        BEQ.S   EADATA
DATAEA  BSR     DATARD3
        BRA     COMMALN
EADATA  BSR     EALONG
        BRA     COMMAD3
;
; Subtract
;
CASE9   BTST    #8,D7
        BEQ.S   CASE9A
        MOVE.W  D7,D0
        AND.W   #$30,D0
        BNE.S   CASE9A
        MOVE.W  D7,D0
        AND.W   #$C0,D0
        CMP.W   #$C0,D0
        BEQ.S   CASE9A
        OPCODE  4,'SUBX'
ADDSUBX APPNDSZ D4
AORSBCD CMP.W   #1,D5
        BNE.S   @1
        EA      #4,D6,LONG
        BSR     COMMA
        EA      #4,D3,LONG
        RTS
@1      BSR     DATARD6
        BRA     COMMAD3
CASE9A  CMP.W   #3,D4
        BNE.S   CASE9B
        OPCODE  6,'SUBA.W'
EAADDR  CMP.W   #7,D4
        BNE.S   @1
        EA      D5,D6,#TRUE
        BRA.S   @2
@1      BSR     EA56F
@2      BSR     COMMA
        ADDRREG D3
        RTS
CASE9B  CMP.W   #7,D4
        BNE.S   CASE9C
        OPCODE  6,'SUBA.L'
        BRA.S   EAADDR
        RTS
CASE9C  OPCODE  3,'SUB'
        BRA     DEANEAD
;
; L1010 - IUJSR, IUJMP, IULEA, IUPEA
;
CASEA   MOVE.W  D3,D0
        LSR.W   #1,D0
        AND.W   #$3,D0          ; needed ?
        LEA     CASEAIU,A2
        XJPW    CAIUXX,D0,D1
;
CAIUXX  .WORD   CAIUXX0-CAIUXX,CAIUXX1-CAIUXX,CAIUXX2-CAIUXX,CAIUXX3-CAIUXX
;
CAIUXX0 OPCODE  5,'IUJSR'
CAIUXX1 OPCODE  5,'IUJMP'
CAIUXX2 OPCODE  5,'IULEA'
CAIUXX3 OPCODE  5,'IUPEA'
CASEAIU APPCHAR 36
        MOVE.W  D3,D0
        LSR.W   #1,D0
        AND.W   #$3,D0          ; needed ?
        CMP.W   #2,D0
        BEQ.S   IULEA
        MOVE.W  D7,-(A7)
        AND.W   #$FF,(A7)
        BSR     HEX4
        NXTWORD
        BSR     HEX4
        RTS
IULEA   MOVE.W  D7,D0
        AND.W   #$7F,D0
        SWAP    D0
        NXTWORD
        MOVE.W  (A7)+,D0
        ADD.L   D0,D0
        MOVE.L  D0,-(A7)
        BSR     HEX4
        BSR     HEX4
        BSR     COMMA
        MOVE.W  D7,D0
        LSR.W   #7,D0
        AND.W   #$7,D0
        ADDRREG D0
        RTS
;
; Compare, exclusive or
;
CASEB   BTST    #8,D7
        BEQ.S   CASEBA
        CMP.W   #1,D5
        BNE.S   CASEBA
        MOVE.W  D7,D0
        AND.W   #$C0,D0
        CMP.W   #$C0,D0
        BEQ.S   CASEBA
        OPCODE  4,'CMPM'
        APPNDSZ D4
        EA      #3,D6,#FALSE
        BSR     COMMA
        EA      #3,D3,#FALSE
        RTS
CASEBA  BTST    #8,D7
        BEQ.S   CASEBB
        MOVE.W  D7,D0
        AND.W   #$C0,D0
        CMP.W   #$C0,D0
        BEQ.S   CASEBB
        OPCODE  3,'EOR'
        APPNDSZ D4
        BRA     DATAEA
CASEBB  CMP.W   #3,D4
        BNE.S   CASEBC
        OPCODE  6,'CMPA.W'
        BRA     EAADDR
        RTS
CASEBC  CMP.W   #7,D4
        BNE.S   CASEBD
        OPCODE  6,'CMPA.L'
        BRA     EAADDR
        RTS
CASEBD  OPCODE  3,'CMP'
        APPNDSZ D4
        BSR     EALONG
        BRA     COMMAD3
;
; And, Multiply, Add decimal, Exchange
;
CASEC   CMP.W   #5,D4
        BNE.S   @1
        TST.W   D5
        BNE.S   @1
        OPCODE  3,'EXG'
        BSR     DATARD3
        BRA     COMMAD6
@1      CMP.W   #5,D4
        BNE.S   @2
        CMP.W   #1,D5
        BNE.S   @2
        OPCODE  3,'EXG'
        ADDRREG D3
        BSR     COMMA
        ADDRREG D6
        RTS
@2      CMP.W   #6,D4
        BNE.S   BCDADD
        CMP.W   #1,D5
        BNE.S   BCDADD
        OPCODE  3,'EXG'
        BSR     DATARD3
        BSR     COMMA
        ADDRREG D6
        RTS
BCDADD  MOVE.W  D7,D0
        AND.W   #$1F0,D0
        CMP.W   #$100,D0
        BNE.S   SMUL
        OPCODE  4,'ABCD'
        BRA     AORSBCD
SMUL    CMP.W   #7,D4
        BNE.S   UMUL
        OPCODE  4,'MULS'
        BRA     EA2D3
UMUL    CMP.W   #3,D4
        BNE.S   @1
        OPCODE  4,'MULU'
        BRA     EA2D3
@1      OPCODE  3,'AND'
        BRA     DEANEAD
;
; Add
;
CASED   BTST    #8,D7
        BEQ.S   CASEDA
        MOVE.W  D7,D0
        AND.W   #$30,D0
        BNE.S   CASEDA
        MOVE.W  D7,D0
        AND.W   #$C0,D0
        CMP.W   #$C0,D0
        BEQ.S   CASEDA
        OPCODE  4,'ADDX'
        BRA     ADDSUBX
CASEDA  CMP.W   #3,D4
        BNE.S   CASEDB
        OPCODE  6,'ADDA.W'
        BRA     EAADDR
        RTS
CASEDB  CMP.W   #7,D4
        BNE.S   CASEDC
        OPCODE  6,'ADDA.L'
        BRA     EAADDR
        RTS
CASEDC  OPCODE  3,'ADD'
        BRA     DEANEAD
;
; PUTSHFT -- put shift opcode
;
PUTSHFT MOVE.L  (A7)+,A2
        XJPB    SHFTTBL,D0,A0,D1,PUTSHFT
SHIFT0  OPCODE  3,'ASR'
SHIFT1  OPCODE  3,'ASL'
SHIFT2  OPCODE  3,'LSR'
SHIFT3  OPCODE  3,'LSL'
SHIFT4  OPCODE  4,'ROXR'
SHIFT5  OPCODE  4,'ROXL'
SHIFT6  OPCODE  3,'ROR'
SHIFT7  OPCODE  3,'ROL'
;
; Shifts and rotates
;
CASEE   B6TO7   D0
        CMP.W   #3,D0
        BNE.S   DRSHIFT
        MOVE.W  D7,D0
        LSR.W   #8,D0
        AND.W   #7,D0
        BSR     PUTSHFT
        APPNDSZ #1
        BRA     EA56F
DRSHIFT MOVE.W  D5,D0
        AND.W   #3,D0
        ADD.W   D0,D0
        BTST    #8,D7
        BEQ.S   @1
        ADD.W   #1,D0
@1      BSR     PUTSHFT
        APPNDSZ D4
        BTST    #5,D7
        BEQ.S   @2
        BSR     DATARD3
        BRA.S   COMMAD6
@2      USE8IF0 D3
        SHORTIM D0
COMMAD6 BSR     COMMA
        BRA     DATARD6
;
; unassigned
;
CASEF   ILLEGAL
        RTS
;
;       BITTBL
;
BITTBL  .BYTE   OPBTST-T0,OPBCHG-T0,OPBCLR-T0,OPBSET-T0
;
;       C0TBL
;
C0TBL   .BYTE   C0S0-CASE0C,C0S1-CASE0C,C0S2-CASE0C,C0S3-CASE0C
        .BYTE   C0S4-CASE0C,C0S5-CASE0C,C0S6-CASE0C,C0S7-CASE0C
;
;       C4S4TBL
;
C4S4TBL .BYTE   C4S4S0-T1,C4S4S1-T1,C4S4S2-T1,C4S4S3-T1
;
;       C4S7TBL
;
C4S7TBL .BYTE   C4S7S0-T2,C4S7S1-T2,C4S7S2-T2,C4S7S3-T2
;
;       C4S7S1T
;
C4S7S1T .BYTE   C4S7S10-T3,C4S7S11-T3,C4S7S12-T3,C4S7S13-T3
        .BYTE   C4S7S14-T3,C4S7S15-T3,C4S7S16-T3,C4S7S17-T3
;
;       MISC TRANSFER TABLE
;
MISC    .BYTE   MISC0-C4S7S16,MISC1-C4S7S16,MISC2-C4S7S16,MISC3-C4S7S16
        .BYTE   MISC4-C4S7S16,MISC5-C4S7S16,MISC6-C4S7S16,MISC7-C4S7S16
;
;       SHIFT TRANSFER TABLE
;
SHFTTBL .BYTE   SHIFT0-PUTSHFT,SHIFT1-PUTSHFT,SHIFT2-PUTSHFT,SHIFT3-PUTSHFT
        .BYTE   SHIFT4-PUTSHFT,SHIFT5-PUTSHFT,SHIFT6-PUTSHFT,SHIFT7-PUTSHFT
;
;       THEEND -- USED BY SHELL TO COPY DISASSEMBLER
;
        .WORD   0,0,0
THEEND  .WORD   0
;
        END


