Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / fm / lib / breakpt.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: breakpt.fth
4\
5\ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6\
7\ - Do no alter or remove copyright notices
8\
9\ - Redistribution and use of this software in source and binary forms, with
10\ or without modification, are permitted provided that the following
11\ conditions are met:
12\
13\ - Redistribution of source code must retain the above copyright notice,
14\ this list of conditions and the following disclaimer.
15\
16\ - Redistribution in binary form must reproduce the above copyright notice,
17\ this list of conditions and the following disclaimer in the
18\ documentation and/or other materials provided with the distribution.
19\
20\ Neither the name of Sun Microsystems, Inc. or the names of contributors
21\ may be used to endorse or promote products derived from this software
22\ without specific prior written permission.
23\
24\ This software is provided "AS IS," without a warranty of any kind.
25\ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
26\ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
27\ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
28\ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
29\ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
30\ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
31\ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
32\ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
33\ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
34\ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
35\ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
36\
37\ You acknowledge that this software is not designed, licensed or
38\ intended for use in the design, construction, operation or maintenance of
39\ any nuclear facility.
40\
41\ ========== Copyright Header End ============================================
42\ breakpt.fth 2.15 01/05/18
43\ Copyright 1985-1990 Bradley Forthware
44\ Copyright 1990-2001 Sun Microsystems, Inc. All Rights Reserved
45
46\ Assembly language breakpoints
47\
48\ Files needed:
49\
50\ objects.fth Defining words for multiple code field words
51\ registers.fth Defines the register save area.
52\ CPU dependent
53\ catchexc.fth Saves the machine state in the register save area.
54\ CPU & operating system dependent
55\ machdep.fth Defines CPU-dependent words for placing breakpoints
56\ and finding the next instruction.
57\ CPU-dependent
58\ breakpt.fth (This file) Manages the list of breakpoints, handles
59\ single-stepping. Machine-independent
60
61needs array array.fth
62
63only forth also hidden also
64forth definitions
65
66decimal
67
68\ Moved to cpustate.fth
69\ nuser restartable? restartable? off
70
71defer restart ( -- )
72defer restart-step ( -- )
73
74hidden definitions
75
76headerless
77
7820 constant max#breakpoints
79max#breakpoints array >breakpoint
80max#breakpoints array >breakpoint-action
81max#breakpoints array >saved-opcode
82
832 array >step-breakpoint
842 array >step-saved-opcode
85variable #breakpoints
86variable #steps
87variable pc-at-breakpoint
88variable pc-at-step
89variable breakpoints-installed
90
91: init-breakpoints ( -- )
92 #steps off
93 #breakpoints off
94 0 >step-breakpoint off
95 1 >step-breakpoint off
96 breakpoints-installed off
97;
98
99\ Search the breakpoint table to see if adr is breakpointed.
100\ If it is, return the index into the table, or -1 if it's not there.
101: find-breakpoint ( adr -- breakpoint#|-1 )
102 -1 swap
103 #breakpoints @ 0
104 ?do
105 dup i >breakpoint @ =
106 if nip i swap leave then
107 loop ( breakpoint# | -1 )
108 drop
109;
110\ Enter a breakpoint at addr. If adr is already breakpointed,
111\ don't enter it twice.
112: set-breakpoint ( adr -- )
113 dup find-breakpoint ( adr breakpoint# )
114 0< if
115 dup ( adr adr )
116 #breakpoints @ max#breakpoints >= abort" Too many breakpoints"
117 #breakpoints @ 1 #breakpoints +! ( adr breakpoint# )
118 >breakpoint !
119 then ( adr )
120 \ Set default action to be .breakpoint
121 0 swap find-breakpoint >breakpoint-action !
122;
123\ Display the breakpoint table.
124: show-breakpoints ( -- )
125 #breakpoints @ 0 ?do
126 i >breakpoint @ u.
127 i >breakpoint-action @ ?dup if ." { " >name .id ." } " then
128 loop
129;
130\ If the breakpoint is installed in memory, take it out.
131: repair-breakpoint ( breakpoint# -- )
132 dup >breakpoint @ at-breakpoint?
133 if dup >saved-opcode @ over >breakpoint @ op! then
134 drop
135;
136
137\ Remove the breakpoint at adr from the table, if it's there.
138: remove-breakpoint ( adr -- )
139 find-breakpoint ( breakpoint# )
140 dup 0< ( breakpoint# flag )
141 if drop
142 else ( breakpoint# )
143 dup repair-breakpoint
144 \ Shuffle the remaining breakpoints down to fill the vacated slot
145 #breakpoints @ swap 1+ ( last-breakpoint# breakpoint# )
146 ?do
147 i >breakpoint @ i 1- >breakpoint !
148 i >breakpoint-action @ i 1- >breakpoint-action !
149 loop
150 -1 #breakpoints +!
151 then
152;
153
154\ When we restart the program, we have to put breakpoints at all the
155\ places in the breakpoint list. If there is a breakpoint at the
156\ current PC, we have to temporarily not put one there, because we
157\ want to execute it at least once (presumably we just hit it).
158\ So we have to single step by putting breakpoints at the next instruction,
159\ then when we hit that instruction, we put the breakpoint at the previous
160\ place. In fact, the "next instruction" may actually be 2 instructions
161\ because the current instruction could be a branch.
162
163: install-breakpoints ( -- )
164 breakpoints-installed @ if exit then
165 breakpoints-installed on
166 #breakpoints @ 0 ?do
167 i >breakpoint @ ( breakpoint-adr )
168 dup op@ ( adr opcode )
169 over at-breakpoint? 0= if ( adr opcode )
170 i >saved-opcode ! ( breakpoint-adr )
171 put-breakpoint
172 else
173 2drop
174 then
175 loop
176;
177: repair-breakpoints ( -- )
178 #breakpoints @ 0 ?do i repair-breakpoint loop
179 breakpoints-installed off
180;
181
182\ Single stepping:
183\ To single step, we have to breakpoint the instruction just after the
184\ current instruction. If that instruction is a conditional branch, we
185\ have to breakpoint both the next instruction and the branch target.
186\ The machine-dependent next-instruction routine finds the next instruction
187\ and the branch target.
188
189variable following-jsrs?
190: set-step-breakpoints ( -- )
191 following-jsrs? @ next-instruction ( next-adr branch-target|0 )
192 swap ( step-breakpoint-adr0 step-breakpoint-adr1 )
193 2 0 do
194 dup i >step-breakpoint ! ( step-breakpoint-adr )
195 ?dup if ( step-breakpoint-adr )
196 dup op@ i >step-saved-opcode ! ( step-breakpoint-adr )
197 put-breakpoint
198 then
199 loop
200;
201: repair-step-breakpoints ( -- )
202 2 0 do
203 i >step-breakpoint @ ?dup if ( step-breakpoint-adr )
204 at-breakpoint?
205 if i >step-saved-opcode @ i >step-breakpoint @ op! then
206 0 i >step-breakpoint !
207 then
208 loop
209;
210: remove-all-breakpoints ( -- )
211 repair-breakpoints repair-step-breakpoints #breakpoints off
212;
213: uninstall-breakpoints ( -- )
214 breakpoints-installed @ if
215 remove-all-breakpoints
216 then
217;
218
219: current-address-breakpointed? ( -- flag )
220 rpc find-breakpoint 0>=
221;
222: current-address-stepped? ( -- flag )
223 rpc 0 >step-breakpoint @ =
224 rpc 1 >step-breakpoint @ = or
225;
226
227: ?restart-ok ( -- ) restartable? @ 0= abort" No program is active." ;
228
229: (step ( -- ) set-step-breakpoints ?restart-ok restart-step ;
230headers
231
232forth definitions
233chain: go-chain
234 \ Put stuff to do before returning to a client in this chain.
235;
236defer go-hook ' go-chain is go-hook
237\ : breakpoint-go ( -- ) install-breakpoints restart ;
238: steps ( n -- ) #steps ! following-jsrs? on (step ;
239: step ( -- ) 1 steps ;
240: hops ( n -- ) #steps ! following-jsrs? off (step ;
241: hop ( -- ) 1 hops ;
242: go ( -- )
243 go-hook ?restart-ok #steps off
244 current-address-breakpointed?
245 if following-jsrs? on (step else install-breakpoints restart then
246;
247
248: +bp ( adr -- )
249 uninstall-breakpoints
250 dup
251 bp-address-valid? if
252 set-breakpoint
253 else
254 ." Invalid breakpoint address " .x cr
255 then
256;
257
258: +bpx ( adr -- ) \ name
259 ' over +bp ( adr acf )
260 swap find-breakpoint ( acf bp# | -1 )
261 dup 0< if ( acf -1 )
262 2drop ( )
263 else ( acf bp# )
264 >breakpoint-action ! ( )
265 then
266;
267
268: till ( adr -- ) +bp go ;
269: return ( -- ) return-adr till ; \ Finish and return from subroutine
270: returnl ( -- ) leaf-return-adr till ; \ Finish and ret. from leaf subr.
271: finish-loop ( -- ) loop-exit-adr till ; \ Finish the enclosing loop
272
273headerless
274alias continue go
275variable #gos
276
277headers
278: gos ( n -- ) 1- #gos ! go ;
279
280: .pc ( -- ) rpc u. ;
281defer .step
282defer .breakpoint
283
284headerless
285hidden definitions
286' .instruction is .step
287' .instruction is .breakpoint
288: breakpoint-message ( -- )
289
290 \ If the trap type is inconsistent with a breakpoint, then we
291 \ just print the exception type and exit.
292
293 breakpoint-trap? 0= if .exception quit then \ Exit to interpreter
294
295 \ If we are doing multiple single-steps, then we decrement the
296 \ step count and continue stepping until the count reaches 0.
297
298 #steps @ if
299 restartable? on
300 .step
301 -1 #steps +! #steps @ if (step then \ Exit to program
302 quit \ Exit to interpreter
303 then
304
305 \ If we are at a single-step location, but the step count variable was 0,
306 \ then it was a "hidden step". A "hidden step" happens when "go" is
307 \ executed from a location where there is a breakpoint set. We had to
308 \ step once to execute the breakpointed instruction, and then we replace
309 \ the location with a breakpoint insruction and go.
310
311 pc-at-step @ if restartable? on go then \ Exit to program
312
313 \ If we are at a breakpoint location, then we consult the #gos variable
314 \ to determine how many more times to go, and either go or "quit" to
315 \ the interactive interpreter.
316
317 pc-at-breakpoint @ if
318 restartable? on
319 rpc find-breakpoint >breakpoint-action @ ?dup if
320 execute
321 else
322 .breakpoint
323 then
324 #gos @ if -1 #gos +! go then \ Exit to program
325 quit \ Exit to interpreter
326 then
327
328 \ If we get here, a "breakpoint trap" occurred at a location where
329 \ we don't think there should have been a breakpoint. This means
330 \ that the location happens to contain an instruction that causes the
331 \ same kind of trap that is used for breakpoints (whatever that is for
332 \ the particular system). This could happen if a previous breakpoint
333 \ didn't get cleaned up properly, or if memory got overwritten with
334 \ breakpoint (or equivalent) instructions, or if the program jumped to
335 \ an invalid location that happened to contain breakpoint (or equivalent)
336 \ instructions.
337
338 .exception quit \ Exit to interpreter
339;
340headers
341: (handle-breakpoint ( -- )
342 current-address-stepped? pc-at-step !
343 current-address-breakpointed? pc-at-breakpoint !
344 repair-step-breakpoints
345 repair-breakpoints
346
347 breakpoint-message
348;
349' (handle-breakpoint is handle-breakpoint
350
351forth definitions
352
353: -bp ( adr -- )
354 uninstall-breakpoints
355 remove-breakpoint
356;
357\ Remove most-recently-set breakpoint
358: --bp ( -- )
359 #breakpoints @ if
360 #breakpoints @ 1- repair-breakpoint
361 -1 #breakpoints +!
362 then
363;
364: bpon ( -- )
365 uninstall-breakpoints
366 install-breakpoints
367;
368: .bp ( -- ) show-breakpoints ;
369: bpoff ( -- ) remove-all-breakpoints ;
370: skip ( -- ) bumppc go ;
371
372chain: init ( -- ) init-breakpoints ;
373
374init-breakpoints
375
376also keys-forth definitions
377: ^t step ;
378only forth also definitions