backtrace.S 3.7 KB

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