gdbstub-entry.S 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /******************************************************************************
  2. * Copyright 2015 Espressif Systems
  3. *
  4. * Description: Assembly routines for the gdbstub
  5. *
  6. * License: ESPRESSIF MIT License
  7. *******************************************************************************/
  8. #include "gdbstub-cfg.h"
  9. #include <xtensa/config/specreg.h>
  10. #include <xtensa/config/core-isa.h>
  11. #include <xtensa/corebits.h>
  12. #define DEBUG_PC (EPC + XCHAL_DEBUGLEVEL)
  13. #define DEBUG_EXCSAVE (EXCSAVE + XCHAL_DEBUGLEVEL)
  14. #define DEBUG_PS (EPS + XCHAL_DEBUGLEVEL)
  15. .global gdbstub_savedRegs
  16. #if GDBSTUB_USE_OWN_STACK
  17. .global gdbstub_exceptionStack
  18. #endif
  19. .text
  20. .literal_position
  21. .text
  22. .align 4
  23. /*
  24. The savedRegs struct:
  25. uint32_t pc;
  26. uint32_t ps;
  27. uint32_t sar;
  28. uint32_t vpri;
  29. uint32_t a0;
  30. uint32_t a[14]; //a2..a15
  31. uint32_t litbase;
  32. uint32_t sr176;
  33. uint32_t sr208;
  34. uint32_t a1;
  35. uint32_t reason;
  36. */
  37. /*
  38. This is the debugging exception routine; it's called by the debugging vector
  39. We arrive here with all regs intact except for a2. The old contents of A2 are saved
  40. into the DEBUG_EXCSAVE special function register. EPC is the original PC.
  41. */
  42. gdbstub_debug_exception_entry:
  43. /*
  44. //Minimum no-op debug exception handler, for debug
  45. rsr a2,DEBUG_PC
  46. addi a2,a2,3
  47. wsr a2,DEBUG_PC
  48. xsr a2, DEBUG_EXCSAVE
  49. rfi XCHAL_DEBUGLEVEL
  50. */
  51. //Save all regs to structure
  52. movi a2, gdbstub_savedRegs
  53. s32i a0, a2, 0x10
  54. s32i a1, a2, 0x58
  55. rsr a0, DEBUG_PS
  56. s32i a0, a2, 0x04
  57. rsr a0, DEBUG_EXCSAVE //was R2
  58. s32i a0, a2, 0x14
  59. s32i a3, a2, 0x18
  60. s32i a4, a2, 0x1c
  61. s32i a5, a2, 0x20
  62. s32i a6, a2, 0x24
  63. s32i a7, a2, 0x28
  64. s32i a8, a2, 0x2c
  65. s32i a9, a2, 0x30
  66. s32i a10, a2, 0x34
  67. s32i a11, a2, 0x38
  68. s32i a12, a2, 0x3c
  69. s32i a13, a2, 0x40
  70. s32i a14, a2, 0x44
  71. s32i a15, a2, 0x48
  72. rsr a0, SAR
  73. s32i a0, a2, 0x08
  74. rsr a0, LITBASE
  75. s32i a0, a2, 0x4C
  76. rsr a0, 176
  77. s32i a0, a2, 0x50
  78. rsr a0, 208
  79. s32i a0, a2, 0x54
  80. rsr a0, DEBUGCAUSE
  81. s32i a0, a2, 0x5C
  82. rsr a4, DEBUG_PC
  83. s32i a4, a2, 0x00
  84. #if GDBSTUB_USE_OWN_STACK
  85. //Move to our own stack
  86. movi a1, exceptionStack+255*4
  87. #endif
  88. //If ICOUNT is -1, disable it by setting it to 0, otherwise we will keep triggering on the same instruction.
  89. rsr a2, ICOUNT
  90. movi a3, -1
  91. bne a2, a3, noIcountReset
  92. movi a3, 0
  93. wsr a3, ICOUNT
  94. noIcountReset:
  95. rsr a2, ps
  96. addi a2, a2, -PS_EXCM_MASK
  97. wsr a2, ps
  98. rsync
  99. //Call into the C code to do the actual handling.
  100. call0 gdbstub_handle_debug_exception
  101. DebugExceptionExit:
  102. rsr a2, ps
  103. addi a2, a2, PS_EXCM_MASK
  104. wsr a2, ps
  105. rsync
  106. //Restore registers from the gdbstub_savedRegs struct
  107. movi a2, gdbstub_savedRegs
  108. l32i a0, a2, 0x00
  109. wsr a0, DEBUG_PC
  110. // l32i a0, a2, 0x54
  111. // wsr a0, 208
  112. l32i a0, a2, 0x50
  113. //wsr a0, 176 //Some versions of gcc do not understand this...
  114. .byte 0x00, 176, 0x13 //so we hand-assemble the instruction.
  115. l32i a0, a2, 0x4C
  116. wsr a0, LITBASE
  117. l32i a0, a2, 0x08
  118. wsr a0, SAR
  119. l32i a15, a2, 0x48
  120. l32i a14, a2, 0x44
  121. l32i a13, a2, 0x40
  122. l32i a12, a2, 0x3c
  123. l32i a11, a2, 0x38
  124. l32i a10, a2, 0x34
  125. l32i a9, a2, 0x30
  126. l32i a8, a2, 0x2c
  127. l32i a7, a2, 0x28
  128. l32i a6, a2, 0x24
  129. l32i a5, a2, 0x20
  130. l32i a4, a2, 0x1c
  131. l32i a3, a2, 0x18
  132. l32i a0, a2, 0x14
  133. wsr a0, DEBUG_EXCSAVE //was R2
  134. l32i a0, a2, 0x04
  135. wsr a0, DEBUG_PS
  136. l32i a1, a2, 0x58
  137. l32i a0, a2, 0x10
  138. //Read back vector-saved a2 value, put back address of this routine.
  139. movi a2, gdbstub_debug_exception_entry
  140. xsr a2, DEBUG_EXCSAVE
  141. //All done. Return to where we came from.
  142. rfi XCHAL_DEBUGLEVEL
  143. #if GDBSTUB_FREERTOS
  144. /*
  145. FreeRTOS exception handling code. For some reason or another, we can't just hook the main exception vector: it
  146. seems FreeRTOS uses that for something else too (interrupts). FreeRTOS has its own fatal exception handler, and we
  147. hook that. Unfortunately, that one is called from a few different places (eg directly in the DoubleExceptionVector)
  148. so the precise location of the original register values are somewhat of a mystery when we arrive here...
  149. As a 'solution', we'll just decode the most common case of the user_fatal_exception_handler being called from
  150. the user exception handler vector:
  151. - excsave1 - orig a0
  152. - a1: stack frame:
  153. sf+16: orig a1
  154. sf+8: ps
  155. sf+4: epc
  156. sf+12: orig a0
  157. sf: magic no?
  158. */
  159. .global gdbstub_handle_user_exception
  160. .global gdbstub_user_exception_entry
  161. .align 4
  162. gdbstub_user_exception_entry:
  163. //Save all regs to structure
  164. movi a0, gdbstub_savedRegs
  165. s32i a1, a0, 0x14 //was a2
  166. s32i a3, a0, 0x18
  167. s32i a4, a0, 0x1c
  168. s32i a5, a0, 0x20
  169. s32i a6, a0, 0x24
  170. s32i a7, a0, 0x28
  171. s32i a8, a0, 0x2c
  172. s32i a9, a0, 0x30
  173. s32i a10, a0, 0x34
  174. s32i a11, a0, 0x38
  175. s32i a12, a0, 0x3c
  176. s32i a13, a0, 0x40
  177. s32i a14, a0, 0x44
  178. s32i a15, a0, 0x48
  179. rsr a2, SAR
  180. s32i a2, a0, 0x08
  181. rsr a2, LITBASE
  182. s32i a2, a0, 0x4C
  183. rsr a2, 176
  184. s32i a2, a0, 0x50
  185. rsr a2, 208
  186. s32i a2, a0, 0x54
  187. rsr a2, EXCCAUSE
  188. s32i a2, a0, 0x5C
  189. //Get the rest of the regs from the stack struct
  190. l32i a3, a1, 12
  191. s32i a3, a0, 0x10
  192. l32i a3, a1, 16
  193. s32i a3, a0, 0x58
  194. l32i a3, a1, 8
  195. s32i a3, a0, 0x04
  196. l32i a3, a1, 4
  197. s32i a3, a0, 0x00
  198. #if GDBSTUB_USE_OWN_STACK
  199. movi a1, exceptionStack+255*4
  200. #endif
  201. rsr a2, ps
  202. addi a2, a2, -PS_EXCM_MASK
  203. wsr a2, ps
  204. rsync
  205. call0 gdbstub_handle_user_exception
  206. UserExceptionExit:
  207. /*
  208. Okay, from here on, it Does Not Work. There's not really any continuing from an exception in the
  209. FreeRTOS case; there isn't any effort put in reversing the mess the exception code made yet. Maybe this
  210. is still something we need to implement later, if there's any demand for it, or maybe we should modify
  211. FreeRTOS to allow this in the future. (Which will then kill backwards compatibility... hmmm.)
  212. */
  213. j UserExceptionExit
  214. .global gdbstub_handle_uart_int
  215. .global gdbstub_uart_entry
  216. .align 4
  217. gdbstub_uart_entry:
  218. //On entry, the stack frame is at SP+16.
  219. //This is a small stub to present that as the first arg to the gdbstub_handle_uart function.
  220. movi a2, 16
  221. add a2, a2, a1
  222. movi a3, gdbstub_handle_uart_int
  223. jx a3
  224. #endif
  225. .global gdbstub_save_extra_sfrs_for_exception
  226. .align 4
  227. //The Xtensa OS HAL does not save all the special function register things. This bit of assembly
  228. //fills the gdbstub_savedRegs struct with them.
  229. gdbstub_save_extra_sfrs_for_exception:
  230. movi a2, gdbstub_savedRegs
  231. rsr a3, LITBASE
  232. s32i a3, a2, 0x4C
  233. rsr a3, 176
  234. s32i a3, a2, 0x50
  235. rsr a3, 208
  236. s32i a3, a2, 0x54
  237. rsr a3, EXCCAUSE
  238. s32i a3, a2, 0x5C
  239. ret
  240. .global gdbstub_init_debug_entry
  241. .global _DebugExceptionVector
  242. .align 4
  243. gdbstub_init_debug_entry:
  244. //This puts the following 2 instructions into the debug exception vector:
  245. // xsr a2, DEBUG_EXCSAVE
  246. // jx a2
  247. movi a2, _DebugExceptionVector
  248. movi a3, 0xa061d220
  249. s32i a3, a2, 0
  250. movi a3, 0x00000002
  251. s32i a3, a2, 4
  252. //Tell the just-installed debug vector where to go.
  253. movi a2, gdbstub_debug_exception_entry
  254. wsr a2, DEBUG_EXCSAVE
  255. ret
  256. //Set up ICOUNT register to step one single instruction
  257. .global gdbstub_icount_ena_single_step
  258. .align 4
  259. gdbstub_icount_ena_single_step:
  260. movi a3, XCHAL_DEBUGLEVEL //Only count steps in non-debug mode
  261. movi a2, -2
  262. wsr a3, ICOUNTLEVEL
  263. wsr a2, ICOUNT
  264. isync
  265. ret
  266. //These routines all assume only one breakpoint and watchpoint is available, which
  267. //is the case for the ESP8266 Xtensa core.
  268. .global gdbstub_set_hw_breakpoint
  269. gdbstub_set_hw_breakpoint:
  270. //a2 - addr, a3 - len (unused here)
  271. rsr a4, IBREAKENABLE
  272. bbsi a4, 0, return_w_error
  273. wsr a2, IBREAKA
  274. movi a2, 1
  275. wsr a2, IBREAKENABLE
  276. isync
  277. movi a2, 1
  278. ret
  279. .global gdbstub_del_hw_breakpoint
  280. gdbstub_del_hw_breakpoint:
  281. //a2 - addr
  282. rsr a5, IBREAKENABLE
  283. bbci a5, 0, return_w_error
  284. rsr a3, IBREAKA
  285. bne a3, a2, return_w_error
  286. movi a2,0
  287. wsr a2, IBREAKENABLE
  288. isync
  289. movi a2, 1
  290. ret
  291. .global gdbstub_set_hw_watchpoint
  292. //a2 - addr, a3 - mask, a4 - type (1=read, 2=write, 3=access)
  293. gdbstub_set_hw_watchpoint:
  294. //Check if any of the masked address bits are set. If so, that is an error.
  295. movi a5,0x0000003F
  296. xor a5, a5, a3
  297. bany a2, a5, return_w_error
  298. //Check if watchpoint already is set
  299. rsr a5, DBREAKC
  300. movi a6, 0xC0000000
  301. bany a6, a5, return_w_error
  302. //Set watchpoint
  303. wsr a2, DBREAKA
  304. //Combine type and mask
  305. movi a6, 0x3F
  306. and a3, a3, a6
  307. slli a4, a4, 30
  308. or a3, a3, a4
  309. wsr a3, DBREAKC
  310. // movi a2, 1
  311. mov a2, a3
  312. isync
  313. ret
  314. .global gdbstub_del_hw_watchpoint
  315. //a2 - addr
  316. gdbstub_del_hw_watchpoint:
  317. //See if the address matches
  318. rsr a3, DBREAKA
  319. bne a3, a2, return_w_error
  320. //See if the bp actually is set
  321. rsr a3, DBREAKC
  322. movi a2, 0xC0000000
  323. bnone a3, a2, return_w_error
  324. //Disable bp
  325. movi a2,0
  326. wsr a2,DBREAKC
  327. movi a2,1
  328. isync
  329. ret
  330. return_w_error:
  331. movi a2, 0
  332. ret
  333. //Breakpoint, with an attempt at a functional function prologue and epilogue...
  334. .global gdbstub_do_break_breakpoint_addr
  335. .global gdbstub_do_break
  336. .align 4
  337. gdbstub_do_break:
  338. addi a1, a1, -16
  339. s32i a15, a1, 12
  340. mov a15, a1
  341. gdbstub_do_break_breakpoint_addr:
  342. break 0,0
  343. mov a1, a15
  344. l32i a15, a1, 12
  345. addi a1, a1, 16
  346. ret