context_gcc.S 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. * Copyright (c) 2019-Present Nuclei Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020/03/26 Huaqi First Nuclei RISC-V porting implementation
  9. */
  10. #include "riscv_encoding.h"
  11. /* see https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc */
  12. #ifndef __riscv_32e
  13. /* Make sure the stack pointer is 16-byte aligned when calling c function */
  14. #define portRegNum 32
  15. #else
  16. /* Make sure the stack pointer is 4-byte aligned when calling c function for ilp32e */
  17. #define portRegNum 14
  18. #endif
  19. #define portCONTEXT_SIZE ( portRegNum * REGBYTES )
  20. .extern rt_interrupt_from_thread
  21. .extern rt_interrupt_to_thread
  22. .section .text
  23. /*
  24. * void rt_hw_context_switch_to(rt_ubase_t to);
  25. * a0 --> to_thread
  26. */
  27. .globl rt_hw_context_switch_to
  28. /* Start the first task. This also clears the bit that indicates the FPU is
  29. in use in case the FPU was used before the scheduler was started - which
  30. would otherwise result in the unnecessary leaving of space in the stack
  31. for lazy saving of FPU registers. */
  32. .type rt_hw_context_switch_to, @function
  33. .align 3
  34. rt_hw_context_switch_to:
  35. /* Setup Interrupt Stack using
  36. The stack that was used by main()
  37. before the scheduler is started is
  38. no longer required after the scheduler is started.
  39. Interrupt stack pointer is stored in CSR_XSCRATCH */
  40. la t0, _sp
  41. csrw CSR_XSCRATCH, t0
  42. LOAD sp, 0x0(a0) /* Read sp from first TCB member(a0) */
  43. /* Pop PC from stack and set XEPC */
  44. LOAD t0, 0 * REGBYTES(sp)
  45. csrw CSR_XEPC, t0
  46. /* Pop xstatus from stack and set it */
  47. LOAD t0, (portRegNum - 1) * REGBYTES(sp)
  48. csrw CSR_XSTATUS, t0
  49. /* Interrupt still disable here */
  50. /* Restore registers from stack */
  51. LOAD x1, 1 * REGBYTES(sp) /* RA */
  52. LOAD x5, 2 * REGBYTES(sp)
  53. LOAD x6, 3 * REGBYTES(sp)
  54. LOAD x7, 4 * REGBYTES(sp)
  55. LOAD x8, 5 * REGBYTES(sp)
  56. LOAD x9, 6 * REGBYTES(sp)
  57. LOAD x10, 7 * REGBYTES(sp)
  58. LOAD x11, 8 * REGBYTES(sp)
  59. LOAD x12, 9 * REGBYTES(sp)
  60. LOAD x13, 10 * REGBYTES(sp)
  61. LOAD x14, 11 * REGBYTES(sp)
  62. LOAD x15, 12 * REGBYTES(sp)
  63. #ifndef __riscv_32e
  64. LOAD x16, 13 * REGBYTES(sp)
  65. LOAD x17, 14 * REGBYTES(sp)
  66. LOAD x18, 15 * REGBYTES(sp)
  67. LOAD x19, 16 * REGBYTES(sp)
  68. LOAD x20, 17 * REGBYTES(sp)
  69. LOAD x21, 18 * REGBYTES(sp)
  70. LOAD x22, 19 * REGBYTES(sp)
  71. LOAD x23, 20 * REGBYTES(sp)
  72. LOAD x24, 21 * REGBYTES(sp)
  73. LOAD x25, 22 * REGBYTES(sp)
  74. LOAD x26, 23 * REGBYTES(sp)
  75. LOAD x27, 24 * REGBYTES(sp)
  76. LOAD x28, 25 * REGBYTES(sp)
  77. LOAD x29, 26 * REGBYTES(sp)
  78. LOAD x30, 27 * REGBYTES(sp)
  79. LOAD x31, 28 * REGBYTES(sp)
  80. #endif
  81. addi sp, sp, portCONTEXT_SIZE
  82. XRET
  83. .size rt_hw_context_switch_to, . - rt_hw_context_switch_to
  84. .align 2
  85. .global eclic_xsip_handler
  86. .type eclic_xsip_handler, @function
  87. eclic_xsip_handler:
  88. addi sp, sp, -portCONTEXT_SIZE
  89. STORE x1, 1 * REGBYTES(sp) /* RA */
  90. STORE x5, 2 * REGBYTES(sp)
  91. STORE x6, 3 * REGBYTES(sp)
  92. STORE x7, 4 * REGBYTES(sp)
  93. STORE x8, 5 * REGBYTES(sp)
  94. STORE x9, 6 * REGBYTES(sp)
  95. STORE x10, 7 * REGBYTES(sp)
  96. STORE x11, 8 * REGBYTES(sp)
  97. STORE x12, 9 * REGBYTES(sp)
  98. STORE x13, 10 * REGBYTES(sp)
  99. STORE x14, 11 * REGBYTES(sp)
  100. STORE x15, 12 * REGBYTES(sp)
  101. #ifndef __riscv_32e
  102. STORE x16, 13 * REGBYTES(sp)
  103. STORE x17, 14 * REGBYTES(sp)
  104. STORE x18, 15 * REGBYTES(sp)
  105. STORE x19, 16 * REGBYTES(sp)
  106. STORE x20, 17 * REGBYTES(sp)
  107. STORE x21, 18 * REGBYTES(sp)
  108. STORE x22, 19 * REGBYTES(sp)
  109. STORE x23, 20 * REGBYTES(sp)
  110. STORE x24, 21 * REGBYTES(sp)
  111. STORE x25, 22 * REGBYTES(sp)
  112. STORE x26, 23 * REGBYTES(sp)
  113. STORE x27, 24 * REGBYTES(sp)
  114. STORE x28, 25 * REGBYTES(sp)
  115. STORE x29, 26 * REGBYTES(sp)
  116. STORE x30, 27 * REGBYTES(sp)
  117. STORE x31, 28 * REGBYTES(sp)
  118. #endif
  119. /* Push xstatus to stack */
  120. csrr t0, CSR_XSTATUS
  121. STORE t0, (portRegNum - 1) * REGBYTES(sp)
  122. /* Push additional registers */
  123. /* Store sp to task stack */
  124. LOAD t0, rt_interrupt_from_thread
  125. STORE sp, 0(t0)
  126. csrr t0, CSR_XEPC
  127. STORE t0, 0(sp)
  128. jal xPortTaskSwitch
  129. /* Switch task context */
  130. LOAD t0, rt_interrupt_to_thread
  131. LOAD sp, 0x0(t0)
  132. /* Pop PC from stack and set XEPC */
  133. LOAD t0, 0 * REGBYTES(sp)
  134. csrw CSR_XEPC, t0
  135. /* Pop additional registers */
  136. /* Pop xstatus from stack and set it */
  137. LOAD t0, (portRegNum - 1) * REGBYTES(sp)
  138. csrw CSR_XSTATUS, t0
  139. /* Interrupt still disable here */
  140. /* Restore registers from stack */
  141. LOAD x1, 1 * REGBYTES(sp) /* RA */
  142. LOAD x5, 2 * REGBYTES(sp)
  143. LOAD x6, 3 * REGBYTES(sp)
  144. LOAD x7, 4 * REGBYTES(sp)
  145. LOAD x8, 5 * REGBYTES(sp)
  146. LOAD x9, 6 * REGBYTES(sp)
  147. LOAD x10, 7 * REGBYTES(sp)
  148. LOAD x11, 8 * REGBYTES(sp)
  149. LOAD x12, 9 * REGBYTES(sp)
  150. LOAD x13, 10 * REGBYTES(sp)
  151. LOAD x14, 11 * REGBYTES(sp)
  152. LOAD x15, 12 * REGBYTES(sp)
  153. #ifndef __riscv_32e
  154. LOAD x16, 13 * REGBYTES(sp)
  155. LOAD x17, 14 * REGBYTES(sp)
  156. LOAD x18, 15 * REGBYTES(sp)
  157. LOAD x19, 16 * REGBYTES(sp)
  158. LOAD x20, 17 * REGBYTES(sp)
  159. LOAD x21, 18 * REGBYTES(sp)
  160. LOAD x22, 19 * REGBYTES(sp)
  161. LOAD x23, 20 * REGBYTES(sp)
  162. LOAD x24, 21 * REGBYTES(sp)
  163. LOAD x25, 22 * REGBYTES(sp)
  164. LOAD x26, 23 * REGBYTES(sp)
  165. LOAD x27, 24 * REGBYTES(sp)
  166. LOAD x28, 25 * REGBYTES(sp)
  167. LOAD x29, 26 * REGBYTES(sp)
  168. LOAD x30, 27 * REGBYTES(sp)
  169. LOAD x31, 28 * REGBYTES(sp)
  170. #endif
  171. addi sp, sp, portCONTEXT_SIZE
  172. XRET
  173. .size eclic_xsip_handler, . - eclic_xsip_handler