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 15 16@ fp is 0 or stack frame 17 18#define frame v4 19#define sv_fp v5 20#define sv_pc v6 21#define offset v8 22 23ENTRY(__backtrace) 24 mov r0, fp 25 26ENTRY(c_backtrace) 27 28#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK) 29 mov pc, lr 30ENDPROC(__backtrace) 31ENDPROC(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 37 381: 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 42 43/* 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 */ 58for_each_frame: 59 601001: ldw sv_pc, [frame+], #0 @ get saved pc 611002: ldw sv_fp, [frame+], #-12 @ get saved fp 62 63 sub sv_pc, sv_pc, offset @ Correct PC for prefetching 64 651003: 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 71201: 72 sub r0, sv_pc, #8 @ allow for mov + stmia 73202: 74 ldw r1, [frame+], #-4 @ get saved lr 75 mov r2, frame 76 b.l dump_backtrace_entry 77 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 85 861004: 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 92201: 93 cxor.a sv_fp, #0 @ zero saved fp means 94 beq no_frame @ no further frames 95 96 csub.a sv_fp, frame @ next frame must be 97 mov frame, sv_fp @ above the current frame 98 bua for_each_frame 99 1001006: adr r0, .Lbad 101 mov r1, frame 102 b.l printk 103no_frame: ldm.w (v4 - v8, pc), [sp]+ 104ENDPROC(__backtrace) 105ENDPROC(c_backtrace) 106 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 114 115#define instr v4 116#define reg v5 117#define stack v6 118 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 1241: mov r3, #1 125 csub.a reg, #8 126 bne 201f 127 sub reg, reg, #3 128201: 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 141201: 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 145201: 146 adr r0, .Lfp 147 b.l printk 1482: sub.a reg, reg, #1 149 bns 1b 150 cxor.a v7, #0 151 beq 201f 152 adr r0, .Lcr 153 b.l printk 154201: ldm.w (instr, reg, stack, v7, pc), [sp]+ 155 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, () 162 163#endif 164