-
Notifications
You must be signed in to change notification settings - Fork 425
/
dbgsupp.s
203 lines (164 loc) · 4.72 KB
/
dbgsupp.s
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
;
; Ullrich von Bassewitz, 08.08.1998
;
; Support routines for the debugger
;
.export _DbgInit
.export _DbgSP, _DbgCS, _DbgHI
.import popptr1, return0, _DbgEntry, _set_brk, _end_brk
.import _DbgBreaks
.import _brk_pc
.import __ZP_START__ ; Linker generated
.include "zeropage.inc"
; C callable function, will install the debugger
_DbgInit:
lda #<DbgBreak
ldx #>DbgBreak
jmp _set_brk
; Entry for the break vector.
DbgBreak:
pla
sta retsav
pla
sta retsav+1
cli
tsx ; Stack pointer
stx _DbgSP
jsr DbgSwapZP ; Swap stuff
lda #<DbgStack ; Set new stack
sta sp
lda #>DbgStack
sta sp+1
jsr ResetDbgBreaks ; Reset temporary breakpoints
jsr _DbgEntry ; Call C code
jsr SetDbgBreaks ; Set temporary breakpoints
jsr DbgSwapZP ; Swap stuff back
lda retsav+1
pha
lda retsav
pha
rts
; Stack used when in debugger mode
.bss
.res 256
DbgStack:
; Swap space for the C temporaries
CTemp:
_DbgCS: .res 2 ; sp
_DbgHI: .res 2 ; sreg
.res (zpsavespace-4) ; Other stuff
_DbgSP: .res 1
retsav: .res 2 ; Save buffer for return address
.code
; Swap the C temporaries
DbgSwapZP:
ldy #zpsavespace-1
Swap1: ldx CTemp,y
lda <__ZP_START__,y
sta CTemp,y
txa
sta sp,y
dey
bpl Swap1
rts
; ----------------------------------------------------------------------------
; Utility functions
; Set/reset the breakpoints. We must do that here since the breakpoints
; may be in the runtime stuff, causing the C part to fail before it has
; reset the breakpoints. See declaration of struct breakpoint in the C
; source
MaxBreaks = 48 ; 4*12
ResetDbgBreaks:
ldy #0
ldx #0
L4: lda _DbgBreaks+3,x ; Get bk_use
beq L6 ; Jump if not set
bpl L5 ; Jump if user breakpoint
lda #0
sta _DbgBreaks+3,x ; Clear if temp breakpoint
L5: lda _DbgBreaks+1,x ; PC hi
sta ptr1+1
lda _DbgBreaks,x ; PC lo
sta ptr1
lda _DbgBreaks+2,x ; Old OPC
sta (ptr1),y ; Reset the breakpoint
L6: inx
inx
inx
inx
cpx #MaxBreaks ; Done?
bne L4
rts
SetDbgBreaks:
ldx #0
ldy #0
L7: lda _DbgBreaks+3,x ; Get bk_use
beq L8 ; Jump if not set
lda _DbgBreaks+1,x ; PC hi
sta ptr1+1
lda _DbgBreaks,x ; PC lo
sta ptr1
lda (ptr1),y ; Get the breakpoint OPC...
sta _DbgBreaks+2,x ; ...and save it
lda #$00 ; Load BRK opcode
sta (ptr1),y
L8: inx
inx
inx
inx
cpx #MaxBreaks ; Done?
bne L7
rts
; Get a free breakpoint slot or return 0
.export _DbgGetBreakSlot
_DbgGetBreakSlot:
ldx #0
L10: lda _DbgBreaks+3,x ; Get bk_use
beq L11 ; Jump if not set
inx
inx
inx
inx
cpx #MaxBreaks ; Done?
bne L10
jmp return0 ; No free slot
L11: stx tmp1
lda #<_DbgBreaks
ldx #>_DbgBreaks
clc
adc tmp1
bcc L12
inx
L12: ldy #1 ; Force != 0
rts
; Check if a given address has a user breakpoint set, if found, return the
; slot, otherwise return 0.
.export _DbgIsBreak
_DbgIsBreak:
jsr popptr1 ; Get address
ldx #0
L20: lda _DbgBreaks+3,x ; Get bk_use
beq L21 ; Jump if not set
bmi L21 ; Jump if temp breakpoint
lda _DbgBreaks,x ; Low byte of address
cmp ptr1
bne L21
lda _DbgBreaks+1,x ; High byte of address
cmp ptr1+1
beq L22
L21: inx
inx
inx
inx
cpx #MaxBreaks ; Done?
bne L20
jmp return0 ; Not found
L22: stx tmp1
lda #<_DbgBreaks
ldx #>_DbgBreaks
clc
adc tmp1
bcc L23
inx
L23: ldy #1 ; Force != 0
rts