xtensa_context.S 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. /*******************************************************************************
  2. Copyright (c) 2006-2015 Cadence Design Systems Inc.
  3. Permission is hereby granted, free of charge, to any person obtaining
  4. a copy of this software and associated documentation files (the
  5. "Software"), to deal in the Software without restriction, including
  6. without limitation the rights to use, copy, modify, merge, publish,
  7. distribute, sublicense, and/or sell copies of the Software, and to
  8. permit persons to whom the Software is furnished to do so, subject to
  9. the following conditions:
  10. The above copyright notice and this permission notice shall be included
  11. in all copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  15. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  16. CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  17. TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  18. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. --------------------------------------------------------------------------------
  20. XTENSA CONTEXT SAVE AND RESTORE ROUTINES
  21. Low-level Call0 functions for handling generic context save and restore of
  22. registers not specifically addressed by the interrupt vectors and handlers.
  23. Those registers (not handled by these functions) are PC, PS, A0, A1 (SP).
  24. Except for the calls to RTOS functions, this code is generic to Xtensa.
  25. Note that in Call0 ABI, interrupt handlers are expected to preserve the callee-
  26. save regs (A12-A15), which is always the case if the handlers are coded in C.
  27. However A12, A13 are made available as scratch registers for interrupt dispatch
  28. code, so are presumed saved anyway, and are always restored even in Call0 ABI.
  29. Only A14, A15 are truly handled as callee-save regs.
  30. Because Xtensa is a configurable architecture, this port supports all user
  31. generated configurations (except restrictions stated in the release notes).
  32. This is accomplished by conditional compilation using macros and functions
  33. defined in the Xtensa HAL (hardware adaptation layer) for your configuration.
  34. Only the processor state included in your configuration is saved and restored,
  35. including any processor state added by user configuration options or TIE.
  36. *******************************************************************************/
  37. /* Warn nicely if this file gets named with a lowercase .s instead of .S: */
  38. #define NOERROR #
  39. NOERROR: .error "C preprocessor needed for this file: make sure its filename\
  40. ends in uppercase .S, or use xt-xcc's -x assembler-with-cpp option."
  41. #include "xtensa_rtos.h"
  42. #include "xtensa_context.h"
  43. #ifdef XT_USE_OVLY
  44. #include <xtensa/overlay_os_asm.h>
  45. #endif
  46. .text
  47. /*******************************************************************************
  48. _xt_context_save
  49. !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!
  50. Saves all Xtensa processor state except PC, PS, A0, A1 (SP), A12, A13, in the
  51. interrupt stack frame defined in xtensa_rtos.h.
  52. Its counterpart is _xt_context_restore (which also restores A12, A13).
  53. Caller is expected to have saved PC, PS, A0, A1 (SP), A12, A13 in the frame.
  54. This function preserves A12 & A13 in order to provide the caller with 2 scratch
  55. regs that need not be saved over the call to this function. The choice of which
  56. 2 regs to provide is governed by xthal_window_spill_nw and xthal_save_extra_nw,
  57. to avoid moving data more than necessary. Caller can assign regs accordingly.
  58. Entry Conditions:
  59. A0 = Return address in caller.
  60. A1 = Stack pointer of interrupted thread or handler ("interruptee").
  61. Original A12, A13 have already been saved in the interrupt stack frame.
  62. Other processor state except PC, PS, A0, A1 (SP), A12, A13, is as at the
  63. point of interruption.
  64. If windowed ABI, PS.EXCM = 1 (exceptions disabled).
  65. Exit conditions:
  66. A0 = Return address in caller.
  67. A1 = Stack pointer of interrupted thread or handler ("interruptee").
  68. A12, A13 as at entry (preserved).
  69. If windowed ABI, PS.EXCM = 1 (exceptions disabled).
  70. *******************************************************************************/
  71. .global _xt_context_save
  72. .type _xt_context_save,@function
  73. .align 4
  74. .literal_position
  75. .align 4
  76. _xt_context_save:
  77. s32i a2, sp, XT_STK_A2
  78. s32i a3, sp, XT_STK_A3
  79. s32i a4, sp, XT_STK_A4
  80. s32i a5, sp, XT_STK_A5
  81. s32i a6, sp, XT_STK_A6
  82. s32i a7, sp, XT_STK_A7
  83. s32i a8, sp, XT_STK_A8
  84. s32i a9, sp, XT_STK_A9
  85. s32i a10, sp, XT_STK_A10
  86. s32i a11, sp, XT_STK_A11
  87. /*
  88. Call0 ABI callee-saved regs a12-15 do not need to be saved here.
  89. a12-13 are the caller's responsibility so it can use them as scratch.
  90. So only need to save a14-a15 here for Windowed ABI (not Call0).
  91. */
  92. #ifndef __XTENSA_CALL0_ABI__
  93. s32i a14, sp, XT_STK_A14
  94. s32i a15, sp, XT_STK_A15
  95. #endif
  96. rsr a3, SAR
  97. s32i a3, sp, XT_STK_SAR
  98. #if XCHAL_HAVE_LOOPS
  99. rsr a3, LBEG
  100. s32i a3, sp, XT_STK_LBEG
  101. rsr a3, LEND
  102. s32i a3, sp, XT_STK_LEND
  103. rsr a3, LCOUNT
  104. s32i a3, sp, XT_STK_LCOUNT
  105. #endif
  106. #ifdef XT_USE_SWPRI
  107. /* Save virtual priority mask */
  108. movi a3, _xt_vpri_mask
  109. l32i a3, a3, 0
  110. s32i a3, sp, XT_STK_VPRI
  111. #endif
  112. #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)
  113. mov a9, a0 /* preserve ret addr */
  114. #endif
  115. #ifndef __XTENSA_CALL0_ABI__
  116. /*
  117. To spill the reg windows, temp. need pre-interrupt stack ptr and a4-15.
  118. Need to save a9,12,13 temporarily (in frame temps) and recover originals.
  119. Interrupts need to be disabled below XCHAL_EXCM_LEVEL and window overflow
  120. and underflow exceptions disabled (assured by PS.EXCM == 1).
  121. */
  122. s32i a12, sp, XT_STK_TMP0 /* temp. save stuff in stack frame */
  123. s32i a13, sp, XT_STK_TMP1
  124. s32i a9, sp, XT_STK_TMP2
  125. /*
  126. Save the overlay state if we are supporting overlays. Since we just saved
  127. three registers, we can conveniently use them here. Note that as of now,
  128. overlays only work for windowed calling ABI.
  129. */
  130. #ifdef XT_USE_OVLY
  131. l32i a9, sp, XT_STK_PC /* recover saved PC */
  132. _xt_overlay_get_state a9, a12, a13
  133. s32i a9, sp, XT_STK_OVLY /* save overlay state */
  134. #endif
  135. l32i a12, sp, XT_STK_A12 /* recover original a9,12,13 */
  136. l32i a13, sp, XT_STK_A13
  137. l32i a9, sp, XT_STK_A9
  138. addi sp, sp, XT_STK_FRMSZ /* restore the interruptee's SP */
  139. call0 xthal_window_spill_nw /* preserves only a4,5,8,9,12,13 */
  140. addi sp, sp, -XT_STK_FRMSZ
  141. l32i a12, sp, XT_STK_TMP0 /* recover stuff from stack frame */
  142. l32i a13, sp, XT_STK_TMP1
  143. l32i a9, sp, XT_STK_TMP2
  144. #endif
  145. #if XCHAL_EXTRA_SA_SIZE > 0
  146. /*
  147. NOTE: Normally the xthal_save_extra_nw macro only affects address
  148. registers a2-a5. It is theoretically possible for Xtensa processor
  149. designers to write TIE that causes more address registers to be
  150. affected, but it is generally unlikely. If that ever happens,
  151. more registers need to be saved/restored around this macro invocation.
  152. Here we assume a9,12,13 are preserved.
  153. Future Xtensa tools releases might limit the regs that can be affected.
  154. */
  155. addi a2, sp, XT_STK_EXTRA /* where to save it */
  156. # if XCHAL_EXTRA_SA_ALIGN > 16
  157. movi a3, -XCHAL_EXTRA_SA_ALIGN
  158. and a2, a2, a3 /* align dynamically >16 bytes */
  159. # endif
  160. call0 xthal_save_extra_nw /* destroys a0,2,3,4,5 */
  161. #endif
  162. #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)
  163. mov a0, a9 /* retrieve ret addr */
  164. #endif
  165. ret
  166. /*******************************************************************************
  167. _xt_context_restore
  168. !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!
  169. Restores all Xtensa processor state except PC, PS, A0, A1 (SP) (and in Call0
  170. ABI, A14, A15 which are preserved by all interrupt handlers) from an interrupt
  171. stack frame defined in xtensa_rtos.h .
  172. Its counterpart is _xt_context_save (whose caller saved A12, A13).
  173. Caller is responsible to restore PC, PS, A0, A1 (SP).
  174. Entry Conditions:
  175. A0 = Return address in caller.
  176. A1 = Stack pointer of interrupted thread or handler ("interruptee").
  177. Exit conditions:
  178. A0 = Return address in caller.
  179. A1 = Stack pointer of interrupted thread or handler ("interruptee").
  180. Other processor state except PC, PS, A0, A1 (SP), is as at the point
  181. of interruption.
  182. *******************************************************************************/
  183. .global _xt_context_restore
  184. .type _xt_context_restore,@function
  185. .align 4
  186. .literal_position
  187. .align 4
  188. _xt_context_restore:
  189. #if XCHAL_EXTRA_SA_SIZE > 0
  190. /*
  191. NOTE: Normally the xthal_restore_extra_nw macro only affects address
  192. registers a2-a5. It is theoretically possible for Xtensa processor
  193. designers to write TIE that causes more address registers to be
  194. affected, but it is generally unlikely. If that ever happens,
  195. more registers need to be saved/restored around this macro invocation.
  196. Here we only assume a13 is preserved.
  197. Future Xtensa tools releases might limit the regs that can be affected.
  198. */
  199. mov a13, a0 /* preserve ret addr */
  200. addi a2, sp, XT_STK_EXTRA /* where to find it */
  201. # if XCHAL_EXTRA_SA_ALIGN > 16
  202. movi a3, -XCHAL_EXTRA_SA_ALIGN
  203. and a2, a2, a3 /* align dynamically >16 bytes */
  204. # endif
  205. call0 xthal_restore_extra_nw /* destroys a0,2,3,4,5 */
  206. mov a0, a13 /* retrieve ret addr */
  207. #endif
  208. #if XCHAL_HAVE_LOOPS
  209. l32i a2, sp, XT_STK_LBEG
  210. l32i a3, sp, XT_STK_LEND
  211. wsr a2, LBEG
  212. l32i a2, sp, XT_STK_LCOUNT
  213. wsr a3, LEND
  214. wsr a2, LCOUNT
  215. #endif
  216. #ifdef XT_USE_OVLY
  217. /*
  218. If we are using overlays, this is a good spot to check if we need
  219. to restore an overlay for the incoming task. Here we have a bunch
  220. of registers to spare. Note that this step is going to use a few
  221. bytes of storage below SP (SP-20 to SP-32) if an overlay is going
  222. to be restored.
  223. */
  224. l32i a2, sp, XT_STK_PC /* retrieve PC */
  225. l32i a3, sp, XT_STK_PS /* retrieve PS */
  226. l32i a4, sp, XT_STK_OVLY /* retrieve overlay state */
  227. l32i a5, sp, XT_STK_A1 /* retrieve stack ptr */
  228. _xt_overlay_check_map a2, a3, a4, a5, a6
  229. s32i a2, sp, XT_STK_PC /* save updated PC */
  230. s32i a3, sp, XT_STK_PS /* save updated PS */
  231. #endif
  232. #ifdef XT_USE_SWPRI
  233. /* Restore virtual interrupt priority and interrupt enable */
  234. movi a3, _xt_intdata
  235. l32i a4, a3, 0 /* a4 = _xt_intenable */
  236. l32i a5, sp, XT_STK_VPRI /* a5 = saved _xt_vpri_mask */
  237. and a4, a4, a5
  238. wsr a4, INTENABLE /* update INTENABLE */
  239. s32i a5, a3, 4 /* restore _xt_vpri_mask */
  240. #endif
  241. l32i a3, sp, XT_STK_SAR
  242. l32i a2, sp, XT_STK_A2
  243. wsr a3, SAR
  244. l32i a3, sp, XT_STK_A3
  245. l32i a4, sp, XT_STK_A4
  246. l32i a5, sp, XT_STK_A5
  247. l32i a6, sp, XT_STK_A6
  248. l32i a7, sp, XT_STK_A7
  249. l32i a8, sp, XT_STK_A8
  250. l32i a9, sp, XT_STK_A9
  251. l32i a10, sp, XT_STK_A10
  252. l32i a11, sp, XT_STK_A11
  253. /*
  254. Call0 ABI callee-saved regs a12-15 do not need to be restored here.
  255. However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(),
  256. so need to be restored anyway, despite being callee-saved in Call0.
  257. */
  258. l32i a12, sp, XT_STK_A12
  259. l32i a13, sp, XT_STK_A13
  260. #ifndef __XTENSA_CALL0_ABI__
  261. l32i a14, sp, XT_STK_A14
  262. l32i a15, sp, XT_STK_A15
  263. #endif
  264. ret
  265. /*******************************************************************************
  266. _xt_coproc_init
  267. Initializes global co-processor management data, setting all co-processors
  268. to "unowned". Leaves CPENABLE as it found it (does NOT clear it).
  269. Called during initialization of the RTOS, before any threads run.
  270. This may be called from normal Xtensa single-threaded application code which
  271. might use co-processors. The Xtensa run-time initialization enables all
  272. co-processors. They must remain enabled here, else a co-processor exception
  273. might occur outside of a thread, which the exception handler doesn't expect.
  274. Entry Conditions:
  275. Xtensa single-threaded run-time environment is in effect.
  276. No thread is yet running.
  277. Exit conditions:
  278. None.
  279. Obeys ABI conventions per prototype:
  280. void _xt_coproc_init(void)
  281. *******************************************************************************/
  282. #if XCHAL_CP_NUM > 0
  283. .global _xt_coproc_init
  284. .type _xt_coproc_init,@function
  285. .align 4
  286. .literal_position
  287. .align 4
  288. _xt_coproc_init:
  289. ENTRY0
  290. /* Initialize thread co-processor ownerships to 0 (unowned). */
  291. movi a2, _xt_coproc_owner_sa /* a2 = base of owner array */
  292. addi a3, a2, (XCHAL_CP_MAX*portNUM_PROCESSORS) << 2 /* a3 = top+1 of owner array */
  293. movi a4, 0 /* a4 = 0 (unowned) */
  294. 1: s32i a4, a2, 0
  295. addi a2, a2, 4
  296. bltu a2, a3, 1b
  297. RET0
  298. #endif
  299. /*******************************************************************************
  300. _xt_coproc_release
  301. Releases any and all co-processors owned by a given thread. The thread is
  302. identified by it's co-processor state save area defined in xtensa_context.h .
  303. Must be called before a thread's co-proc save area is deleted to avoid
  304. memory corruption when the exception handler tries to save the state.
  305. May be called when a thread terminates or completes but does not delete
  306. the co-proc save area, to avoid the exception handler having to save the
  307. thread's co-proc state before another thread can use it (optimization).
  308. Needs to be called on the processor the thread was running on. Unpinned threads
  309. won't have an entry here because they get pinned as soon they use a coprocessor.
  310. Entry Conditions:
  311. A2 = Pointer to base of co-processor state save area.
  312. Exit conditions:
  313. None.
  314. Obeys ABI conventions per prototype:
  315. void _xt_coproc_release(void * coproc_sa_base)
  316. *******************************************************************************/
  317. #if XCHAL_CP_NUM > 0
  318. .global _xt_coproc_release
  319. .type _xt_coproc_release,@function
  320. .align 4
  321. .literal_position
  322. .align 4
  323. _xt_coproc_release:
  324. ENTRY0 /* a2 = base of save area */
  325. getcoreid a5
  326. movi a3, XCHAL_CP_MAX << 2
  327. mull a5, a5, a3
  328. movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */
  329. add a3, a3, a5
  330. addi a4, a3, XCHAL_CP_MAX << 2 /* a4 = top+1 of owner array */
  331. movi a5, 0 /* a5 = 0 (unowned) */
  332. rsil a6, XCHAL_EXCM_LEVEL /* lock interrupts */
  333. 1: l32i a7, a3, 0 /* a7 = owner at a3 */
  334. bne a2, a7, 2f /* if (coproc_sa_base == owner) */
  335. s32i a5, a3, 0 /* owner = unowned */
  336. 2: addi a3, a3, 1<<2 /* a3 = next entry in owner array */
  337. bltu a3, a4, 1b /* repeat until end of array */
  338. 3: wsr a6, PS /* restore interrupts */
  339. RET0
  340. #endif
  341. /*******************************************************************************
  342. _xt_coproc_savecs
  343. If there is a current thread and it has a coprocessor state save area, then
  344. save all callee-saved state into this area. This function is called from the
  345. solicited context switch handler. It calls a system-specific function to get
  346. the coprocessor save area base address.
  347. Entry conditions:
  348. - The thread being switched out is still the current thread.
  349. - CPENABLE state reflects which coprocessors are active.
  350. - Registers have been saved/spilled already.
  351. Exit conditions:
  352. - All necessary CP callee-saved state has been saved.
  353. - Registers a2-a7, a13-a15 have been trashed.
  354. Must be called from assembly code only, using CALL0.
  355. *******************************************************************************/
  356. #if XCHAL_CP_NUM > 0
  357. .extern _xt_coproc_sa_offset /* external reference */
  358. .global _xt_coproc_savecs
  359. .type _xt_coproc_savecs,@function
  360. .align 4
  361. .literal_position
  362. .align 4
  363. _xt_coproc_savecs:
  364. /* At entry, CPENABLE should be showing which CPs are enabled. */
  365. rsr a2, CPENABLE /* a2 = which CPs are enabled */
  366. beqz a2, .Ldone /* quick exit if none */
  367. mov a14, a0 /* save return address */
  368. call0 XT_RTOS_CP_STATE /* get address of CP save area */
  369. mov a0, a14 /* restore return address */
  370. beqz a15, .Ldone /* if none then nothing to do */
  371. s16i a2, a15, XT_CP_CS_ST /* save mask of CPs being stored */
  372. movi a13, _xt_coproc_sa_offset /* array of CP save offsets */
  373. l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */
  374. #if XCHAL_CP0_SA_SIZE
  375. bbci.l a2, 0, 2f /* CP 0 not enabled */
  376. l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */
  377. add a3, a14, a15 /* a3 = save area for CP 0 */
  378. xchal_cp0_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  379. 2:
  380. #endif
  381. #if XCHAL_CP1_SA_SIZE
  382. bbci.l a2, 1, 2f /* CP 1 not enabled */
  383. l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */
  384. add a3, a14, a15 /* a3 = save area for CP 1 */
  385. xchal_cp1_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  386. 2:
  387. #endif
  388. #if XCHAL_CP2_SA_SIZE
  389. bbci.l a2, 2, 2f
  390. l32i a14, a13, 8
  391. add a3, a14, a15
  392. xchal_cp2_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  393. 2:
  394. #endif
  395. #if XCHAL_CP3_SA_SIZE
  396. bbci.l a2, 3, 2f
  397. l32i a14, a13, 12
  398. add a3, a14, a15
  399. xchal_cp3_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  400. 2:
  401. #endif
  402. #if XCHAL_CP4_SA_SIZE
  403. bbci.l a2, 4, 2f
  404. l32i a14, a13, 16
  405. add a3, a14, a15
  406. xchal_cp4_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  407. 2:
  408. #endif
  409. #if XCHAL_CP5_SA_SIZE
  410. bbci.l a2, 5, 2f
  411. l32i a14, a13, 20
  412. add a3, a14, a15
  413. xchal_cp5_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  414. 2:
  415. #endif
  416. #if XCHAL_CP6_SA_SIZE
  417. bbci.l a2, 6, 2f
  418. l32i a14, a13, 24
  419. add a3, a14, a15
  420. xchal_cp6_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  421. 2:
  422. #endif
  423. #if XCHAL_CP7_SA_SIZE
  424. bbci.l a2, 7, 2f
  425. l32i a14, a13, 28
  426. add a3, a14, a15
  427. xchal_cp7_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  428. 2:
  429. #endif
  430. .Ldone:
  431. ret
  432. #endif
  433. /*******************************************************************************
  434. _xt_coproc_restorecs
  435. Restore any callee-saved coprocessor state for the incoming thread.
  436. This function is called from coprocessor exception handling, when giving
  437. ownership to a thread that solicited a context switch earlier. It calls a
  438. system-specific function to get the coprocessor save area base address.
  439. Entry conditions:
  440. - The incoming thread is set as the current thread.
  441. - CPENABLE is set up correctly for all required coprocessors.
  442. - a2 = mask of coprocessors to be restored.
  443. Exit conditions:
  444. - All necessary CP callee-saved state has been restored.
  445. - CPENABLE - unchanged.
  446. - Registers a2-a7, a13-a15 have been trashed.
  447. Must be called from assembly code only, using CALL0.
  448. *******************************************************************************/
  449. #if XCHAL_CP_NUM > 0
  450. .global _xt_coproc_restorecs
  451. .type _xt_coproc_restorecs,@function
  452. .align 4
  453. .literal_position
  454. .align 4
  455. _xt_coproc_restorecs:
  456. mov a14, a0 /* save return address */
  457. call0 XT_RTOS_CP_STATE /* get address of CP save area */
  458. mov a0, a14 /* restore return address */
  459. beqz a15, .Ldone2 /* if none then nothing to do */
  460. l16ui a3, a15, XT_CP_CS_ST /* a3 = which CPs have been saved */
  461. xor a3, a3, a2 /* clear the ones being restored */
  462. s32i a3, a15, XT_CP_CS_ST /* update saved CP mask */
  463. movi a13, _xt_coproc_sa_offset /* array of CP save offsets */
  464. l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */
  465. #if XCHAL_CP0_SA_SIZE
  466. bbci.l a2, 0, 2f /* CP 0 not enabled */
  467. l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */
  468. add a3, a14, a15 /* a3 = save area for CP 0 */
  469. xchal_cp0_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  470. 2:
  471. #endif
  472. #if XCHAL_CP1_SA_SIZE
  473. bbci.l a2, 1, 2f /* CP 1 not enabled */
  474. l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */
  475. add a3, a14, a15 /* a3 = save area for CP 1 */
  476. xchal_cp1_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  477. 2:
  478. #endif
  479. #if XCHAL_CP2_SA_SIZE
  480. bbci.l a2, 2, 2f
  481. l32i a14, a13, 8
  482. add a3, a14, a15
  483. xchal_cp2_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  484. 2:
  485. #endif
  486. #if XCHAL_CP3_SA_SIZE
  487. bbci.l a2, 3, 2f
  488. l32i a14, a13, 12
  489. add a3, a14, a15
  490. xchal_cp3_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  491. 2:
  492. #endif
  493. #if XCHAL_CP4_SA_SIZE
  494. bbci.l a2, 4, 2f
  495. l32i a14, a13, 16
  496. add a3, a14, a15
  497. xchal_cp4_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  498. 2:
  499. #endif
  500. #if XCHAL_CP5_SA_SIZE
  501. bbci.l a2, 5, 2f
  502. l32i a14, a13, 20
  503. add a3, a14, a15
  504. xchal_cp5_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  505. 2:
  506. #endif
  507. #if XCHAL_CP6_SA_SIZE
  508. bbci.l a2, 6, 2f
  509. l32i a14, a13, 24
  510. add a3, a14, a15
  511. xchal_cp6_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  512. 2:
  513. #endif
  514. #if XCHAL_CP7_SA_SIZE
  515. bbci.l a2, 7, 2f
  516. l32i a14, a13, 28
  517. add a3, a14, a15
  518. xchal_cp7_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
  519. 2:
  520. #endif
  521. .Ldone2:
  522. ret
  523. #endif