contex_gcc.S 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Copyright (c) 2018, Synopsys, Inc.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #define __ASSEMBLY__
  7. #include "inc/arc/arc.h"
  8. #include "inc/arc/arc_asm_common.h"
  9. .global rt_interrupt_enter; .type rt_interrupt_enter, %function
  10. .global rt_interrupt_leave; .type rt_interrupt_leave, %function
  11. .global context_switch_reqflg; .type context_switch_reqflg, %object
  12. .global rt_interrupt_from_thread; .type rt_interrupt_from_thread, %object
  13. .global rt_interrupt_to_thread; .type rt_interrupt_to_thread, %object
  14. .text
  15. .align 4
  16. dispatcher:
  17. st sp, [r0]
  18. ld sp, [r1]
  19. pop r0
  20. j [r0]
  21. /* return routine when task dispatch happened in task context */
  22. dispatch_r:
  23. RESTORE_NONSCRATCH_REGS
  24. j [blink]
  25. /*
  26. * rt_base_t rt_hw_interrupt_disable();
  27. */
  28. .global rt_hw_interrupt_disable
  29. .type rt_hw_interrupt_disable, %function
  30. rt_hw_interrupt_disable:
  31. clri r0
  32. j [blink]
  33. /*
  34. * void rt_hw_interrupt_enable(rt_base_t level);
  35. */
  36. .global rt_hw_interrupt_enable
  37. .type rt_hw_interrupt_enable, %function
  38. rt_hw_interrupt_enable:
  39. seti r0
  40. j [blink]
  41. .global rt_hw_context_switch_interrupt
  42. .type rt_hw_context_switch_interrupt, %function
  43. rt_hw_context_switch_interrupt:
  44. st r0, [rt_interrupt_from_thread]
  45. st r1, [rt_interrupt_to_thread]
  46. mov r0, 1
  47. st r0, [context_switch_reqflg]
  48. j [blink]
  49. /*
  50. * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
  51. * r0 --> from
  52. * r1 --> to
  53. */
  54. .global rt_hw_context_switch
  55. .type rt_hw_context_switch, %function
  56. rt_hw_context_switch:
  57. SAVE_NONSCRATCH_REGS
  58. mov r2, dispatch_r
  59. push r2
  60. b dispatcher
  61. /*
  62. * void rt_hw_context_switch_to(rt_uint32 to);
  63. * r0 --> to
  64. */
  65. .global rt_hw_context_switch_to
  66. .type rt_hw_context_switch_to, %function
  67. rt_hw_context_switch_to:
  68. ld sp, [r0]
  69. pop r0
  70. j [r0]
  71. .global start_r
  72. .type start_r, %function
  73. start_r:
  74. pop blink;
  75. pop r1
  76. pop r2
  77. pop r0
  78. j_s.d [r1]
  79. kflag r2
  80. /****** exceptions and interrupts handing ******/
  81. /****** entry for exception handling ******/
  82. .global exc_entry_cpu
  83. .align 4
  84. exc_entry_cpu:
  85. EXCEPTION_PROLOGUE
  86. mov blink, sp
  87. mov r3, sp /* as exception handler's para(p_excinfo) */
  88. ld r0, [exc_nest_count]
  89. add r1, r0, 1
  90. st r1, [exc_nest_count]
  91. cmp r0, 0
  92. bne exc_handler_1
  93. /* change to exception stack if interrupt happened in task context */
  94. mov sp, _e_stack
  95. exc_handler_1:
  96. PUSH blink
  97. lr r0, [AUX_ECR]
  98. lsr r0, r0, 16
  99. mov r1, exc_int_handler_table
  100. ld.as r2, [r1, r0]
  101. mov r0, r3
  102. jl [r2]
  103. /* interrupts are not allowed */
  104. ret_exc:
  105. POP sp
  106. mov r1, exc_nest_count
  107. ld r0, [r1]
  108. sub r0, r0, 1
  109. cmp r0, 0
  110. bne.d ret_exc_1
  111. st r0, [r1]
  112. ld r0, [context_switch_reqflg]
  113. cmp r0, 0
  114. bne ret_exc_2
  115. ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */
  116. EXCEPTION_EPILOGUE
  117. rtie
  118. /* there is a dispatch request */
  119. ret_exc_2:
  120. /* clear dispatch request */
  121. mov r0, 0
  122. st r0, [context_switch_reqflg]
  123. SAVE_CALLEE_REGS /* save callee save registers */
  124. /* clear exception bit to do exception exit by SW */
  125. lr r0, [AUX_STATUS32]
  126. bclr r0, r0, AUX_STATUS_BIT_AE
  127. kflag r0
  128. mov r1, ret_exc_r /* save return address */
  129. PUSH r1
  130. ld r0, [rt_interrupt_from_thread]
  131. ld r1, [rt_interrupt_to_thread]
  132. b dispatcher
  133. ret_exc_r:
  134. /* recover exception status */
  135. lr r0, [AUX_STATUS32]
  136. bset r0, r0, AUX_STATUS_BIT_AE
  137. kflag r0
  138. RESTORE_CALLEE_REGS
  139. EXCEPTION_EPILOGUE
  140. rtie
  141. /****** entry for normal interrupt exception handling ******/
  142. .global exc_entry_int /* entry for interrupt handling */
  143. .align 4
  144. exc_entry_int:
  145. #if ARC_FEATURE_FIRQ == 1
  146. /* check whether it is P0 interrupt */
  147. #if ARC_FEATURE_RGF_NUM_BANKS > 1
  148. lr r0, [AUX_IRQ_ACT]
  149. btst r0, 0
  150. jnz exc_entry_firq
  151. #else
  152. PUSH r10
  153. lr r10, [AUX_IRQ_ACT]
  154. btst r10, 0
  155. POP r10
  156. jnz exc_entry_firq
  157. #endif
  158. #endif
  159. INTERRUPT_PROLOGUE
  160. mov blink, sp
  161. clri /* disable interrupt */
  162. ld r3, [exc_nest_count]
  163. add r2, r3, 1
  164. st r2, [exc_nest_count]
  165. seti /* enable higher priority interrupt */
  166. cmp r3, 0
  167. bne irq_handler_1
  168. /* change to exception stack if interrupt happened in task context */
  169. mov sp, _e_stack
  170. irq_handler_1:
  171. PUSH blink
  172. jl rt_interrupt_enter
  173. lr r0, [AUX_IRQ_CAUSE]
  174. sr r0, [AUX_IRQ_SELECT]
  175. mov r1, exc_int_handler_table
  176. ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */
  177. /* handle software triggered interrupt */
  178. lr r3, [AUX_IRQ_HINT]
  179. cmp r3, r0
  180. bne.d irq_hint_handled
  181. xor r3, r3, r3
  182. sr r3, [AUX_IRQ_HINT]
  183. irq_hint_handled:
  184. lr r3, [AUX_IRQ_PRIORITY]
  185. PUSH r3 /* save irq priority */
  186. jl [r2] /* jump to interrupt handler */
  187. jl rt_interrupt_leave
  188. ret_int:
  189. clri /* disable interrupt */
  190. POP r3 /* irq priority */
  191. POP sp
  192. mov r1, exc_nest_count
  193. ld r0, [r1]
  194. sub r0, r0, 1
  195. cmp r0, 0
  196. bne.d ret_int_1
  197. st r0, [r1]
  198. ld r0, [context_switch_reqflg]
  199. cmp r0, 0
  200. bne ret_int_2
  201. ret_int_1: /* return from non-task context */
  202. INTERRUPT_EPILOGUE
  203. rtie
  204. /* there is a dispatch request */
  205. ret_int_2:
  206. /* clear dispatch request */
  207. mov r0, 0
  208. st r0, [context_switch_reqflg]
  209. /* interrupt return by SW */
  210. lr r10, [AUX_IRQ_ACT]
  211. PUSH r10
  212. bclr r10, r10, r3 /* clear related bits in IRQ_ACT */
  213. sr r10, [AUX_IRQ_ACT]
  214. SAVE_CALLEE_REGS /* save callee save registers */
  215. mov r1, ret_int_r /* save return address */
  216. PUSH r1
  217. ld r0, [rt_interrupt_from_thread]
  218. ld r1, [rt_interrupt_to_thread]
  219. b dispatcher
  220. ret_int_r:
  221. RESTORE_CALLEE_REGS
  222. /* recover AUX_IRQ_ACT to restore the interrup status */
  223. POPAX AUX_IRQ_ACT
  224. INTERRUPT_EPILOGUE
  225. rtie