| /* |
| * Copyright (c) 2016 Cadence Design Systems, Inc. |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /* XTENSA CONTEXT SAVE AND RESTORE ROUTINES |
| * |
| * Low-level Call0 functions for handling generic context save and restore of |
| * registers not specifically addressed by the interrupt vectors and handlers. |
| * Those registers (not handled by these functions) are PC, PS, A0, A1 (SP). |
| * Except for the calls to RTOS functions, this code is generic to Xtensa. |
| * |
| * Note that in Call0 ABI, interrupt handlers are expected to preserve the |
| * callee-save regs (A12-A15), which is always the case if the handlers are |
| * coded in C. However A12, A13 are made available as scratch registers for |
| * interrupt dispatch code, so are presumed saved anyway, and are always |
| * restored even in Call0 ABI. Only A14, A15 are truly handled as callee-save |
| * regs. |
| * |
| * Because Xtensa is a configurable architecture, this port supports all user |
| * generated configurations (except restrictions stated in the release notes). |
| * This is accomplished by conditional compilation using macros and functions |
| * defined in the Xtensa HAL (hardware adaptation layer) for your |
| * configuration. Only the processor state included in your configuration is |
| * saved and restored, including any processor state added by user |
| * configuration options or TIE. |
| */ |
| |
| /* Warn nicely if this file gets named with a lowercase .s instead of .S: */ |
| #define NOERROR # |
| NOERROR: .error "C preprocessor needed for this file: make sure its filename\ |
| ends in uppercase .S, or use xt-xcc's -x assembler-with-cpp option." |
| |
| |
| #include "xtensa_rtos.h" |
| |
| #ifdef XT_USE_OVLY |
| #include <xtensa/overlay_os_asm.h> |
| #endif |
| |
| .text |
| |
| /* |
| * _xt_context_save |
| * |
| * !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !! |
| * |
| * Saves all Xtensa processor state except PC, PS, A0, A1 (SP), A12, A13, in |
| * the interrupt stack frame defined in xtensa_rtos.h. Its counterpart is |
| * _xt_context_restore (which also restores A12, A13). |
| * |
| * Caller is expected to have saved PC, PS, A0, A1 (SP), A12, A13 in the frame. |
| * This function preserves A12 & A13 in order to provide the caller with 2 |
| * scratch regs that need not be saved over the call to this function. The |
| * choice of which 2 regs to provide is governed by xthal_window_spill_nw and |
| * xthal_save_extra_nw, to avoid moving data more than necessary. Caller can |
| * assign regs accordingly. |
| * |
| * Entry Conditions: |
| * A0 = Return address in caller. |
| * A1 = Stack pointer of interrupted thread or handler ("interruptee"). |
| * Original A12, A13 have already been saved in the interrupt stack frame. |
| * Other processor state except PC, PS, A0, A1 (SP), A12, A13, is as at the |
| * point of interruption. |
| * If windowed ABI, PS.EXCM = 1 (exceptions disabled). |
| * |
| * Exit conditions: |
| * A0 = Return address in caller. |
| * A1 = Stack pointer of interrupted thread or handler ("interruptee"). |
| * A12, A13 as at entry (preserved). |
| * If windowed ABI, PS.EXCM = 1 (exceptions disabled). |
| */ |
| |
| .global _xt_context_save |
| .type _xt_context_save,@function |
| .align 4 |
| _xt_context_save: |
| |
| s32i a2, sp, XT_STK_a2 |
| s32i a3, sp, XT_STK_a3 |
| s32i a4, sp, XT_STK_a4 |
| s32i a5, sp, XT_STK_a5 |
| s32i a6, sp, XT_STK_a6 |
| s32i a7, sp, XT_STK_a7 |
| s32i a8, sp, XT_STK_a8 |
| s32i a9, sp, XT_STK_a9 |
| s32i a10, sp, XT_STK_a10 |
| s32i a11, sp, XT_STK_a11 |
| |
| /* Call0 ABI callee-saved regs a12-15 do not need to be saved here. a12-13 |
| * are the caller's responsibility so it can use them as scratch. So only |
| * need to save a14-a15 here for Windowed ABI (not Call0). |
| */ |
| #ifndef __XTENSA_CALL0_ABI__ |
| s32i a14, sp, XT_STK_a14 |
| s32i a15, sp, XT_STK_a15 |
| #endif |
| |
| rsr a3, SAR |
| s32i a3, sp, XT_STK_sar |
| |
| #if XCHAL_HAVE_LOOPS |
| rsr a3, LBEG |
| s32i a3, sp, XT_STK_lbeg |
| rsr a3, LEND |
| s32i a3, sp, XT_STK_lend |
| rsr a3, LCOUNT |
| s32i a3, sp, XT_STK_lcount |
| #endif |
| |
| #if XT_USE_SWPRI |
| /* Save virtual priority mask */ |
| movi a3, _xt_vpri_mask |
| l32i a3, a3, 0 |
| s32i a3, sp, XT_STK_VPRI |
| #endif |
| |
| #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__) |
| mov a9, a0 /* preserve ret addr */ |
| #endif |
| |
| #ifndef __XTENSA_CALL0_ABI__ |
| /* To spill the reg windows, temp. need pre-interrupt stack ptr and a4-15. |
| * Need to save a9,12,13 temporarily (in frame temps) and recover |
| * originals. Interrupts need to be disabled below XCHAL_EXCM_LEVEL and |
| * window overflow and underflow exceptions disabled (assured by PS.EXCM == |
| * 1). |
| */ |
| s32i a12, sp, XT_STK_tmp0 /* temp. save stuff in stack frame */ |
| s32i a13, sp, XT_STK_tmp1 |
| s32i a9, sp, XT_STK_tmp2 |
| |
| /* Save the overlay state if we are supporting overlays. Since we just |
| * saved three registers, we can conveniently use them here. Note that as |
| * of now, overlays only work for windowed calling ABI. |
| */ |
| #ifdef XT_USE_OVLY |
| l32i a9, sp, XT_STK_PC /* recover saved PC */ |
| _xt_overlay_get_state a9, a12, a13 |
| s32i a9, sp, XT_STK_OVLY /* save overlay state */ |
| #endif |
| |
| l32i a12, sp, XT_STK_a12 /* recover original a9,12,13 */ |
| l32i a13, sp, XT_STK_a13 |
| l32i a9, sp, XT_STK_a9 |
| addi sp, sp, XT_STK_FRMSZ /* restore the interruptee's SP */ |
| call0 xthal_window_spill_nw /* preserves only a4,5,8,9,12,13 */ |
| addi sp, sp, -XT_STK_FRMSZ |
| l32i a12, sp, XT_STK_tmp0 /* recover stuff from stack frame */ |
| l32i a13, sp, XT_STK_tmp1 |
| l32i a9, sp, XT_STK_tmp2 |
| #endif |
| |
| #if XCHAL_EXTRA_SA_SIZE > 0 |
| /* NOTE: Normally the xthal_save_extra_nw macro only affects address |
| * registers a2-a5. It is theoretically possible for Xtensa processor |
| * designers to write TIE that causes more address registers to be |
| * affected, but it is generally unlikely. If that ever happens, more |
| * registers need to be saved/restored around this macro invocation. Here |
| * we assume a9,12,13 are preserved. Future Xtensa tools releases might |
| * limit the regs that can be affected. |
| */ |
| addi a2, sp, XT_STK_EXTRA /* where to save it */ |
| # if XCHAL_EXTRA_SA_ALIGN > 16 |
| movi a3, -XCHAL_EXTRA_SA_ALIGN |
| and a2, a2, a3 /* align dynamically >16 bytes */ |
| # endif |
| call0 xthal_save_extra_nw /* destroys a0,2,3,4,5 */ |
| #endif |
| |
| #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__) |
| mov a0, a9 /* retrieve ret addr */ |
| #endif |
| |
| ret |
| |
| /*_xt_context_restore |
| * |
| * !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !! |
| * |
| * Restores all Xtensa processor state except PC, PS, A0, A1 (SP) (and in Call0 |
| * ABI, A14, A15 which are preserved by all interrupt handlers) from an |
| * interrupt stack frame defined in xtensa_rtos.h. Its counterpart is |
| * _xt_context_save (whose caller saved A12, A13). |
| * |
| * Caller is responsible to restore PC, PS, A0, A1 (SP). |
| * |
| * Entry Conditions: |
| * A0 = Return address in caller. |
| * A1 = Stack pointer of interrupted thread or handler ("interruptee"). |
| * |
| * Exit conditions: |
| * A0 = Return address in caller. |
| * A1 = Stack pointer of interrupted thread or handler ("interruptee"). |
| * Other processor state except PC, PS, A0, A1 (SP), is as at the point |
| * of interruption. |
| */ |
| |
| .global _xt_context_restore |
| .type _xt_context_restore,@function |
| .align 4 |
| _xt_context_restore: |
| |
| #if XCHAL_EXTRA_SA_SIZE > 0 |
| /* NOTE: Normally the xthal_restore_extra_nw macro only affects address |
| * registers a2-a5. It is theoretically possible for Xtensa processor |
| * designers to write TIE that causes more address registers to be |
| * affected, but it is generally unlikely. If that ever happens, more |
| * registers need to be saved/restored around this macro invocation. Here |
| * we only assume a13 is preserved. Future Xtensa tools releases might |
| * limit the regs that can be affected. |
| */ |
| mov a13, a0 /* preserve ret addr */ |
| addi a2, sp, XT_STK_EXTRA /* where to find it */ |
| # if XCHAL_EXTRA_SA_ALIGN > 16 |
| movi a3, -XCHAL_EXTRA_SA_ALIGN |
| and a2, a2, a3 /* align dynamically >16 bytes */ |
| # endif |
| call0 xthal_restore_extra_nw /* destroys a0,2,3,4,5 */ |
| mov a0, a13 /* retrieve ret addr */ |
| #endif |
| |
| #if XCHAL_HAVE_LOOPS |
| l32i a2, sp, XT_STK_lbeg |
| l32i a3, sp, XT_STK_lend |
| wsr a2, LBEG |
| l32i a2, sp, XT_STK_lcount |
| wsr a3, LEND |
| wsr a2, LCOUNT |
| #endif |
| |
| #ifdef XT_USE_OVLY |
| /* If we are using overlays, this is a good spot to check if we need to |
| * restore an overlay for the incoming task. Here we have a bunch of |
| * registers to spare. Note that this step is going to use a few bytes of |
| * storage below SP (SP-20 to SP-32) if an overlay is going to be |
| * restored. |
| */ |
| l32i a2, sp, XT_STK_pc /* retrieve PC */ |
| l32i a3, sp, XT_STK_ps /* retrieve PS */ |
| l32i a4, sp, XT_STK_ovly /* retrieve overlay state */ |
| l32i a5, sp, XT_STK_a1 /* retrieve stack ptr */ |
| _xt_overlay_check_map a2, a3, a4, a5, a6 |
| s32i a2, sp, XT_STK_pc /* save updated PC */ |
| s32i a3, sp, XT_STK_ps /* save updated PS */ |
| #endif |
| |
| #ifdef XT_USE_SWPRI |
| /* Restore virtual interrupt priority and interrupt enable */ |
| movi a3, _xt_intdata |
| l32i a4, a3, 0 /* a4 = _xt_intenable */ |
| l32i a5, sp, XT_STK_VPRI /* a5 = saved _xt_vpri_mask */ |
| and a4, a4, a5 |
| wsr a4, INTENABLE /* update INTENABLE */ |
| s32i a5, a3, 4 /* restore _xt_vpri_mask */ |
| #endif |
| |
| l32i a3, sp, XT_STK_sar |
| l32i a2, sp, XT_STK_a2 |
| wsr a3, SAR |
| l32i a3, sp, XT_STK_a3 |
| l32i a4, sp, XT_STK_a4 |
| l32i a5, sp, XT_STK_a5 |
| l32i a6, sp, XT_STK_a6 |
| l32i a7, sp, XT_STK_a7 |
| l32i a8, sp, XT_STK_a8 |
| l32i a9, sp, XT_STK_a9 |
| l32i a10, sp, XT_STK_a10 |
| l32i a11, sp, XT_STK_a11 |
| |
| /* |
| * Call0 ABI callee-saved regs a12-15 do not need to be restored here. |
| * However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(), |
| * so need to be restored anyway, despite being callee-saved in Call0. |
| */ |
| l32i a12, sp, XT_STK_a12 |
| l32i a13, sp, XT_STK_a13 |
| #ifndef __XTENSA_CALL0_ABI__ |
| l32i a14, sp, XT_STK_a14 |
| l32i a15, sp, XT_STK_a15 |
| #endif |
| |
| ret |
| |
| |
| /* _xt_coproc_init |
| * |
| * Initializes global co-processor management data, setting all co-processors |
| * to "unowned". Leaves CPENABLE as it found it (does NOT clear it). |
| * |
| * Called during initialization of the RTOS, before any threads run. |
| * |
| * This may be called from normal Xtensa single-threaded application code which |
| * might use co-processors. The Xtensa run-time initialization enables all |
| * co-processors. They must remain enabled here, else a co-processor exception |
| * might occur outside of a thread, which the exception handler doesn't expect. |
| * |
| * Entry Conditions: |
| * Xtensa single-threaded run-time environment is in effect. |
| * No thread is yet running. |
| * |
| * Exit conditions: |
| * None. |
| * |
| * Obeys ABI conventions per prototype: |
| * void _xt_coproc_init(void) |
| */ |
| |
| #if XCHAL_CP_NUM > 0 |
| |
| .global _xt_coproc_init |
| .type _xt_coproc_init,@function |
| .align 4 |
| _xt_coproc_init: |
| ENTRY0 |
| |
| /* Initialize thread co-processor ownerships to 0 (unowned). */ |
| movi a2, _xt_coproc_owner_sa /* a2 = base of owner array */ |
| addi a3, a2, XCHAL_CP_MAX << 2 /* a3 = top+1 of owner array */ |
| movi a4, 0 /* a4 = 0 (unowned) */ |
| 1: s32i a4, a2, 0 |
| addi a2, a2, 4 |
| bltu a2, a3, 1b |
| |
| RET0 |
| |
| #endif |
| |
| |
| /* _xt_coproc_release |
| * |
| * Releases any and all co-processors owned by a given thread. The thread is |
| * identified by it's co-processor state save area defined in xtensa_context.h |
| * |
| * Must be called before a thread's co-proc save area is deleted to avoid |
| * memory corruption when the exception handler tries to save the state. |
| * May be called when a thread terminates or completes but does not delete |
| * the co-proc save area, to avoid the exception handler having to save the |
| * thread's co-proc state before another thread can use it (optimization). |
| * |
| * Entry Conditions: |
| * A2 = Pointer to base of co-processor state save area. |
| * |
| * Exit conditions: |
| * None. |
| * |
| * Obeys ABI conventions per prototype: |
| * void _xt_coproc_release(void * coproc_sa_base) |
| */ |
| |
| #if XCHAL_CP_NUM > 0 |
| |
| .global _xt_coproc_release |
| .type _xt_coproc_release,@function |
| .align 4 |
| _xt_coproc_release: |
| ENTRY0 /* a2 = base of save area */ |
| |
| movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */ |
| addi a4, a3, XCHAL_CP_MAX << 2 /* a4 = top+1 of owner array */ |
| movi a5, 0 /* a5 = 0 (unowned) */ |
| |
| rsil a6, XCHAL_EXCM_LEVEL /* lock interrupts */ |
| |
| 1: l32i a7, a3, 0 /* a7 = owner at a3 */ |
| bne a2, a7, 2f /* if (coproc_sa_base == owner) */ |
| s32i a5, a3, 0 /* owner = unowned */ |
| 2: addi a3, a3, 1<<2 /* a3 = next entry in owner array */ |
| bltu a3, a4, 1b /* repeat until end of array */ |
| |
| 3: wsr a6, PS /* restore interrupts */ |
| |
| RET0 |
| |
| #endif |
| |
| |
| /* _xt_coproc_savecs |
| * |
| * If there is a current thread and it has a coprocessor state save area, then |
| * save all callee-saved state into this area. This function is called from the |
| * solicited context switch handler. It calls a system-specific function to get |
| * the coprocessor save area base address. |
| * |
| * Entry conditions: |
| * - The thread being switched out is still the current thread. |
| * - CPENABLE state reflects which coprocessors are active. |
| * - Registers have been saved/spilled already. |
| * |
| * Exit conditions: |
| * - All necessary CP callee-saved state has been saved. |
| * - Registers a2-a7, a13-a15 have been trashed. |
| * |
| * Must be called from assembly code only, using CALL0. |
| */ |
| |
| #if XCHAL_CP_NUM > 0 |
| |
| .extern _xt_coproc_sa_offset /* external reference */ |
| |
| .global _xt_coproc_savecs |
| .type _xt_coproc_savecs,@function |
| .align 4 |
| _xt_coproc_savecs: |
| |
| /* At entry, CPENABLE should be showing which CPs are enabled. */ |
| |
| rsr a2, CPENABLE /* a2 = which CPs are enabled */ |
| beqz a2, .Ldone /* quick exit if none */ |
| mov a14, a0 /* save return address */ |
| call0 XT_RTOS_CP_STATE /* get address of CP save area */ |
| mov a0, a14 /* restore return address */ |
| beqz a15, .Ldone /* if none then nothing to do */ |
| s16i a2, a15, XT_CP_CS_ST /* save mask of CPs being stored */ |
| movi a13, _xt_coproc_sa_offset /* array of CP save offsets */ |
| l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */ |
| |
| #if XCHAL_CP0_SA_SIZE |
| bbci.l a2, 0, 2f /* CP 0 not enabled */ |
| l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */ |
| add a3, a14, a15 /* a3 = save area for CP 0 */ |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP1_SA_SIZE |
| bbci.l a2, 1, 2f /* CP 1 not enabled */ |
| l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */ |
| add a3, a14, a15 /* a3 = save area for CP 1 */ |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP2_SA_SIZE |
| bbci.l a2, 2, 2f |
| l32i a14, a13, 8 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP3_SA_SIZE |
| bbci.l a2, 3, 2f |
| l32i a14, a13, 12 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP4_SA_SIZE |
| bbci.l a2, 4, 2f |
| l32i a14, a13, 16 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP5_SA_SIZE |
| bbci.l a2, 5, 2f |
| l32i a14, a13, 20 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP6_SA_SIZE |
| bbci.l a2, 6, 2f |
| l32i a14, a13, 24 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP7_SA_SIZE |
| bbci.l a2, 7, 2f |
| l32i a14, a13, 28 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| .Ldone: |
| ret |
| #endif |
| |
| |
| /* |
| * _xt_coproc_restorecs |
| * |
| * Restore any callee-saved coprocessor state for the incoming thread. |
| * This function is called from coprocessor exception handling, when giving |
| * ownership to a thread that solicited a context switch earlier. It calls a |
| * system-specific function to get the coprocessor save area base address. |
| * |
| * Entry conditions: |
| * - The incoming thread is set as the current thread. |
| * - CPENABLE is set up correctly for all required coprocessors. |
| * - a2 = mask of coprocessors to be restored. |
| * |
| * Exit conditions: |
| * - All necessary CP callee-saved state has been restored. |
| * - CPENABLE - unchanged. |
| * - Registers a2-a7, a13-a15 have been trashed. |
| * |
| * Must be called from assembly code only, using CALL0. |
| */ |
| |
| #if XCHAL_CP_NUM > 0 |
| |
| .global _xt_coproc_restorecs |
| .type _xt_coproc_restorecs,@function |
| .align 4 |
| _xt_coproc_restorecs: |
| |
| mov a14, a0 /* save return address */ |
| call0 XT_RTOS_CP_STATE /* get address of CP save area */ |
| mov a0, a14 /* restore return address */ |
| beqz a15, .Ldone2 /* if none then nothing to do */ |
| l16ui a3, a15, XT_CP_CS_ST /* a3 = which CPs have been saved */ |
| xor a3, a3, a2 /* clear the ones being restored */ |
| s32i a3, a15, XT_CP_CS_ST /* update saved CP mask */ |
| movi a13, _xt_coproc_sa_offset /* array of CP save offsets */ |
| l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */ |
| |
| #if XCHAL_CP0_SA_SIZE |
| bbci.l a2, 0, 2f /* CP 0 not enabled */ |
| l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */ |
| add a3, a14, a15 /* a3 = save area for CP 0 */ |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP1_SA_SIZE |
| bbci.l a2, 1, 2f /* CP 1 not enabled */ |
| l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */ |
| add a3, a14, a15 /* a3 = save area for CP 1 */ |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP2_SA_SIZE |
| bbci.l a2, 2, 2f |
| l32i a14, a13, 8 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP3_SA_SIZE |
| bbci.l a2, 3, 2f |
| l32i a14, a13, 12 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP4_SA_SIZE |
| bbci.l a2, 4, 2f |
| l32i a14, a13, 16 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP5_SA_SIZE |
| bbci.l a2, 5, 2f |
| l32i a14, a13, 20 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP6_SA_SIZE |
| bbci.l a2, 6, 2f |
| l32i a14, a13, 24 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| #if XCHAL_CP7_SA_SIZE |
| bbci.l a2, 7, 2f |
| l32i a14, a13, 28 |
| add a3, a14, a15 |
| 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 |
| 2: |
| #endif |
| |
| .Ldone2: |
| ret |
| |
| #endif |
| |