blob: 2e4e045342b5e30f18ed43ba38176e3c97733d4c [file] [log] [blame]
/****************************************************************************
* arch/xtensa/src/common/xtensa_coproc.S
*
* SPDX-License-Identifier: MIT
* SPDX-FileCopyrightText: 2016 Gregory Nutt. All rights reserved.
* SPDX-FileCopyrightText: 2006-2015 Cadence Design Systems Inc.
* SPDX-FileContributor: Gregory Nutt <gnutt@nuttx.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
****************************************************************************/
.file "xtensa_coproc.S"
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <arch/irq.h>
#include <arch/xtensa/core.h>
#include <arch/xtensa/xtensa_abi.h>
#include <arch/xtensa/xtensa_coproc.h>
#include <arch/xtensa/xtensa_specregs.h>
#include <arch/chip/core-isa.h>
#include <arch/chip/tie.h>
#include <arch/chip/tie-asm.h>
/****************************************************************************
* Public Data
****************************************************************************/
.section .rodata, "a"
/* Offset to CP n save area in thread's CP save area. */
.global _xtensa_coproc_saoffsets
.type _xtensa_coproc_saoffsets, @object
.align 16 /* Minimize crossing cache boundaries */
_xtensa_coproc_saoffsets:
.word XTENSA_CP0_SA, XTENSA_CP1_SA, XTENSA_CP2_SA, XTENSA_CP3_SA
.word XTENSA_CP4_SA, XTENSA_CP5_SA, XTENSA_CP6_SA, XTENSA_CP7_SA
.size _xtensa_coproc_saoffsets, . - _xtensa_coproc_saoffsets
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Macro: xtensa_coproc_savestate
*
* Description:
* 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.
*
* It is also called from xtensa_coproc_savestate() for synchronous
* context switches. xtensa_coproc_savestate() is simply a C wrapper
* around the assembly language call to _xtensa_coproc_savestate.
*
* Entry Conditions:
* - Registers have been saved/spilled already.
*
* Exit conditions:
* - All necessary CP callee-saved state has been saved.
* - Registers a2-a7, a13-a14 have been trashed.
*
****************************************************************************/
.macro xtensa_coproc_savestate
/* The stack when interrupt happened
* ----------------------------------------------------
* | Reserve area (0x20) |
* ----------------------------------------------------
* | Coproc context |
* ----------------------------------------------------
* | Xtensa common regs |
* ---------------------------------------------------| <- SP
*/
addi a3, sp, (4 * COMMON_CTX_REGS)
/* CPENABLE should show which CPs are enabled. */
rsr a2, CPENABLE /* a2 = which CPs are enabled */
beqz a2, Ldone1 /* Quick exit if none */
movi a13, _xtensa_coproc_saoffsets /* Array of CP save offsets */
#if XCHAL_CP0_SA_SIZE > 0
bbci.l a2, 0, 2f /* CP 0 not enabled */
l32i a14, a13, 0 /* a14 = _xtensa_coproc_saoffsets[0] */
add a3, a14, a3 /* a3 = save area for CP 0 */
xchal_cp0_store a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP1_SA_SIZE > 0
bbci.l a2, 1, 2f /* CP 1 not enabled */
l32i a14, a13, 4 /* a14 = _xtensa_coproc_saoffsets[1] */
add a3, a14, a3 /* a3 = save area for CP 1 */
xchal_cp1_store a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP2_SA_SIZE > 0
bbci.l a2, 2, 2f
l32i a14, a13, 8
add a3, a14, a3
xchal_cp2_store a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP3_SA_SIZE > 0
bbci.l a2, 3, 2f
l32i a14, a13, 12
add a3, a14, a3
xchal_cp3_store a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP4_SA_SIZE > 0
bbci.l a2, 4, 2f
l32i a14, a13, 16
add a3, a14, a3
xchal_cp4_store a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP5_SA_SIZE > 0
bbci.l a2, 5, 2f
l32i a14, a13, 20
add a3, a14, a3
xchal_cp5_store a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP6_SA_SIZE > 0
bbci.l a2, 6, 2f
l32i a14, a13, 24
add a3, a14, a3
xchal_cp6_store a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP7_SA_SIZE > 0
bbci.l a2, 7, 2f
l32i a14, a13, 28
add a3, a14, a3
xchal_cp7_store a3, a4, a5, a6, a7
2:
#endif
Ldone1:
.endm
/****************************************************************************
* Macro: xtensa_coproc_restorestate
*
* Description:
* 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.
*
* It is also called from xtensa_coproc_restorestate() for synchronous
* context switches. xtensa_coproc_restorestate() is simply a C wrapper
* around the assembly language call to _xtensa_coproc_restorestate.
*
* Entry Conditions:
*
* Exit conditions:
* - All necessary CP callee-saved state has been restored.
* - Registers a3-a8, a13-a14 have been trashed.
*
****************************************************************************/
.macro xtensa_coproc_restorestate
/* The stack when interrupt happened (the register A2)
* ----------------------------------------------------
* | Reserve area (0x20) |
* ----------------------------------------------------
* | Coproc context |
* ----------------------------------------------------
* | Xtensa common regs |
* ---------------------------------------------------| <- SP
*/
addi a3, a2, (4 * COMMON_CTX_REGS)
rsr a8, CPENABLE /* a8 = which CPs are enabled */
beqz a8, Ldone2 /* Quick exit if none */
movi a13, _xtensa_coproc_saoffsets /* Array of CP save offsets */
#if XCHAL_CP0_SA_SIZE
bbci.l a8, 0, 2f /* CP 0 not enabled */
l32i a14, a13, 0 /* a14 = _xtensa_coproc_saoffsets[0] */
add a3, a14, a3 /* a3 = save area for CP 0 */
xchal_cp0_load a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP1_SA_SIZE
bbci.l a8, 1, 2f /* CP 1 not enabled */
l32i a14, a13, 4 /* a14 = _xtensa_coproc_saoffsets[1] */
add a3, a14, a3 /* a3 = save area for CP 1 */
xchal_cp1_load a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP2_SA_SIZE
bbci.l a8, 2, 2f
l32i a14, a13, 8
add a3, a14, a3
xchal_cp2_load a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP3_SA_SIZE
bbci.l a8, 3, 2f
l32i a14, a13, 12
add a3, a14, a3
xchal_cp3_load a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP4_SA_SIZE
bbci.l a8, 4, 2f
l32i a14, a13, 16
add a3, a14, a3
xchal_cp4_load a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP5_SA_SIZE
bbci.l a8, 5, 2f
l32i a14, a13, 20
add a3, a14, a3
xchal_cp5_load a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP6_SA_SIZE
bbci.l a8, 6, 2f
l32i a14, a13, 24
add a3, a14, a3
xchal_cp6_load a3, a4, a5, a6, a7
2:
#endif
#if XCHAL_CP7_SA_SIZE
bbci.l a8, 7, 2f
l32i a14, a13, 28
add a3, a14, a3
xchal_cp7_load a3, a4, a5, a6, a7
2:
#endif
/* Ensure wsr.CPENABLE has completed. */
rsync
Ldone2:
.endm