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