Linux 3.8-rc7
[cris-mirror.git] / arch / unicore32 / lib / backtrace.S
blobef01d77f2f65909309467d573688e8fb719cf957
1 /*
2  * linux/arch/unicore32/lib/backtrace.S
3  *
4  * Code specific to PKUnity SoC and UniCore ISA
5  *
6  * Copyright (C) 2001-2010 GUAN Xue-tao
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 #include <linux/linkage.h>
13 #include <asm/assembler.h>
14                 .text
16 @ fp is 0 or stack frame
18 #define frame   v4
19 #define sv_fp   v5
20 #define sv_pc   v6
21 #define offset  v8
23 ENTRY(__backtrace)
24                 mov     r0, fp
26 ENTRY(c_backtrace)
28 #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
29                 mov     pc, lr
30 ENDPROC(__backtrace)
31 ENDPROC(c_backtrace)
32 #else
33                 stm.w   (v4 - v8, lr), [sp-]    @ Save an extra register
34                                                 @ so we have a location...
35                 mov.a   frame, r0               @ if frame pointer is zero
36                 beq     no_frame                @ we have no stack frames
38 1:              stm.w   (pc), [sp-]             @ calculate offset of PC stored
39                 ldw.w   r0, [sp]+, #4           @ by stmfd for this CPU
40                 adr     r1, 1b
41                 sub     offset, r0, r1
44  * Stack frame layout:
45  *             optionally saved caller registers (r4 - r10)
46  *             saved fp
47  *             saved sp
48  *             saved lr
49  *    frame => saved pc
50  *             optionally saved arguments (r0 - r3)
51  * saved sp => <next word>
52  *
53  * Functions start with the following code sequence:
54  *                  mov   ip, sp
55  *                  stm.w (r0 - r3), [sp-] (optional)
56  * corrected pc =>  stm.w sp, (..., fp, ip, lr, pc)
57  */
58 for_each_frame:
60 1001:           ldw     sv_pc, [frame+], #0     @ get saved pc
61 1002:           ldw     sv_fp, [frame+], #-12   @ get saved fp
63                 sub     sv_pc, sv_pc, offset    @ Correct PC for prefetching
65 1003:           ldw     r2, [sv_pc+], #-4       @ if stmfd sp, {args} exists,
66                 ldw     r3, .Ldsi+4             @ adjust saved 'pc' back one
67                 cxor.a  r3, r2 >> #14           @ instruction
68                 beq     201f
69                 sub     r0, sv_pc, #4           @ allow for mov
70                 b       202f
71 201:
72                 sub     r0, sv_pc, #8           @ allow for mov + stmia
73 202:
74                 ldw     r1, [frame+], #-4       @ get saved lr
75                 mov     r2, frame
76                 b.l     dump_backtrace_entry
78                 ldw     r1, [sv_pc+], #-4       @ if stmfd sp, {args} exists,
79                 ldw     r3, .Ldsi+4
80                 cxor.a  r3, r1 >> #14
81                 bne     1004f
82                 ldw     r0, [frame+], #-8       @ get sp
83                 sub     r0, r0, #4              @ point at the last arg
84                 b.l     .Ldumpstm               @ dump saved registers
86 1004:           ldw     r1, [sv_pc+], #0        @ if stmfd {, fp, ip, lr, pc}
87                 ldw     r3, .Ldsi               @ instruction exists,
88                 cxor.a  r3, r1 >> #14
89                 bne     201f
90                 sub     r0, frame, #16
91                 b.l     .Ldumpstm               @ dump saved registers
92 201:
93                 cxor.a  sv_fp, #0               @ zero saved fp means
94                 beq     no_frame                @ no further frames
96                 csub.a  sv_fp, frame            @ next frame must be
97                 mov     frame, sv_fp            @ above the current frame
98                 bua     for_each_frame
100 1006:           adr     r0, .Lbad
101                 mov     r1, frame
102                 b.l     printk
103 no_frame:       ldm.w   (v4 - v8, pc), [sp]+
104 ENDPROC(__backtrace)
105 ENDPROC(c_backtrace)
107                 .pushsection __ex_table,"a"
108                 .align  3
109                 .long   1001b, 1006b
110                 .long   1002b, 1006b
111                 .long   1003b, 1006b
112                 .long   1004b, 1006b
113                 .popsection
115 #define instr v4
116 #define reg   v5
117 #define stack v6
119 .Ldumpstm:      stm.w   (instr, reg, stack, v7, lr), [sp-]
120                 mov     stack, r0
121                 mov     instr, r1
122                 mov     reg, #14
123                 mov     v7, #0
124 1:              mov     r3, #1
125                 csub.a  reg, #8
126                 bne     201f
127                 sub     reg, reg, #3
128 201:
129                 cand.a  instr, r3 << reg
130                 beq     2f
131                 add     v7, v7, #1
132                 cxor.a  v7, #6
133                 cmoveq  v7, #1
134                 cmoveq  r1, #'\n'
135                 cmovne  r1, #' '
136                 ldw.w   r3, [stack]+, #-4
137                 mov     r2, reg
138                 csub.a  r2, #8
139                 bsl     201f
140                 sub     r2, r2, #3
141 201:
142                 cand.a  instr, #0x40            @ if H is 1, high 16 regs
143                 beq     201f
144                 add     r2, r2, #0x10           @ so r2 need add 16
145 201:
146                 adr     r0, .Lfp
147                 b.l     printk
148 2:              sub.a   reg, reg, #1
149                 bns     1b
150                 cxor.a  v7, #0
151                 beq     201f
152                 adr     r0, .Lcr
153                 b.l     printk
154 201:            ldm.w   (instr, reg, stack, v7, pc), [sp]+
156 .Lfp:           .asciz  "%cr%d:%08x"
157 .Lcr:           .asciz  "\n"
158 .Lbad:          .asciz  "Backtrace aborted due to bad frame pointer <%p>\n"
159                 .align
160 .Ldsi:          .word   0x92eec000 >> 14        @ stm.w sp, (... fp, ip, lr, pc)
161                 .word   0x92e10000 >> 14        @ stm.w sp, ()
163 #endif