context_gcc.S 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * Copyright (c) 2006-2020, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-10-06 ZhaoXiaowei the first version
  9. */
  10. .macro SAVE_CONTEXT
  11. /* Switch to use the EL0 stack pointer. */
  12. MSR SPSEL, #0
  13. /* Save the entire context. */
  14. STP X0, X1, [SP, #-0x10]!
  15. STP X2, X3, [SP, #-0x10]!
  16. STP X4, X5, [SP, #-0x10]!
  17. STP X6, X7, [SP, #-0x10]!
  18. STP X8, X9, [SP, #-0x10]!
  19. STP X10, X11, [SP, #-0x10]!
  20. STP X12, X13, [SP, #-0x10]!
  21. STP X14, X15, [SP, #-0x10]!
  22. STP X16, X17, [SP, #-0x10]!
  23. STP X18, X19, [SP, #-0x10]!
  24. STP X20, X21, [SP, #-0x10]!
  25. STP X22, X23, [SP, #-0x10]!
  26. STP X24, X25, [SP, #-0x10]!
  27. STP X26, X27, [SP, #-0x10]!
  28. STP X28, X29, [SP, #-0x10]!
  29. STP X30, XZR, [SP, #-0x10]!
  30. MRS X0, CurrentEL
  31. CMP X0, 0xc
  32. B.EQ 3f
  33. CMP X0, 0x8
  34. B.EQ 2f
  35. CMP X0, 0x4
  36. B.EQ 1f
  37. B .
  38. 3:
  39. MRS X3, SPSR_EL3
  40. /* Save the ELR. */
  41. MRS X2, ELR_EL3
  42. B 0f
  43. 2:
  44. MRS X3, SPSR_EL2
  45. /* Save the ELR. */
  46. MRS X2, ELR_EL2
  47. B 0f
  48. 1:
  49. MRS X3, SPSR_EL1
  50. MRS X2, ELR_EL1
  51. B 0f
  52. 0:
  53. STP X2, X3, [SP, #-0x10]!
  54. MOV X0, SP /* Move SP into X0 for saving. */
  55. /* Switch to use the ELx stack pointer. */
  56. MSR SPSEL, #1
  57. .endm
  58. .macro SAVE_CONTEXT_T
  59. /* Switch to use the EL0 stack pointer. */
  60. MSR SPSEL, #0
  61. /* Save the entire context. */
  62. STP X0, X1, [SP, #-0x10]!
  63. STP X2, X3, [SP, #-0x10]!
  64. STP X4, X5, [SP, #-0x10]!
  65. STP X6, X7, [SP, #-0x10]!
  66. STP X8, X9, [SP, #-0x10]!
  67. STP X10, X11, [SP, #-0x10]!
  68. STP X12, X13, [SP, #-0x10]!
  69. STP X14, X15, [SP, #-0x10]!
  70. STP X16, X17, [SP, #-0x10]!
  71. STP X18, X19, [SP, #-0x10]!
  72. STP X20, X21, [SP, #-0x10]!
  73. STP X22, X23, [SP, #-0x10]!
  74. STP X24, X25, [SP, #-0x10]!
  75. STP X26, X27, [SP, #-0x10]!
  76. STP X28, X29, [SP, #-0x10]!
  77. STP X30, XZR, [SP, #-0x10]!
  78. MRS X0, CurrentEL
  79. CMP X0, 0xc
  80. B.EQ 3f
  81. CMP X0, 0x8
  82. B.EQ 2f
  83. CMP X0, 0x4
  84. B.EQ 1f
  85. B .
  86. 3:
  87. MRS X3, SPSR_EL3
  88. MOV X2, X30
  89. B 0f
  90. 2:
  91. MRS X3, SPSR_EL2
  92. MOV X2, X30
  93. B 0f
  94. 1:
  95. MRS X3, SPSR_EL1
  96. MOV X2, X30
  97. B 0f
  98. 0:
  99. STP X2, X3, [SP, #-0x10]!
  100. MOV X0, SP /* Move SP into X0 for saving. */
  101. /* Switch to use the ELx stack pointer. */
  102. MSR SPSEL, #1
  103. .endm
  104. .macro RESTORE_CONTEXT
  105. /* Switch to use the EL0 stack pointer. */
  106. MSR SPSEL, #0
  107. /* Set the SP to point to the stack of the task being restored. */
  108. MOV SP, X0
  109. LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
  110. MRS X0, CurrentEL
  111. CMP X0, 0xc
  112. B.EQ 3f
  113. CMP X0, 0x8
  114. B.EQ 2f
  115. CMP X0, 0x4
  116. B.EQ 1f
  117. B .
  118. 3:
  119. MSR SPSR_EL3, X3
  120. MSR ELR_EL3, X2
  121. B 0f
  122. 2:
  123. MSR SPSR_EL2, X3
  124. MSR ELR_EL2, X2
  125. B 0f
  126. 1:
  127. MSR SPSR_EL1, X3
  128. MSR ELR_EL1, X2
  129. B 0f
  130. 0:
  131. LDP X30, XZR, [SP], #0x10
  132. LDP X28, X29, [SP], #0x10
  133. LDP X26, X27, [SP], #0x10
  134. LDP X24, X25, [SP], #0x10
  135. LDP X22, X23, [SP], #0x10
  136. LDP X20, X21, [SP], #0x10
  137. LDP X18, X19, [SP], #0x10
  138. LDP X16, X17, [SP], #0x10
  139. LDP X14, X15, [SP], #0x10
  140. LDP X12, X13, [SP], #0x10
  141. LDP X10, X11, [SP], #0x10
  142. LDP X8, X9, [SP], #0x10
  143. LDP X6, X7, [SP], #0x10
  144. LDP X4, X5, [SP], #0x10
  145. LDP X2, X3, [SP], #0x10
  146. LDP X0, X1, [SP], #0x10
  147. /* Switch to use the ELx stack pointer. _RB_ Might not be required. */
  148. MSR SPSEL, #1
  149. ERET
  150. .endm
  151. .text
  152. /*
  153. * rt_base_t rt_hw_interrupt_disable();
  154. */
  155. .globl rt_hw_interrupt_disable
  156. rt_hw_interrupt_disable:
  157. MRS X0, DAIF
  158. MSR DAIFSet, #3
  159. DSB SY
  160. RET
  161. /*
  162. * void rt_hw_interrupt_enable(rt_base_t level);
  163. */
  164. .globl rt_hw_interrupt_enable
  165. rt_hw_interrupt_enable:
  166. DSB SY
  167. MOV X1, #0xC0
  168. ANDS X0, X0, X1
  169. B.NE rt_hw_interrupt_enable_exit
  170. MSR DAIFClr, #3
  171. rt_hw_interrupt_enable_exit:
  172. RET
  173. /*
  174. * void rt_hw_context_switch_to(rt_ubase_t to);
  175. * r0 --> to
  176. */
  177. .globl rt_hw_context_switch_to
  178. rt_hw_context_switch_to:
  179. LDR X0, [X0]
  180. RESTORE_CONTEXT
  181. .text
  182. /*
  183. * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
  184. * r0 --> from
  185. * r1 --> to
  186. */
  187. .globl rt_hw_context_switch
  188. rt_hw_context_switch:
  189. MOV X8,X0
  190. MOV X9,X1
  191. SAVE_CONTEXT_T
  192. STR X0, [X8] // store sp in preempted tasks TCB
  193. LDR X0, [X9] // get new task stack pointer
  194. RESTORE_CONTEXT
  195. /*
  196. * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
  197. */
  198. .globl rt_thread_switch_interrupt_flag
  199. .globl rt_interrupt_from_thread
  200. .globl rt_interrupt_to_thread
  201. .globl rt_hw_context_switch_interrupt
  202. rt_hw_context_switch_interrupt:
  203. ADR X2, rt_thread_switch_interrupt_flag
  204. LDR X3, [X2]
  205. CMP X3, #1
  206. B.EQ _reswitch
  207. ADR X4, rt_interrupt_from_thread // set rt_interrupt_from_thread
  208. MOV X3, #1 // set rt_thread_switch_interrupt_flag to 1
  209. STR X0, [X4]
  210. STR X3, [X2]
  211. _reswitch:
  212. ADR X2, rt_interrupt_to_thread // set rt_interrupt_to_thread
  213. STR X1, [X2]
  214. RET
  215. .text
  216. // -- Exception handlers ----------------------------------
  217. .align 8
  218. .globl vector_fiq
  219. vector_fiq:
  220. SAVE_CONTEXT
  221. STP X0, X1, [SP, #-0x10]!
  222. BL rt_hw_trap_fiq
  223. LDP X0, X1, [SP], #0x10
  224. RESTORE_CONTEXT
  225. .globl rt_interrupt_enter
  226. .globl rt_interrupt_leave
  227. .globl rt_thread_switch_interrupt_flag
  228. .globl rt_interrupt_from_thread
  229. .globl rt_interrupt_to_thread
  230. // -------------------------------------------------------------------
  231. .align 8
  232. .globl vector_irq
  233. vector_irq:
  234. SAVE_CONTEXT
  235. STP X0, X1, [SP, #-0x10]!
  236. BL rt_interrupt_enter
  237. BL rt_hw_trap_irq
  238. BL rt_interrupt_leave
  239. LDP X0, X1, [SP], #0x10
  240. // if rt_thread_switch_interrupt_flag set, jump to
  241. // rt_hw_context_switch_interrupt_do and don't return
  242. ADR X1, rt_thread_switch_interrupt_flag
  243. LDR X2, [X1]
  244. CMP X2, #1
  245. B.NE vector_irq_exit
  246. MOV X2, #0 // clear flag
  247. STR X2, [X1]
  248. ADR X3, rt_interrupt_from_thread
  249. LDR X4, [X3]
  250. STR x0, [X4] // store sp in preempted tasks's TCB
  251. ADR x3, rt_interrupt_to_thread
  252. LDR X4, [X3]
  253. LDR x0, [X4] // get new task's stack pointer
  254. vector_irq_exit:
  255. RESTORE_CONTEXT
  256. // -------------------------------------------------
  257. .align 8
  258. .globl vector_error
  259. vector_error:
  260. SAVE_CONTEXT
  261. BL rt_hw_trap_error
  262. B .