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