xtensa_loadstore_handler.S 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. Copyright 2019 Espressif Systems (Shanghai) PTE LTD
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. /*
  14. * LoadStoreErrorCause: Occurs when trying to access 32 bit addressable memory region as 8 bit or 16 bit
  15. * LoadStoreAlignmentCause: Occurs when trying to access in an unaligned manner
  16. *
  17. * xxxx xxxx = imm8 field
  18. * yyyy = imm4 field
  19. * ssss = s field
  20. * tttt = t field
  21. *
  22. * 16 0
  23. * -------------------
  24. * L32I.N yyyy ssss tttt 1000
  25. * S32I.N yyyy ssss tttt 1001
  26. *
  27. * 23 0
  28. * -----------------------------
  29. * L8UI xxxx xxxx 0000 ssss tttt 0010 <- LoadStoreError
  30. * L16UI xxxx xxxx 0001 ssss tttt 0010 <- LoadStoreError, LoadStoreAlignment
  31. * L16SI xxxx xxxx 1001 ssss tttt 0010 <- LoadStoreError, LoadStoreAlignment
  32. * L32I xxxx xxxx 0010 ssss tttt 0010 <- LoadStoreAlignment
  33. *
  34. * S8I xxxx xxxx 0100 ssss tttt 0010 <- LoadStoreError
  35. * S16I xxxx xxxx 0101 ssss tttt 0010 <- LoadStoreError, LoadStoreAlignment
  36. * S32I xxxx xxxx 0110 ssss tttt 0010 <- LoadStoreAlignment
  37. *
  38. * ******* UNSUPPORTED *******
  39. *
  40. * L32E 0000 1001 rrrr ssss tttt 0000
  41. * S32E 0100 1001 rrrr ssss tttt 0000
  42. * -----------------------------
  43. */
  44. #include "xtensa_rtos.h"
  45. #include "sdkconfig.h"
  46. #include "soc/soc.h"
  47. #define LOADSTORE_HANDLER_STACK_SZ 8
  48. .section .bss, "aw"
  49. .balign 16
  50. LoadStoreHandlerStack:
  51. .rept LOADSTORE_HANDLER_STACK_SZ
  52. .word 0
  53. .endr
  54. /* LoadStoreErrorCause handler:
  55. *
  56. * Completes 8-bit or 16-bit load/store instructions from 32-bit aligned memory region
  57. * Called from UserExceptionVector if EXCCAUSE is LoadStoreErrorCause
  58. */
  59. .global LoadStoreErrorHandler
  60. .section .iram1, "ax"
  61. .literal_position
  62. .balign 4
  63. LoadStoreErrorHandler:
  64. .type LoadStoreErrorHandler, @function
  65. wsr a0, depc // Save return address in depc
  66. mov a0, sp
  67. movi sp, LoadStoreHandlerStack
  68. s32i a0, sp, 0x04 // Since a0 contains value of a1
  69. s32i a2, sp, 0x08
  70. s32i a3, sp, 0x0c
  71. s32i a4, sp, 0x10
  72. rsr a0, sar // Save SAR in a0 to restore later
  73. /* Check whether the address lies in the valid range */
  74. rsr a3, excvaddr
  75. movi a4, _iram_text_end // End of code section of IRAM
  76. bge a3, a4, 1f
  77. movi a4, SOC_CACHE_APP_LOW // Check if in APP cache region
  78. blt a3, a4, .LS_wrong_opcode
  79. movi a4, SOC_CACHE_APP_HIGH
  80. bge a3, a4, .LS_wrong_opcode
  81. j 2f
  82. 1:
  83. movi a4, SOC_IRAM_HIGH // End of IRAM address range
  84. bge a3, a4, .LS_wrong_opcode
  85. 2:
  86. /* Examine the opcode which generated the exception */
  87. /* Note: Instructions are in this order to avoid pipeline stalls. */
  88. rsr a2, epc1
  89. movi a4, ~3
  90. ssa8l a2 // sar is now correct shift for aligned read
  91. and a2, a2, a4 // a2 now 4-byte aligned address of instruction
  92. l32i a4, a2, 0
  93. l32i a2, a2, 4
  94. src a2, a2, a4 // a2 now instruction that failed
  95. bbci a2, 1, .LS_wrong_opcode
  96. bbsi a2, 14, .LSE_store_op // Store instruction
  97. /* l8/l16ui/l16si */
  98. movi a4, ~3
  99. and a4, a3, a4 // a4 now word aligned read address
  100. ssa8l a3 // sar is now shift to extract a3's byte
  101. l32i a4, a4, 0 // perform the actual read
  102. srl a4, a4 // shift right correct distance
  103. extui a3, a2, 12, 4
  104. bnez a3, 1f // l16ui/l16si
  105. extui a4, a4, 0, 8 // mask off bits needed for an l8
  106. j 2f
  107. 1:
  108. extui a4, a4, 0, 16
  109. bbci a2, 15, 2f // l16ui
  110. /* Sign adjustment */
  111. slli a4, a4, 16
  112. srai a4, a4, 16 // a4 contains the value
  113. 2:
  114. /* a4 contains the value */
  115. rsr a3, epc1
  116. addi a3, a3, 3
  117. wsr a3, epc1
  118. wsr a0, sar
  119. rsr a0, excsave1
  120. extui a2, a2, 3, 5
  121. blti a2, 10, .LSE_stack_reg
  122. movi a3, .LS_jumptable_base
  123. addx8 a2, a2, a3 // a2 is now the address to jump to
  124. l32i a3, sp, 0x0c
  125. jx a2
  126. .LSE_stack_reg:
  127. addx2 a2, a2, sp
  128. s32i a4, a2, 0
  129. /* Restore all values */
  130. l32i a4, sp, 0x10
  131. l32i a3, sp, 0x0c
  132. l32i a2, sp, 0x08
  133. l32i a1, sp, 0x04
  134. rfe
  135. .LSE_store_op:
  136. s32i a5, a1, 0x14
  137. s32i a6, a1, 0x18
  138. /* a2 -> instruction that caused the error */
  139. /* a3 -> unaligned address */
  140. extui a4, a2, 4, 4
  141. blti a4, 7, 1f
  142. movi a5, .LSE_store_reg
  143. addx8 a5, a4, a5
  144. jx a5
  145. 1:
  146. addx4 a4, a4, sp
  147. l32i a4, a4, 0
  148. .LSE_store_data:
  149. /* a4 contains the value */
  150. rsr a6, epc1
  151. addi a6, a6, 3
  152. wsr a6, epc1
  153. ssa8b a3
  154. movi a5, -1
  155. bbsi a2, 12, 1f // s16
  156. extui a4, a4, 0, 8
  157. movi a6, 0xff
  158. j 2f
  159. 1:
  160. extui a4, a4, 0, 16
  161. movi a6, 0xffff
  162. 2:
  163. sll a4, a4 // shift the value to proper offset
  164. sll a6, a6
  165. xor a5, a5, a6 // a5 contains the mask
  166. movi a6, ~3
  167. and a3, a3, a6 // a3 has the aligned address
  168. l32i a6, a3, 0 // a6 contains the data at the aligned address
  169. and a6, a6, a5
  170. or a4, a6, a4
  171. s32i a4, a3, 0
  172. /* Restore registers */
  173. wsr a0, sar
  174. l32i a6, sp, 0x18
  175. l32i a5, sp, 0x14
  176. l32i a4, sp, 0x10
  177. l32i a3, sp, 0x0c
  178. l32i a2, sp, 0x08
  179. l32i a1, sp, 0x04
  180. rsr a0, excsave1
  181. rfe
  182. .LSE_store_reg:
  183. .org .LSE_store_reg + (7 * 8)
  184. mov a4, a7
  185. j .LSE_store_data
  186. .org .LSE_store_reg + (8 * 8)
  187. mov a4, a8
  188. j .LSE_store_data
  189. .org .LSE_store_reg + (9 * 8)
  190. mov a4, a9
  191. j .LSE_store_data
  192. .org .LSE_store_reg + (10 * 8)
  193. mov a4, a10
  194. j .LSE_store_data
  195. .org .LSE_store_reg + (11 * 8)
  196. mov a4, a11
  197. j .LSE_store_data
  198. .org .LSE_store_reg + (12 * 8)
  199. mov a4, a12
  200. j .LSE_store_data
  201. .org .LSE_store_reg + (13 * 8)
  202. mov a4, a13
  203. j .LSE_store_data
  204. .org .LSE_store_reg + (14 * 8)
  205. mov a4, a14
  206. j .LSE_store_data
  207. .org .LSE_store_reg + (15 * 8)
  208. mov a4, a15
  209. j .LSE_store_data
  210. /* LoadStoreAlignmentCause handler:
  211. *
  212. * Completes unaligned 16-bit and 32-bit load/store instructions from 32-bit aligned memory region
  213. * Called from UserExceptionVector if EXCCAUSE is LoadStoreAlignmentCause
  214. */
  215. .global AlignmentErrorHandler
  216. .section .iram1, "ax"
  217. .literal_position
  218. .balign 4
  219. AlignmentErrorHandler:
  220. .type AlignmentErrorHandler, @function
  221. wsr a0, depc // Save return address in depc
  222. mov a0, sp
  223. movi sp, LoadStoreHandlerStack
  224. s32i a0, sp, 0x04 // Since a0 contains value of a1
  225. s32i a2, sp, 0x08
  226. s32i a3, sp, 0x0c
  227. s32i a4, sp, 0x10
  228. rsr a0, sar // Save SAR in a0 to restore later
  229. /* Check whether the address lies in the valid range */
  230. rsr a3, excvaddr
  231. movi a4, _iram_text_end // End of code section of IRAM
  232. bge a3, a4, 1f
  233. movi a4, SOC_CACHE_APP_LOW // Check if in APP cache region
  234. blt a3, a4, .LS_wrong_opcode
  235. movi a4, SOC_CACHE_APP_HIGH
  236. bge a3, a4, .LS_wrong_opcode
  237. j 2f
  238. 1:
  239. movi a4, SOC_IRAM_HIGH // End of IRAM address range
  240. bge a3, a4, .LS_wrong_opcode
  241. 2:
  242. /* Examine the opcode which generated the exception */
  243. /* Note: Instructions are in this order to avoid pipeline stalls. */
  244. rsr a2, epc1
  245. movi a4, ~3
  246. ssa8l a2 // sar is now correct shift for aligned read
  247. and a2, a2, a4 // a2 now 4-byte aligned address of instruction
  248. l32i a4, a2, 0
  249. l32i a2, a2, 4
  250. /* a2 has the instruction that caused the error */
  251. src a2, a2, a4
  252. extui a4, a2, 0, 4
  253. addi a4, a4, -9
  254. beqz a4, .LSA_store_op
  255. bbsi a2, 14, .LSA_store_op
  256. ssa8l a3 // a3 contains the unaligned address
  257. movi a4, ~3
  258. and a4, a3, a4 // a4 has the aligned address
  259. l32i a3, a4, 0
  260. l32i a4, a4, 4
  261. src a4, a4, a3
  262. rsr a3, epc1
  263. addi a3, a3, 2
  264. bbsi a2, 3, 1f // l32i.n
  265. bbci a2, 1, .LS_wrong_opcode
  266. addi a3, a3, 1
  267. bbsi a2, 13, 1f // l32
  268. extui a4, a4, 0, 16
  269. bbci a2, 15, 1f // l16ui
  270. /* Sign adjustment */
  271. slli a4, a4, 16
  272. srai a4, a4, 16 // a4 contains the value
  273. 1:
  274. wsr a3, epc1
  275. wsr a0, sar
  276. rsr a0, excsave1
  277. extui a2, a2, 4, 4
  278. blti a2, 5, .LSA_stack_reg // a3 contains the target register
  279. movi a3, .LS_jumptable_base
  280. slli a2, a2, 4
  281. add a2, a2, a3 // a2 is now the address to jump to
  282. l32i a3, sp, 0x0c
  283. jx a2
  284. .LSA_stack_reg:
  285. addx4 a2, a2, sp
  286. s32i a4, a2, 0
  287. /* Restore all values */
  288. l32i a4, sp, 0x10
  289. l32i a3, sp, 0x0c
  290. l32i a2, sp, 0x08
  291. l32i a1, sp, 0x04
  292. rfe
  293. /* Store instruction */
  294. .LSA_store_op:
  295. s32i a5, sp, 0x14
  296. s32i a6, sp, 0x18
  297. s32i a7, sp, 0x1c
  298. /* a2 -> instruction that caused the error */
  299. /* a3 -> unaligned address */
  300. extui a4, a2, 4, 4
  301. blti a4, 8, 1f
  302. movi a5, .LSA_store_reg
  303. addx8 a5, a4, a5
  304. jx a5
  305. 1:
  306. addx4 a4, a4, sp
  307. l32i a4, a4, 0 // a4 contains the value
  308. .LSA_store_data:
  309. movi a6, 0
  310. rsr a7, epc1
  311. addi a7, a7 ,2
  312. bbsi a2, 3, 1f // s32i.n
  313. bbci a2, 1, .LS_wrong_opcode
  314. addi a7, a7, 1
  315. bbsi a2, 13, 1f // s32i
  316. movi a5, -1
  317. extui a4, a4, 0, 16
  318. slli a6, a5, 16 // 0xffff0000
  319. 1:
  320. wsr a7, epc1
  321. movi a5, ~3
  322. and a5, a3, a5 // a5 has the aligned address
  323. ssa8b a3
  324. movi a3, -1
  325. src a7, a6, a3
  326. src a3, a3, a6
  327. /* Store data on lower address */
  328. l32i a6, a5, 0
  329. and a6, a6, a7
  330. sll a7, a4
  331. or a6, a6, a7
  332. s32i a6, a5, 0
  333. /* Store data on higher address */
  334. l32i a7, a5, 4
  335. srl a6, a4
  336. and a3, a7, a3
  337. or a3, a3, a6
  338. s32i a3, a5, 4
  339. /* Restore registers */
  340. wsr a0, sar
  341. rsr a0, excsave1
  342. l32i a7, sp, 0x1c
  343. l32i a6, sp, 0x18
  344. l32i a5, sp, 0x14
  345. l32i a4, sp, 0x10
  346. l32i a3, sp, 0x0c
  347. l32i a2, sp, 0x08
  348. l32i a1, sp, 0x04
  349. rfe
  350. .LSA_store_reg:
  351. .org .LSA_store_reg + (8 * 8)
  352. mov a4, a8
  353. j .LSA_store_data
  354. .org .LSA_store_reg + (9 * 8)
  355. mov a4, a9
  356. j .LSA_store_data
  357. .org .LSA_store_reg + (10 * 8)
  358. mov a4, a10
  359. j .LSA_store_data
  360. .org .LSA_store_reg + (11 * 8)
  361. mov a4, a11
  362. j .LSA_store_data
  363. .org .LSA_store_reg + (12 * 8)
  364. mov a4, a12
  365. j .LSA_store_data
  366. .org .LSA_store_reg + (13 * 8)
  367. mov a4, a13
  368. j .LSA_store_data
  369. .org .LSA_store_reg + (14 * 8)
  370. mov a4, a14
  371. j .LSA_store_data
  372. .org .LSA_store_reg + (15 * 8)
  373. mov a4, a15
  374. j .LSA_store_data
  375. /*
  376. * Common routines for both the exception handlers
  377. */
  378. .balign 4
  379. .LS_jumptable:
  380. /* The first 5 entries (80 bytes) of this table are unused (registers
  381. a0..a4 are handled separately above). Rather than have a whole bunch
  382. of wasted space, just pretend that the table starts 80 bytes
  383. earlier in memory. */
  384. .set .LS_jumptable_base, .LS_jumptable - (16 * 5)
  385. .org .LS_jumptable_base + (16 * 5)
  386. mov a5, a4
  387. l32i a4, sp, 0x10
  388. l32i a2, sp, 0x08
  389. l32i a1, sp, 0x04
  390. rfe
  391. .org .LS_jumptable_base + (16 * 6)
  392. mov a6, a4
  393. l32i a4, sp, 0x10
  394. l32i a2, sp, 0x08
  395. l32i a1, sp, 0x04
  396. rfe
  397. .org .LS_jumptable_base + (16 * 7)
  398. mov a7, a4
  399. l32i a4, sp, 0x10
  400. l32i a2, sp, 0x08
  401. l32i a1, sp, 0x04
  402. rfe
  403. .org .LS_jumptable_base + (16 * 8)
  404. mov a8, a4
  405. l32i a4, sp, 0x10
  406. l32i a2, sp, 0x08
  407. l32i a1, sp, 0x04
  408. rfe
  409. .org .LS_jumptable_base + (16 * 9)
  410. mov a9, a4
  411. l32i a4, sp, 0x10
  412. l32i a2, sp, 0x08
  413. l32i a1, sp, 0x04
  414. rfe
  415. .org .LS_jumptable_base + (16 * 10)
  416. mov a10, a4
  417. l32i a4, sp, 0x10
  418. l32i a2, sp, 0x08
  419. l32i a1, sp, 0x04
  420. rfe
  421. .org .LS_jumptable_base + (16 * 11)
  422. mov a11, a4
  423. l32i a4, sp, 0x10
  424. l32i a2, sp, 0x08
  425. l32i a1, sp, 0x04
  426. rfe
  427. .org .LS_jumptable_base + (16 * 12)
  428. mov a12, a4
  429. l32i a4, sp, 0x10
  430. l32i a2, sp, 0x08
  431. l32i a1, sp, 0x04
  432. rfe
  433. .org .LS_jumptable_base + (16 * 13)
  434. mov a13, a4
  435. l32i a4, sp, 0x10
  436. l32i a2, sp, 0x08
  437. l32i a1, sp, 0x04
  438. rfe
  439. .org .LS_jumptable_base + (16 * 14)
  440. mov a14, a4
  441. l32i a4, sp, 0x10
  442. l32i a2, sp, 0x08
  443. l32i a1, sp, 0x04
  444. rfe
  445. .org .LS_jumptable_base + (16 * 15)
  446. mov a15, a4
  447. l32i a4, sp, 0x10
  448. l32i a2, sp, 0x08
  449. l32i a1, sp, 0x04
  450. rfe
  451. .LS_wrong_opcode:
  452. /* Reaches here if the address is in invalid range or the opcode isn't supported.
  453. * Restore registers and jump back to _xt_user_exc
  454. */
  455. wsr a0, sar
  456. l32i a4, sp, 0x10
  457. l32i a3, sp, 0x0c
  458. l32i a2, sp, 0x08
  459. l32i a1, sp, 0x04
  460. rsr a0, depc
  461. ret // Equivalent to jx a0