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