File: dbgdasm.s

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (296 lines) | stat: -rw-r--r-- 7,866 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
;
; Ullrich von Bassewitz, 07.08.1998
;
; unsigned DbgDisAsm (char* buf, unsigned addr);
; unsigned DbgDisAsm (unsigned addr);
;
;
; Part of this code is taken from the Plus/4 machine language monitor
; (TEDMon).
;

        .import         popax
        .import         __hextab, OffsetTab, AdrFlagTab
        .import         SymbolTab1, SymbolTab2, MnemoTab1, MnemoTab2



; -------------------------------------------------------------------------
; Equates for better readability

        .importzp       sreg, tmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3

BufIndex        = tmp1          ; Index into output buffer
OperandLen      = tmp2          ; Length of operand
BufLen          = tmp3          ; Length of output buffer
AdrFlagBuf      = tmp4          ; Flag for addressing mode
YSave           = sreg          ; Temp storage
XSave           = sreg+1        ; Dito
BufPtr          = ptr1          ; Pointer to output buffer
MemPtr          = ptr2          ; Pointer to memory to disassemble
MnemoBuf        = ptr3          ; Buffer for decoding mnemonic


; -------------------------------------------------------------------------
; Main entries

        .export         _DbgDisAsm, _DbgDisAsmLen

.proc   _DbgDisAsm
        sta     BufLen          ; Save the buffer length
        jsr     popax           ; Get the buffer pointer
        sta     BufPtr
        stx     BufPtr+1
        jsr     popax           ; Get the address
        sta     MemPtr
        stx     MemPtr+1
        lda     #0
        sta     BufIndex        ; Initialize index into buffer
        jsr     DisAssLine      ; Disassemble one line into the buffer

        lda     BufLen          ; Get requested length
        sec
        sbc     BufIndex
        beq     L2
        tax                     ; Count into X
        ldy     BufIndex
        lda     #$20            ; Get a space
L1:     sta     (BufPtr),y
        iny
        dex
        bne     L1
L2:     lda     #0              ; Add C string terminator
        sta     (BufPtr),y
        beq     disassret

.endproc


_DbgDisAsmLen:
        sta     MemPtr          ; Save address
        stx     MemPtr+1
        ldy     #$00
        lda     (MemPtr),y      ; Get the opcode from memory...
        jsr     AnalyzeOPCode   ; ...and analyze it
disassret:
        ldx     OperandLen      ; Get length of operand
        inx                     ; Adjust for opcode byte
        txa
        ldx     #$00            ; Clear high byte
        rts     

; -------------------------------------------------------------------------
; Helper functions


Put3Spaces:
        jsr     PutSpace
Put2Spaces:
        jsr     PutSpace
PutSpace:
        lda     #$20
PutChar:
        sty     YSave           ; Save Y
        ldy     BufIndex        ; Get current line pointer
        cpy     BufLen          ; Be sure not to overflow the buffer
        bcs     PC9
        sta     (BufPtr),y      ; store character
        iny                     ; bump index
        sty     BufIndex
PC9:    ldy     YSave           ; get old value
        rts

; Print the 16 bit hex value in X/Y

PutHex16:
        txa
        jsr     PutHex8
        tya

; Print 8 bit value in A, save X and Y

PutHex8:
        stx     XSave
        sty     YSave
        ldy     BufIndex
        pha
        lsr     a
        lsr     a
        lsr     a
        lsr     a
        tax
        lda     __hextab,x
        sta     (BufPtr),y
        iny
        pla
        and     #$0F
        tax
        lda     __hextab,x
        sta     (BufPtr),y
        iny
        sty     BufIndex
        ldy     YSave
        ldx     XSave
        rts

; -------------------------------------------------------------------------
; Disassemble one line

