The esp8266 portion of the project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

442 lines
10 KiB

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