exception.s 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*****************************************************************
  2. * exception.s
  3. * by Zhiyi Huang, [email protected]
  4. * University of Otago
  5. *
  6. ********************************************************************/
  7. .align 4
  8. .section .text
  9. .global vectors
  10. vectors:
  11. ldr pc, reset_handler
  12. ldr pc, undefintr_handler
  13. ldr pc, swi_handler
  14. ldr pc, prefetch_handler
  15. ldr pc, data_handler
  16. ldr pc, unused_handler
  17. ldr pc, irq_handler
  18. ldr pc, fiq_handler
  19. reset_handler:
  20. .word hang /* reset, in svc mode already */
  21. undefintr_handler:
  22. .word do_und /* undefined instruction */
  23. swi_handler:
  24. .word do_svc /* SWI & SVC */
  25. prefetch_handler:
  26. .word do_pabt /* prefetch abort */
  27. data_handler:
  28. .word do_dabt /* data abort */
  29. unused_handler:
  30. .word hang /* reserved */
  31. irq_handler:
  32. .word do_irq /* IRQ */
  33. fiq_handler:
  34. .word hang /* FIQ */
  35. hang:
  36. bl NotOkLoop;
  37. b hang
  38. do_svc:
  39. push {lr}
  40. mrs lr, spsr
  41. push {lr}
  42. mrs lr, cpsr
  43. push {lr}
  44. mrc p15, 0, lr, c6, c0, 2 /* read Instruction Fault Address Register (IFAR) */
  45. push {lr}
  46. mov lr, #0x40
  47. push {lr}
  48. STMFD sp, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14}
  49. sub sp, sp, #60
  50. mov r0, sp /* save sp */
  51. STMFD r0, {r13}^ /* save user mode sp */
  52. mov r1, r1 /* three nops after STM with user mode banked registers */
  53. mov r1, r1
  54. mov r1, r1
  55. mov sp, r0 /* restore sp */
  56. sub sp, sp, #4
  57. mov r0, sp
  58. bl trap
  59. .global trapret
  60. trapret:
  61. mov r0, sp /* save sp in case it is changed to sp_usr after the following LDMFD instruction */
  62. LDMFD r0, {r13}^ /* restore user mode sp */
  63. mov r1, r1 /* three nops after LDMFD */
  64. mov r1, r1
  65. mov r1, r1
  66. mov sp, r0 /* restore sp */
  67. add sp, sp, #4
  68. LDMFD sp, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12}
  69. add sp, sp, #72
  70. pop {lr}
  71. msr spsr, lr
  72. pop {lr}
  73. movs pc, lr /* subs pc,lr,#0 */
  74. do_und:
  75. STMFD sp, {r0-r4}
  76. mov r0, #0x01
  77. b _switchtosvc
  78. do_pabt:
  79. STMFD sp, {r0-r4}
  80. mov r0, #0x02
  81. b _switchtosvc
  82. do_dabt:
  83. STMFD sp, {r0-r4}
  84. mov r0, #0x04
  85. b _switchtosvc
  86. do_irq:
  87. STMFD sp, {r0-r4}
  88. mov r0, #0x80
  89. b _switchtosvc
  90. _switchtosvc:
  91. mrs r1, spsr
  92. sub r2, lr, #4
  93. mov r3, sp
  94. mrs lr, cpsr
  95. bic lr, #0x0000001F /* PSR_MASK */
  96. orr lr, #0x00000080 /* PSR_DISABLE_IRQ */
  97. orr lr, #0x00000013 /* PSR_MODE_SVC */
  98. msr cpsr, lr /* switch to svc */
  99. push {r2}
  100. push {r1}
  101. mrs r1, cpsr
  102. push {r1}
  103. mrc p15, 0, r1, c6, c0, 2 /* read Instruction Fault Address Register (I
  104. FAR) */
  105. push {r1}
  106. push {r0}
  107. sub r1, r3, #20
  108. LDMFD r1, {r0-r4}
  109. STMFD sp, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14}
  110. sub sp, sp, #60
  111. mov r0, sp /* save sp */
  112. STMFD r0, {r13}^ /* save user mode sp */
  113. mov r1, r1 /* three nops after STM with user mode banked registers */
  114. mov r1, r1
  115. mov r1, r1
  116. mov sp, r0 /* restore sp */
  117. sub sp, sp, #4
  118. mov r0, sp
  119. bl trap
  120. mov r0, sp
  121. add r0, #76
  122. LDMIA r0, {r1}
  123. mov r2, r1
  124. and r2, #0xf
  125. cmp r2, #0
  126. beq _backtouser
  127. msr cpsr, r1
  128. add sp, #4
  129. LDMFD sp, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12}
  130. add sp, sp, #56
  131. pop {r14}
  132. add sp, sp, #16
  133. pop {pc}
  134. _backtouser:
  135. mov r0, sp /* save sp in case it is changed to sp_usr after the following LDMFD instruction */
  136. LDMFD r0, {r13}^ /* restore user mode sp */
  137. mov r1, r1 /* three nops after LDMFD */
  138. mov r1, r1
  139. mov r1, r1
  140. mov sp, r0 /* restore sp */
  141. add sp, sp, #4
  142. LDMIA sp, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12}
  143. add sp, sp, #72
  144. pop {lr}
  145. msr spsr, lr
  146. pop {lr}
  147. movs pc, lr /* subs pc,lr,#0 */
  148. .global set_mode_sp
  149. set_mode_sp:
  150. mrs r2, cpsr
  151. msr cpsr_c,r1
  152. mov sp, r0
  153. mrs r0, cpsr
  154. orr r0, #0x00000080 /* PSR_DISABLE_IRQ */
  155. orr r0, #0x00000040 /* PSR_DISABLE_FIQ */
  156. msr cpsr, r0
  157. msr cpsr_c, r2
  158. bx lr
  159. .global readcpsr
  160. readcpsr:
  161. mrs r0, cpsr
  162. bx lr
  163. .global cli
  164. cli:
  165. mrs r0, cpsr
  166. orr r0, #0x00000080 /* PSR_DISABLE_IRQ */
  167. msr cpsr, r0
  168. bx lr
  169. .global sti
  170. sti:
  171. mrs r0, cpsr
  172. bic r0, r0, #0x00000080 /* PSR_DISABLE_IRQ */
  173. msr cpsr, r0
  174. bx lr
  175. .global swtch
  176. swtch:
  177. push {lr} /* save the return address */
  178. push {lr}
  179. /* save old callee-save registers */
  180. push {r12}
  181. push {r11}
  182. push {r10}
  183. push {r9}
  184. push {r8}
  185. push {r7}
  186. push {r6}
  187. push {r5}
  188. push {r4}
  189. /* switch stacks */
  190. str sp, [r0]
  191. mov sp, r1
  192. /* load new callee-save registers */
  193. pop {r4}
  194. pop {r5}
  195. pop {r6}
  196. pop {r7}
  197. pop {r8}
  198. pop {r9}
  199. pop {r10}
  200. pop {r11}
  201. pop {r12}
  202. /* return to previously saved pc */
  203. pop {lr}
  204. pop {pc}