DisAssLine:
        ldy     MemPtr
        ldx     MemPtr+1
        jsr     PutHex16                ; Print the address
        jsr     Put2Spaces              ; Add some space
        ldy     #$00
        lda     (MemPtr),y              ; Get the opcode from memory...
        jsr     AnalyzeOPCode           ; ...and analyze it
        pha                             ; Save mnemonic
        ldx     OperandLen              ; Number of bytes

; Print the bytes that make up the instruction

        inx
L2083:  dex
        bpl     L208C                   ; Print the instruction bytes
        jsr     Put3Spaces              ; If none left, print spaces instead
        jmp     L2094
L208C:  lda     (MemPtr),y              ; Get a byte from memory
        jsr     PutHex8                 ; ...and print it
        jsr     PutSpace                ; Add some space

L2094:  iny                             ; Next one...
        cpy     #$03                    ; Maximum is three
        bcc     L2083                   ;

        jsr     Put2Spaces              ; Add some space after bytes

; Print the assembler mnemonic

        pla                             ; Get mnemonic code
        ldx     #$03
        jsr     PutMnemo                ; Print the mnemonic
        ldx     #$06

; Print the operand

L20A4:  cpx     #$03
        bne     L20BA
        ldy     OperandLen
        beq     L20BA

L20AC:  lda     AdrFlagBuf
        cmp     #$E8                    ; Branch?
        lda     (MemPtr),y              ; Get branch offset
        bcs     GetBranchAdr            ; If branch: Calculate address
        jsr     PutHex8                 ; Otherwise print 8bit value
        dey
        bne     L20AC

L20BA:  asl     AdrFlagBuf
        bcc     L20CC
        lda     SymbolTab1-1,x
        jsr     PutChar
        lda     SymbolTab2-1,x
        beq     L20CC
        jsr     PutChar

L20CC:  dex
        bne     L20A4
        rts

; If the instruction is a branch, calculate the absolute address of the
; branch target and print it.

GetBranchAdr:
        jsr     L20DD
        clc
        adc     #$01
        bne     L20D9
        inx                             ; Bump high byte
L20D9:  tay
        jmp     PutHex16                ; Output address

L20DD:  ldx     MemPtr+1
        tay
        bpl     L20E3
        dex
L20E3:  adc     MemPtr
        bcc     L20E8
        inx                             ; Bump high byte
L20E8:  rts

; -------------------------------------------------------------------------
; Subroutine to analyze an opcode byte in A. Will return a byte that
; encodes the mnemonic, and will set the number of bytes needed for this
; instruction in OperandLen

AnalyzeOPCode:
        tay
        lsr     a
        bcc     L20F8
        lsr     a
        bcs     L2107
        cmp     #$22
        beq     L2107
        and     #$07
        ora     #$80
L20F8:  lsr     a
        tax
        lda     OffsetTab,x
        bcs     L2103
        lsr     a
        lsr     a
        lsr     a
        lsr     a
L2103:  and     #$0F
        bne     L210B
L2107:  ldy     #$80
        lda     #$00
L210B:  tax
        lda     AdrFlagTab,x
        sta     AdrFlagBuf
        and     #$03
        sta     OperandLen
        tya
        and     #$8F
        tax
        tya
        ldy     #$03
        cpx     #$8A
        beq     L212B

L2120:  lsr     a
        bcc     L212B
        lsr     a
L2124:  lsr     a
        ora     #$20
        dey
        bne     L2124
        iny
L212B:  dey
        bne     L2120
        rts

; -------------------------------------------------------------------------
; Print the mnemonic with code in A (that code was returned by
; AnalyzeOpcode).

PutMnemo:
        tay
        lda     MnemoTab1,y
        sta     MnemoBuf
        lda     MnemoTab2,y
        sta     MnemoBuf+1
L213A:  lda     #$00
        ldy     #$05            ; 3*5 bits in two bytes
L213E:  asl     MnemoBuf+1
        rol     MnemoBuf
        rol     a
        dey
        bne     L213E
        adc     #$3F
        jsr     PutChar
        dex
        bne     L213A
        jmp     PutSpace