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