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