Merge branch 'for-2.6.28' of git://linux-nfs.org/~bfields/linux
[linux-2.6] / arch / cris / arch-v32 / kernel / kgdb_asm.S
1 /*
2  *  Copyright (C) 2004 Axis Communications AB
3  *
4  * Code for handling break 8, hardware breakpoint, single step, and serial
5  * port exceptions for kernel debugging purposes.
6  */
7
8 #include <arch/hwregs/intr_vect.h>
9
10         ;; Exported functions.
11         .globl kgdb_handle_exception
12
13 kgdb_handle_exception:
14
15 ;; Create a register image of the caller.
16 ;;
17 ;; First of all, save the ACR on the stack since we need it for address calculations.
18 ;; We put it into the register struct later.
19
20   subq     4, $sp
21   move.d   $acr, [$sp]
22
23 ;; Now we are free to use ACR all we want.
24 ;; If we were running this handler with interrupts on, we would have to be careful
25 ;; to save and restore CCS manually, but since we aren't we treat it like every other
26 ;; register.
27
28   move.d   reg,  $acr
29   move.d   $r0,  [$acr]        ; Save R0 (start of register struct)
30   addq     4,    $acr
31   move.d   $r1,  [$acr]        ; Save R1
32   addq     4,    $acr
33   move.d   $r2,  [$acr]        ; Save R2
34   addq     4,    $acr
35   move.d   $r3,  [$acr]        ; Save R3
36   addq     4,    $acr
37   move.d   $r4,  [$acr]        ; Save R4
38   addq     4,    $acr
39   move.d   $r5,  [$acr]        ; Save R5
40   addq     4,    $acr
41   move.d   $r6,  [$acr]        ; Save R6
42   addq     4,    $acr
43   move.d   $r7,  [$acr]        ; Save R7
44   addq     4,    $acr
45   move.d   $r8,  [$acr]        ; Save R8
46   addq     4,    $acr
47   move.d   $r9,  [$acr]        ; Save R9
48   addq     4,    $acr
49   move.d   $r10, [$acr]        ; Save R10
50   addq     4,    $acr
51   move.d   $r11, [$acr]        ; Save R11
52   addq     4,    $acr
53   move.d   $r12, [$acr]        ; Save R12
54   addq     4,    $acr
55   move.d   $r13, [$acr]        ; Save R13
56   addq     4,    $acr
57   move.d   $sp,  [$acr]        ; Save SP (R14)
58   addq     4,    $acr
59
60   ;; The ACR register is already saved on the stack, so pop it from there.
61   move.d   [$sp],$r0
62   move.d   $r0,  [$acr]
63   addq     4,    $acr
64
65   move     $bz,  [$acr]
66   addq     1,    $acr
67   move     $vr,  [$acr]
68   addq     1,    $acr
69   move     $pid, [$acr]
70   addq     4,    $acr
71   move     $srs, [$acr]
72   addq     1,    $acr
73   move     $wz,  [$acr]
74   addq     2,    $acr
75   move     $exs, [$acr]
76   addq     4,    $acr
77   move     $eda, [$acr]
78   addq     4,    $acr
79   move     $mof, [$acr]
80   addq     4,    $acr
81   move     $dz,  [$acr]
82   addq     4,    $acr
83   move     $ebp, [$acr]
84   addq     4,    $acr
85   move     $erp, [$acr]
86   addq     4,    $acr
87   move     $srp, [$acr]
88   addq     4,    $acr
89   move     $nrp, [$acr]
90   addq     4,    $acr
91   move     $ccs, [$acr]
92   addq     4,    $acr
93   move     $usp, [$acr]
94   addq     4,    $acr
95   move     $spc, [$acr]
96   addq     4,     $acr
97
98 ;; Skip the pseudo-PC.
99   addq     4,     $acr
100
101 ;; Save the support registers in bank 0 - 3.
102   clear.d $r1 ; Bank counter
103   move.d  sreg, $acr
104
105 ;; Bank 0
106   move    $r1,  $srs
107   nop
108   nop
109   nop
110   move    $s0,   $r0
111   move.d  $r0,   [$acr]
112   addq    4,     $acr
113   move    $s1,   $r0
114   move.d  $r0,   [$acr]
115   addq    4,     $acr
116   move    $s2,   $r0
117   move.d  $r0,   [$acr]
118   addq    4,     $acr
119   move    $s3,   $r0
120   move.d  $r0,   [$acr]
121   addq    4,     $acr
122   move    $s4,   $r0
123   move.d  $r0,   [$acr]
124   addq    4,     $acr
125   move    $s5,   $r0
126   move.d  $r0,   [$acr]
127   addq    4,     $acr
128   move    $s6,   $r0
129   move.d  $r0,   [$acr]
130   addq    4,     $acr
131   move    $s7,   $r0
132   move.d  $r0,   [$acr]
133   addq    4,     $acr
134   move    $s8,   $r0
135   move.d  $r0,   [$acr]
136   addq    4,     $acr
137   move    $s9,   $r0
138   move.d  $r0,   [$acr]
139   addq    4,     $acr
140   move    $s10,  $r0
141   move.d  $r0,   [$acr]
142   addq    4,     $acr
143   move    $s11,  $r0
144   move.d  $r0,   [$acr]
145   addq    4,     $acr
146   move    $s12,  $r0
147   move.d  $r0,   [$acr]
148   addq    4,     $acr
149
150   ;; Nothing in S13 - S15, bank 0
151   clear.d [$acr]
152   addq    4,     $acr
153   clear.d [$acr]
154   addq    4,     $acr
155   clear.d [$acr]
156   addq    4,     $acr
157
158 ;; Bank 1 and bank 2 have the same layout, hence the loop.
159   addq    1, $r1
160 1:
161   move    $r1,  $srs
162   nop
163   nop
164   nop
165   move    $s0,   $r0
166   move.d  $r0,   [$acr]
167   addq    4,     $acr
168   move    $s1,   $r0
169   move.d  $r0,   [$acr]
170   addq    4,     $acr
171   move    $s2,   $r0
172   move.d  $r0,   [$acr]
173   addq    4,     $acr
174   move    $s3,   $r0
175   move.d  $r0,   [$acr]
176   addq    4,     $acr
177   move    $s4,   $r0
178   move.d  $r0,   [$acr]
179   addq    4,     $acr
180   move    $s5,   $r0
181   move.d  $r0,   [$acr]
182   addq    4,     $acr
183   move    $s6,   $r0
184   move.d  $r0,   [$acr]
185   addq    4,     $acr
186
187   ;; Nothing in S7 - S15, bank 1 and 2
188   clear.d [$acr]
189   addq    4,     $acr
190   clear.d [$acr]
191   addq    4,     $acr
192   clear.d [$acr]
193   addq    4,     $acr
194   clear.d [$acr]
195   addq    4,     $acr
196   clear.d [$acr]
197   addq    4,     $acr
198   clear.d [$acr]
199   addq    4,     $acr
200   clear.d [$acr]
201   addq    4,     $acr
202   clear.d [$acr]
203   addq    4,     $acr
204   clear.d [$acr]
205   addq    4,     $acr
206
207   addq 1, $r1
208   cmpq 3, $r1
209   bne 1b
210   nop
211
212 ;; Bank 3
213   move    $r1,  $srs
214   nop
215   nop
216   nop
217   move    $s0,   $r0
218   move.d  $r0,   [$acr]
219   addq    4,     $acr
220   move    $s1,   $r0
221   move.d  $r0,   [$acr]
222   addq    4,     $acr
223   move    $s2,   $r0
224   move.d  $r0,   [$acr]
225   addq    4,     $acr
226   move    $s3,   $r0
227   move.d  $r0,   [$acr]
228   addq    4,     $acr
229   move    $s4,   $r0
230   move.d  $r0,   [$acr]
231   addq    4,     $acr
232   move    $s5,   $r0
233   move.d  $r0,   [$acr]
234   addq    4,     $acr
235   move    $s6,   $r0
236   move.d  $r0,   [$acr]
237   addq    4,     $acr
238   move    $s7,   $r0
239   move.d  $r0,   [$acr]
240   addq    4,     $acr
241   move    $s8,   $r0
242   move.d  $r0,   [$acr]
243   addq    4,     $acr
244   move    $s9,   $r0
245   move.d  $r0,   [$acr]
246   addq    4,     $acr
247   move    $s10,  $r0
248   move.d  $r0,   [$acr]
249   addq    4,     $acr
250   move    $s11,  $r0
251   move.d  $r0,   [$acr]
252   addq    4,     $acr
253   move    $s12,  $r0
254   move.d  $r0,   [$acr]
255   addq    4,     $acr
256   move    $s13,  $r0
257   move.d  $r0,   [$acr]
258   addq    4,     $acr
259   move    $s14,  $r0
260   move.d  $r0,   [$acr]
261   addq    4,     $acr
262 ;; Nothing in S15, bank 3
263   clear.d [$acr]
264   addq    4,     $acr
265
266 ;; Check what got us here: get IDX field of EXS.
267   move $exs,    $r10
268   and.d 0xff00, $r10
269   lsrq 8,       $r10
270 #if defined(CONFIG_ETRAX_KGDB_PORT0)
271   cmp.d SER0_INTR_VECT,   $r10 ; IRQ for serial port 0
272   beq sigint
273   nop
274 #elif defined(CONFIG_ETRAX_KGDB_PORT1)
275   cmp.d SER1_INTR_VECT,   $r10 ; IRQ for serial port 1
276   beq sigint
277   nop
278 #elif defined(CONFIG_ETRAX_KGDB_PORT2)
279   cmp.d SER2_INTR_VECT,   $r10 ; IRQ for serial port 2
280   beq sigint
281   nop
282 #elif defined(CONFIG_ETRAX_KGDB_PORT3)
283   cmp.d SER3_INTR_VECT,   $r10 ; IRQ for serial port 3
284   beq sigint
285   nop
286 #endif
287 ;; Multiple interrupt must be due to serial break.
288   cmp.d 0x30,   $r10 ; Multiple interrupt
289   beq sigint
290   nop
291 ;; Neither of those? Then it's a sigtrap.
292   ba handle_comm
293   moveq 5, $r10      ; Set SIGTRAP (delay slot)
294
295 sigint:
296   ;; Serial interrupt; get character
297   jsr getDebugChar
298   nop                ; Delay slot
299   cmp.b 3, $r10      ; \003 (Ctrl-C)?
300   bne return         ; No, get out of here
301   nop
302   moveq 2, $r10      ; Set SIGINT
303
304 ;;
305 ;; Handle the communication
306 ;;
307 handle_comm:
308   move.d   internal_stack+1020, $sp ; Use the internal stack which grows upwards
309   jsr      handle_exception         ; Interactive routine
310   nop
311
312 ;;
313 ;; Return to the caller
314 ;;
315 return:
316
317 ;; First of all, write the support registers.
318   clear.d $r1 ; Bank counter
319   move.d  sreg, $acr
320
321 ;; Bank 0
322   move    $r1,  $srs
323   nop
324   nop
325   nop
326   move.d  [$acr], $r0
327   move    $r0,    $s0
328   addq    4,      $acr
329   move.d  [$acr], $r0
330   move    $r0,    $s1
331   addq    4,      $acr
332   move.d  [$acr], $r0
333   move    $r0,    $s2
334   addq    4,      $acr
335   move.d  [$acr], $r0
336   move    $r0,    $s3
337   addq    4,      $acr
338   move.d  [$acr], $r0
339   move    $r0,    $s4
340   addq    4,      $acr
341   move.d  [$acr], $r0
342   move    $r0,    $s5
343   addq    4,      $acr
344
345 ;; Nothing in S6 - S7, bank 0.
346   addq    4,      $acr
347   addq    4,      $acr
348
349   move.d  [$acr], $r0
350   move    $r0,    $s8
351   addq    4,      $acr
352   move.d  [$acr], $r0
353   move    $r0,    $s9
354   addq    4,      $acr
355   move.d  [$acr], $r0
356   move    $r0,    $s10
357   addq    4,      $acr
358   move.d  [$acr], $r0
359   move    $r0,    $s11
360   addq    4,      $acr
361   move.d  [$acr], $r0
362   move    $r0,    $s12
363   addq    4,      $acr
364
365 ;; Nothing in S13 - S15, bank 0
366   addq    4,      $acr
367   addq    4,      $acr
368   addq    4,      $acr
369
370 ;; Bank 1 and bank 2 have the same layout, hence the loop.
371   addq    1, $r1
372 2:
373   move    $r1,  $srs
374   nop
375   nop
376   nop
377   move.d  [$acr], $r0
378   move    $r0,    $s0
379   addq    4,      $acr
380   move.d  [$acr], $r0
381   move    $r0,    $s1
382   addq    4,      $acr
383   move.d  [$acr], $r0
384   move    $r0,    $s2
385   addq    4,      $acr
386
387 ;; S3 (MM_CAUSE) is read-only.
388   addq    4,      $acr
389
390   move.d  [$acr], $r0
391   move    $r0,    $s4
392   addq    4,      $acr
393
394 ;; FIXME: Actually write S5/S6? (Affects MM_CAUSE.)
395   addq    4,      $acr
396   addq    4,      $acr
397
398 ;; Nothing in S7 - S15, bank 1 and 2
399   addq    4,      $acr
400   addq    4,      $acr
401   addq    4,      $acr
402   addq    4,      $acr
403   addq    4,      $acr
404   addq    4,      $acr
405   addq    4,      $acr
406   addq    4,      $acr
407   addq    4,      $acr
408
409   addq 1, $r1
410   cmpq 3, $r1
411   bne 2b
412   nop
413
414 ;; Bank 3
415   move    $r1,  $srs
416   nop
417   nop
418   nop
419   move.d  [$acr], $r0
420   move    $r0,    $s0
421   addq    4,      $acr
422   move.d  [$acr], $r0
423   move    $r0,    $s1
424   addq    4,      $acr
425   move.d  [$acr], $r0
426   move    $r0,    $s2
427   addq    4,      $acr
428   move.d  [$acr], $r0
429   move    $r0,    $s3
430   addq    4,      $acr
431   move.d  [$acr], $r0
432   move    $r0,    $s4
433   addq    4,      $acr
434   move.d  [$acr], $r0
435   move    $r0,    $s5
436   addq    4,      $acr
437   move.d  [$acr], $r0
438   move    $r0,    $s6
439   addq    4,      $acr
440   move.d  [$acr], $r0
441   move    $r0,    $s7
442   addq    4,      $acr
443   move.d  [$acr], $r0
444   move    $r0,    $s8
445   addq    4,      $acr
446   move.d  [$acr], $r0
447   move    $r0,    $s9
448   addq    4,      $acr
449   move.d  [$acr], $r0
450   move    $r0,    $s10
451   addq    4,      $acr
452   move.d  [$acr], $r0
453   move    $r0,    $s11
454   addq    4,      $acr
455   move.d  [$acr], $r0
456   move    $r0,    $s12
457   addq    4,      $acr
458   move.d  [$acr], $r0
459   move    $r0,    $s13
460   addq    4,      $acr
461   move.d  [$acr], $r0
462   move    $r0,    $s14
463   addq    4,      $acr
464
465 ;; Nothing in S15, bank 3
466   addq    4,      $acr
467
468 ;; Now, move on to the regular register restoration process.
469
470    move.d  reg,    $acr   ; Reset ACR to point at the beginning of the register image
471    move.d  [$acr], $r0    ; Restore R0
472    addq    4,      $acr
473    move.d  [$acr], $r1    ; Restore R1
474    addq    4,      $acr
475    move.d  [$acr], $r2    ; Restore R2
476    addq    4,      $acr
477    move.d  [$acr], $r3    ; Restore R3
478    addq    4,      $acr
479    move.d  [$acr], $r4    ; Restore R4
480    addq    4,      $acr
481    move.d  [$acr], $r5    ; Restore R5
482    addq    4,      $acr
483    move.d  [$acr], $r6    ; Restore R6
484    addq    4,      $acr
485    move.d  [$acr], $r7    ; Restore R7
486    addq    4,      $acr
487    move.d  [$acr], $r8    ; Restore R8
488    addq    4,      $acr
489    move.d  [$acr], $r9    ; Restore R9
490    addq    4,      $acr
491    move.d  [$acr], $r10   ; Restore R10
492    addq    4,      $acr
493    move.d  [$acr], $r11   ; Restore R11
494    addq    4,      $acr
495    move.d  [$acr], $r12   ; Restore R12
496    addq    4,      $acr
497    move.d  [$acr], $r13   ; Restore R13
498
499 ;;
500 ;; We restore all registers, even though some of them probably haven't changed.
501 ;;
502
503    addq    4,      $acr
504    move.d  [$acr], $sp    ; Restore SP (R14)
505
506    ;; ACR cannot be restored just yet.
507    addq    8,      $acr
508
509    ;; Skip BZ, VR.
510    addq    2,      $acr
511
512    move    [$acr], $pid   ; Restore PID
513    addq    4,      $acr
514    move    [$acr], $srs   ; Restore SRS
515    nop
516    nop
517    nop
518    addq    1,      $acr
519
520    ;; Skip WZ.
521    addq    2,      $acr
522
523    move    [$acr], $exs    ; Restore EXS.
524    addq    4,      $acr
525    move    [$acr], $eda    ; Restore EDA.
526    addq    4,      $acr
527    move    [$acr], $mof    ; Restore MOF.
528
529    ;; Skip DZ.
530    addq    8,      $acr
531
532    move    [$acr], $ebp    ; Restore EBP.
533    addq    4,      $acr
534    move    [$acr], $erp    ; Restore ERP.
535    addq    4,      $acr
536    move    [$acr], $srp    ; Restore SRP.
537    addq    4,      $acr
538    move    [$acr], $nrp    ; Restore NRP.
539    addq    4,      $acr
540    move    [$acr], $ccs    ; Restore CCS like an ordinary register.
541    addq    4,      $acr
542    move    [$acr], $usp    ; Restore USP
543    addq    4,      $acr
544    move    [$acr], $spc    ; Restore SPC
545                            ; No restoration of pseudo-PC of course.
546
547    move.d  reg,    $acr    ; Reset ACR to point at the beginning of the register image
548    add.d   15*4,   $acr
549    move.d  [$acr], $acr    ; Finally, restore ACR.
550    rete                    ; Same as jump ERP
551    rfe                     ; Shifts CCS