Merge ../scsi-misc-2.6
[linux-2.6] / arch / arm26 / lib / backtrace.S
1 /*
2  *  linux/arch/arm26/lib/backtrace.S
3  *
4  *  Copyright (C) 1995, 1996 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 #include <linux/linkage.h>
11 #include <asm/assembler.h>
12                 .text
13
14 @ fp is 0 or stack frame
15
16 #define frame   r4
17 #define next    r5
18 #define save    r6
19 #define mask    r7
20 #define offset  r8
21
22 ENTRY(__backtrace)
23                 mov     r1, #0x10
24                 mov     r0, fp
25
26 ENTRY(c_backtrace)
27
28 #ifdef CONFIG_NO_FRAME_POINTER
29                 mov     pc, lr
30 #else
31
32                 stmfd   sp!, {r4 - r8, lr}      @ Save an extra register so we have a location...
33                 mov     mask, #0xfc000003
34                 tst     mask, r0
35                 movne   r0, #0
36                 movs    frame, r0
37 1:              moveq   r0, #-2
38                 LOADREGS(eqfd, sp!, {r4 - r8, pc})
39
40 2:              stmfd   sp!, {pc}               @ calculate offset of PC in STMIA instruction
41                 ldr     r0, [sp], #4
42                 adr     r1, 2b - 4
43                 sub     offset, r0, r1
44
45 3:              tst     frame, mask             @ Check for address exceptions...
46                 bne     1b
47
48 1001:           ldr     next, [frame, #-12]     @ get fp
49 1002:           ldr     r2, [frame, #-4]        @ get lr
50 1003:           ldr     r3, [frame, #0]         @ get pc
51                 sub     save, r3, offset        @ Correct PC for prefetching
52                 bic     save, save, mask
53 1004:           ldr     r1, [save, #0]          @ get instruction at function
54                 mov     r1, r1, lsr #10
55                 ldr     r3, .Ldsi+4
56                 teq     r1, r3
57                 subeq   save, save, #4
58                 adr     r0, .Lfe
59                 mov     r1, save
60                 bic     r2, r2, mask
61                 bl      printk                  @ print pc and link register
62
63                 ldr     r0, [frame, #-8]        @ get sp
64                 sub     r0, r0, #4
65 1005:           ldr     r1, [save, #4]          @ get instruction at function+4
66                 mov     r3, r1, lsr #10
67                 ldr     r2, .Ldsi+4
68                 teq     r3, r2                  @ Check for stmia sp!, {args}
69                 addeq   save, save, #4          @ next instruction
70                 bleq    .Ldumpstm
71
72                 sub     r0, frame, #16
73 1006:           ldr     r1, [save, #4]          @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction
74                 mov     r3, r1, lsr #10
75                 ldr     r2, .Ldsi
76                 teq     r3, r2
77                 bleq    .Ldumpstm
78
79                 teq     frame, next
80                 movne   frame, next
81                 teqne   frame, #0
82                 bne     3b
83                 LOADREGS(fd, sp!, {r4 - r8, pc})
84
85 /*
86  * Fixup for LDMDB
87  */
88                 .section .fixup,"ax"
89                 .align  0
90 1007:           ldr     r0, =.Lbad
91                 mov     r1, frame
92                 bl      printk
93                 LOADREGS(fd, sp!, {r4 - r8, pc})
94                 .ltorg
95                 .previous
96                 
97                 .section __ex_table,"a"
98                 .align  3
99                 .long   1001b, 1007b
100                 .long   1002b, 1007b
101                 .long   1003b, 1007b
102                 .long   1004b, 1007b
103                 .long   1005b, 1007b
104                 .long   1006b, 1007b
105                 .previous
106
107 #define instr r4
108 #define reg   r5
109 #define stack r6
110
111 .Ldumpstm:      stmfd   sp!, {instr, reg, stack, r7, lr}
112                 mov     stack, r0
113                 mov     instr, r1
114                 mov     reg, #9
115                 mov     r7, #0
116 1:              mov     r3, #1
117                 tst     instr, r3, lsl reg
118                 beq     2f
119                 add     r7, r7, #1
120                 teq     r7, #4
121                 moveq   r7, #0
122                 moveq   r3, #'\n'
123                 movne   r3, #' '
124                 ldr     r2, [stack], #-4
125                 mov     r1, reg
126                 adr     r0, .Lfp
127                 bl      printk
128 2:              subs    reg, reg, #1
129                 bpl     1b
130                 teq     r7, #0
131                 adrne   r0, .Lcr
132                 blne    printk
133                 mov     r0, stack
134                 LOADREGS(fd, sp!, {instr, reg, stack, r7, pc})
135
136 .Lfe:           .asciz  "Function entered at [<%p>] from [<%p>]\n"
137 .Lfp:           .asciz  " r%d = %08X%c"
138 .Lcr:           .asciz  "\n"
139 .Lbad:          .asciz  "Backtrace aborted due to bad frame pointer <%p>\n"
140                 .align
141 .Ldsi:          .word   0x00e92dd8 >> 2
142                 .word   0x00e92d00 >> 2
143
144 #endif