interrupt_gcc.S 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021/07/15 JasonHu The first version
  9. */
  10. #define __ASSEMBLY__
  11. #include <rtconfig.h>
  12. .code32
  13. .text
  14. .extern rt_interrupt_enter
  15. .extern rt_interrupt_leave
  16. .extern rt_thread_switch_interrupt_flag
  17. .extern rt_interrupt_from_thread
  18. .extern rt_interrupt_to_thread
  19. .extern rt_hw_interrupt_dispatch
  20. .extern rt_hw_context_switch
  21. // cpu no error code, need push by us
  22. .macro rt_hw_intr_entry_push_errcode p1
  23. .global rt_hw_intr_entry\p1
  24. rt_hw_intr_entry\p1:
  25. pushl $0x00
  26. pushl %ds
  27. pushl %es
  28. pushl %fs
  29. pushl %gs
  30. pushal
  31. movl %ss, %edx
  32. movl %edx, %ds
  33. movl %edx, %es
  34. pushl $\p1
  35. call rt_interrupt_enter
  36. pushl %esp
  37. call rt_hw_interrupt_dispatch
  38. addl $4, %esp
  39. call rt_interrupt_leave
  40. #ifdef RT_USING_SIGNALS
  41. // check signal and do signal
  42. pushl %esp
  43. call lwp_try_do_signal
  44. addl $4, %esp
  45. #endif /* RT_USING_SIGNALS */
  46. /**
  47. * if rt_thread_switch_interrupt_flag == 1 then
  48. * jmp rt_hw_intr_thread_switch
  49. * end
  50. */
  51. movl $rt_thread_switch_interrupt_flag, %eax
  52. movl (%eax), %ebx
  53. cmp $0x1, %ebx
  54. jz rt_hw_intr_thread_switch
  55. // jmp to exit
  56. movl $rt_hw_intr_exit, %eax
  57. jmp *%eax
  58. .endm
  59. // cpu with error code
  60. .macro rt_hw_intr_entry p1
  61. .global rt_hw_intr_entry\p1
  62. rt_hw_intr_entry\p1:
  63. nop;
  64. pushl %ds
  65. pushl %es
  66. pushl %fs
  67. pushl %gs
  68. pushal
  69. movl %ss, %edx
  70. movl %edx, %ds
  71. movl %edx, %es
  72. pushl $\p1
  73. call rt_interrupt_enter
  74. pushl %esp;
  75. call rt_hw_interrupt_dispatch
  76. addl $4, %esp;
  77. call rt_interrupt_leave
  78. #ifdef RT_USING_SIGNALS
  79. // check signal and do signal
  80. pushl %esp
  81. call lwp_try_do_signal
  82. addl $4, %esp
  83. #endif /* RT_USING_SIGNALS */
  84. /**
  85. * if rt_thread_switch_interrupt_flag == 1 then
  86. * jmp rt_hw_intr_thread_switch
  87. * end
  88. */
  89. movl $rt_thread_switch_interrupt_flag, %eax
  90. movl (%eax), %ebx
  91. cmp $0x1, %ebx
  92. jz rt_hw_intr_thread_switch
  93. // jmp to exit
  94. movl $rt_hw_intr_exit, %eax
  95. jmp *%eax
  96. .endm
  97. rt_hw_intr_entry_push_errcode 0x00
  98. rt_hw_intr_entry_push_errcode 0x01
  99. rt_hw_intr_entry_push_errcode 0x02
  100. rt_hw_intr_entry_push_errcode 0x03
  101. rt_hw_intr_entry_push_errcode 0x04
  102. rt_hw_intr_entry_push_errcode 0x05
  103. rt_hw_intr_entry_push_errcode 0x06
  104. rt_hw_intr_entry_push_errcode 0x07
  105. rt_hw_intr_entry 0x08
  106. rt_hw_intr_entry_push_errcode 0x09
  107. rt_hw_intr_entry 0x0a
  108. rt_hw_intr_entry 0x0b
  109. rt_hw_intr_entry_push_errcode 0x0c
  110. rt_hw_intr_entry 0x0d
  111. rt_hw_intr_entry 0x0e
  112. rt_hw_intr_entry_push_errcode 0x0f
  113. rt_hw_intr_entry_push_errcode 0x10
  114. rt_hw_intr_entry 0x11
  115. rt_hw_intr_entry_push_errcode 0x12
  116. rt_hw_intr_entry_push_errcode 0x13
  117. rt_hw_intr_entry_push_errcode 0x14
  118. rt_hw_intr_entry_push_errcode 0x15
  119. rt_hw_intr_entry_push_errcode 0x16
  120. rt_hw_intr_entry_push_errcode 0x17
  121. rt_hw_intr_entry 0x18
  122. rt_hw_intr_entry_push_errcode 0x19
  123. rt_hw_intr_entry 0x1a
  124. rt_hw_intr_entry 0x1b
  125. rt_hw_intr_entry_push_errcode 0x1c
  126. rt_hw_intr_entry 0x1d
  127. rt_hw_intr_entry 0x1e
  128. rt_hw_intr_entry_push_errcode 0x1f
  129. rt_hw_intr_entry_push_errcode 0x20
  130. rt_hw_intr_entry_push_errcode 0x21
  131. rt_hw_intr_entry_push_errcode 0x22
  132. rt_hw_intr_entry_push_errcode 0x23
  133. rt_hw_intr_entry_push_errcode 0x24
  134. rt_hw_intr_entry_push_errcode 0x25
  135. rt_hw_intr_entry_push_errcode 0x26
  136. rt_hw_intr_entry_push_errcode 0x27
  137. rt_hw_intr_entry_push_errcode 0x28
  138. rt_hw_intr_entry_push_errcode 0x29
  139. rt_hw_intr_entry_push_errcode 0x2a
  140. rt_hw_intr_entry_push_errcode 0x2b
  141. rt_hw_intr_entry_push_errcode 0x2c
  142. rt_hw_intr_entry_push_errcode 0x2d
  143. rt_hw_intr_entry_push_errcode 0x2e
  144. rt_hw_intr_entry_push_errcode 0x2f
  145. rt_hw_intr_entry_push_errcode 0x80 // syscall
  146. rt_hw_intr_thread_switch:
  147. // set rt_thread_switch_interrupt_flag as 0
  148. movl $0x0, %ebx
  149. movl %ebx, (%eax)
  150. // push to into stack
  151. movl $rt_interrupt_to_thread, %eax // get "to"
  152. movl (%eax), %ebx
  153. // push from into stack
  154. movl $rt_interrupt_from_thread, %ecx // get "from"
  155. movl (%ecx), %edx
  156. pushl %ebx
  157. pushl %edx
  158. call rt_hw_context_switch
  159. addl $8, %esp // restore stack
  160. // jmp to exit
  161. movl $rt_hw_intr_exit, %eax
  162. jmp *%eax
  163. #ifdef RT_USING_USERSPACE
  164. .extern rt_hw_syscall_dispath
  165. #ifdef RT_USING_SIGNALS
  166. .extern lwp_try_do_signal
  167. #endif /* RT_USING_SIGNALS */
  168. .global hw_syscall_entry
  169. hw_syscall_entry:
  170. pushl $0x00
  171. pushl %ds
  172. pushl %es
  173. pushl %fs
  174. pushl %gs
  175. pushal
  176. movl %ss, %edx
  177. movl %edx, %ds
  178. movl %edx, %es
  179. pushl $0x80
  180. sti // enable interrupt
  181. pushl %esp
  182. call rt_hw_syscall_dispath
  183. addl $4, %esp
  184. #ifdef RT_USING_SIGNALS
  185. // check signal and do signal
  186. pushl %esp
  187. call lwp_try_do_signal
  188. addl $4, %esp
  189. #endif /* RT_USING_SIGNALS */
  190. cli // disable interrupt
  191. // jmp to exit
  192. movl $rt_hw_intr_exit, %eax
  193. jmp *%eax
  194. .global syscall_exit
  195. syscall_exit:
  196. #endif /* RT_USING_USERSPACE */
  197. .global rt_hw_intr_exit
  198. rt_hw_intr_exit:
  199. addl $4, %esp // skip intr no
  200. popal
  201. popl %gs
  202. popl %fs
  203. popl %es
  204. popl %ds
  205. addl $4, %esp // skip error_code
  206. iret