1;
2; Ullrich von Bassewitz, 07.08.1998
3;
4; unsigned DbgDisAsm (char* buf, unsigned addr);
5; unsigned DbgDisAsm (unsigned addr);
6;
7;
8; Part of this code is taken from the Plus/4 machine language monitor
9; (TEDMon).
10;
11
12        .import         popax
13        .import         __hextab, OffsetTab, AdrFlagTab
14        .import         SymbolTab1, SymbolTab2, MnemoTab1, MnemoTab2
15
16
17
18; -------------------------------------------------------------------------
19; Equates for better readability
20
21        .importzp       sreg, tmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3
22
23BufIndex        = tmp1          ; Index into output buffer
24OperandLen      = tmp2          ; Length of operand
25BufLen          = tmp3          ; Length of output buffer
26AdrFlagBuf      = tmp4          ; Flag for addressing mode
27YSave           = sreg          ; Temp storage
28XSave           = sreg+1        ; Dito
29BufPtr          = ptr1          ; Pointer to output buffer
30MemPtr          = ptr2          ; Pointer to memory to disassemble
31MnemoBuf        = ptr3          ; Buffer for decoding mnemonic
32
33
34; -------------------------------------------------------------------------
35; Main entries
36
37        .export         _DbgDisAsm, _DbgDisAsmLen
38
39.proc   _DbgDisAsm
40        sta     BufLen          ; Save the buffer length
41        jsr     popax           ; Get the buffer pointer
42        sta     BufPtr
43        stx     BufPtr+1
44        jsr     popax           ; Get the address
45        sta     MemPtr
46        stx     MemPtr+1
47        lda     #0
48        sta     BufIndex        ; Initialize index into buffer
49        jsr     DisAssLine      ; Disassemble one line into the buffer
50
51        lda     BufLen          ; Get requested length
52        sec
53        sbc     BufIndex
54        beq     L2
55        tax                     ; Count into X
56        ldy     BufIndex
57        lda     #$20            ; Get a space
58L1:     sta     (BufPtr),y
59        iny
60        dex
61        bne     L1
62L2:     lda     #0              ; Add C string terminator
63        sta     (BufPtr),y
64        beq     disassret
65
66.endproc
67
68
69_DbgDisAsmLen:
70        sta     MemPtr          ; Save address
71        stx     MemPtr+1
72        ldy     #$00
73        lda     (MemPtr),y      ; Get the opcode from memory...
74        jsr     AnalyzeOPCode   ; ...and analyze it
75disassret:
76        ldx     OperandLen      ; Get length of operand
77        inx                     ; Adjust for opcode byte
78        txa
79        ldx     #$00            ; Clear high byte
80        rts
81
82; -------------------------------------------------------------------------
83; Helper functions
84
85
86Put3Spaces:
87        jsr     PutSpace
88Put2Spaces:
89        jsr     PutSpace
90PutSpace:
91        lda     #$20
92PutChar:
93        sty     YSave           ; Save Y
94        ldy     BufIndex        ; Get current line pointer
95        cpy     BufLen          ; Be sure not to overflow the buffer
96        bcs     PC9
97        sta     (BufPtr),y      ; store character
98        iny                     ; bump index
99        sty     BufIndex
100PC9:    ldy     YSave           ; get old value
101        rts
102
103; Print the 16 bit hex value in X/Y
104
105PutHex16:
106        txa
107        jsr     PutHex8
108        tya
109
110; Print 8 bit value in A, save X and Y
111
112PutHex8:
113        stx     XSave
114        sty     YSave
115        ldy     BufIndex
116        pha
117        lsr     a
118        lsr     a
119        lsr     a
120        lsr     a
121        tax
122        lda     __hextab,x
123        sta     (BufPtr),y
124        iny
125        pla
126        and     #$0F
127        tax
128        lda     __hextab,x
129        sta     (BufPtr),y
130        iny
131        sty     BufIndex
132        ldy     YSave
133        ldx     XSave
134        rts
135
136; -------------------------------------------------------------------------
137; Disassemble one line
138
139DisAssLine:
140        ldy     MemPtr
141        ldx     MemPtr+1
142        jsr     PutHex16                ; Print the address
143        jsr     Put2Spaces              ; Add some space
144        ldy     #$00
145        lda     (MemPtr),y              ; Get the opcode from memory...
146        jsr     AnalyzeOPCode           ; ...and analyze it
147        pha                             ; Save mnemonic
148        ldx     OperandLen              ; Number of bytes
149
150; Print the bytes that make up the instruction
151
152        inx
153L2083:  dex
154        bpl     L208C                   ; Print the instruction bytes
155        jsr     Put3Spaces              ; If none left, print spaces instead
156        jmp     L2094
157L208C:  lda     (MemPtr),y              ; Get a byte from memory
158        jsr     PutHex8                 ; ...and print it
159        jsr     PutSpace                ; Add some space
160
161L2094:  iny                             ; Next one...
162        cpy     #$03                    ; Maximum is three
163        bcc     L2083                   ;
164
165        jsr     Put2Spaces              ; Add some space after bytes
166
167; Print the assembler mnemonic
168
169        pla                             ; Get mnemonic code
170        ldx     #$03
171        jsr     PutMnemo                ; Print the mnemonic
172        ldx     #$06
173
174; Print the operand
175
176L20A4:  cpx     #$03
177        bne     L20BA
178        ldy     OperandLen
179        beq     L20BA
180
181L20AC:  lda     AdrFlagBuf
182        cmp     #$E8                    ; Branch?
183        lda     (MemPtr),y              ; Get branch offset
184        bcs     GetBranchAdr            ; If branch: Calculate address
185        jsr     PutHex8                 ; Otherwise print 8bit value
186        dey
187        bne     L20AC
188
189L20BA:  asl     AdrFlagBuf
190        bcc     L20CC
191        lda     SymbolTab1-1,x
192        jsr     PutChar
193        lda     SymbolTab2-1,x
194        beq     L20CC
195        jsr     PutChar
196
197L20CC:  dex
198        bne     L20A4
199        rts
200
201; If the instruction is a branch, calculate the absolute address of the
202; branch target and print it.
203
204GetBranchAdr:
205        jsr     L20DD
206        clc
207        adc     #$01
208        bne     L20D9
209        inx                             ; Bump high byte
210L20D9:  tay
211        jmp     PutHex16                ; Output address
212
213L20DD:  ldx     MemPtr+1
214        tay
215        bpl     L20E3
216        dex
217L20E3:  adc     MemPtr
218        bcc     L20E8
219        inx                             ; Bump high byte
220L20E8:  rts
221
222; -------------------------------------------------------------------------
223; Subroutine to analyze an opcode byte in A. Will return a byte that
224; encodes the mnemonic, and will set the number of bytes needed for this
225; instruction in OperandLen
226
227AnalyzeOPCode:
228        tay
229        lsr     a
230        bcc     L20F8
231        lsr     a
232        bcs     L2107
233        cmp     #$22
234        beq     L2107
235        and     #$07
236        ora     #$80
237L20F8:  lsr     a
238        tax
239        lda     OffsetTab,x
240        bcs     L2103
241        lsr     a
242        lsr     a
243        lsr     a
244        lsr     a
245L2103:  and     #$0F
246        bne     L210B
247L2107:  ldy     #$80
248        lda     #$00
249L210B:  tax
250        lda     AdrFlagTab,x
251        sta     AdrFlagBuf
252        and     #$03
253        sta     OperandLen
254        tya
255        and     #$8F
256        tax
257        tya
258        ldy     #$03
259        cpx     #$8A
260        beq     L212B
261
262L2120:  lsr     a
263        bcc     L212B
264        lsr     a
265L2124:  lsr     a
266        ora     #$20
267        dey
268        bne     L2124
269        iny
270L212B:  dey
271        bne     L2120
272        rts
273
274; -------------------------------------------------------------------------
275; Print the mnemonic with code in A (that code was returned by
276; AnalyzeOpcode).
277
278PutMnemo:
279        tay
280        lda     MnemoTab1,y
281        sta     MnemoBuf
282        lda     MnemoTab2,y
283        sta     MnemoBuf+1
284L213A:  lda     #$00
285        ldy     #$05            ; 3*5 bits in two bytes
286L213E:  asl     MnemoBuf+1
287        rol     MnemoBuf
288        rol     a
289        dey
290        bne     L213E
291        adc     #$3F
292        jsr     PutChar
293        dex
294        bne     L213A
295        jmp     PutSpace
296
297