| /* |
| * Copyright (c) 2017, Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| #ifndef ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ |
| #define ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ |
| |
| #include <xtensa/corebits.h> |
| #include <xtensa/config/core-isa.h> |
| |
| /* |
| * Stack frame layout for a saved processor context, in memory order, |
| * high to low address: |
| * |
| * SP-0 <-- Interrupted stack pointer points here |
| * |
| * SP-4 Caller A3 spill slot \ |
| * SP-8 Caller A2 spill slot | |
| * SP-12 Caller A1 spill slot + (Part of ABI standard) |
| * SP-16 Caller A0 spill slot / |
| * |
| * SP-20 Saved A3 |
| * SP-24 Saved A2 |
| * SP-28 Unused (not "Saved A1" because the SP is saved externally as a handle) |
| * SP-32 Saved A0 |
| * |
| * SP-36 Saved PC (address to jump to following restore) |
| * SP-40 Saved/interrupted PS special register |
| * |
| * SP-44 Saved SAR special register |
| * |
| * SP-48 Saved LBEG special register (if loops enabled) |
| * SP-52 Saved LEND special register (if loops enabled) |
| * SP-56 Saved LCOUNT special register (if loops enabled) |
| * |
| * SP-60 Saved SCOMPARE special register (if S32C1I enabled) |
| * |
| * SP-64 Saved EXCCAUSE special register |
| * |
| * SP-68 Saved THREADPTR special register (if processor has thread pointer) |
| * |
| * (The above fixed-size region is known as the "base save area" in the |
| * code below) |
| * |
| * - 18 FPU registers (if FPU is present and CONFIG_FPU_SHARING enabled) |
| * |
| * - Saved A7 \ |
| * - Saved A6 | |
| * - Saved A5 +- If not in-use by another frame |
| * - Saved A4 / |
| * |
| * - Saved A11 \ |
| * - Saved A10 | |
| * - Saved A9 +- If not in-use by another frame |
| * - Saved A8 / |
| * |
| * - Saved A15 \ |
| * - Saved A14 | |
| * - Saved A13 +- If not in-use by another frame |
| * - Saved A12 / |
| * |
| * - Saved intermediate stack pointer (points to low word of base save |
| * area, i.e. the saved LCOUNT or SAR). The pointer to this value |
| * (i.e. the final stack pointer) is stored externally as the |
| * "restore handle" in the thread context. |
| * |
| * Essentially, you can recover a pointer to the BSA by loading *SP. |
| * Adding the fixed BSA size to that gets you back to the |
| * original/interrupted stack pointer. |
| */ |
| |
| #ifndef __ASSEMBLER__ |
| |
| #include <stdint.h> |
| #include <zephyr/toolchain.h> |
| |
| /** |
| * Base Save Area (BSA) during interrupt. |
| * |
| * This saves the registers during interrupt entrance |
| * so they can be restored later. |
| * |
| * Note that only A0-A3 are saved here. High registers |
| * are saved after the BSA. |
| */ |
| struct xtensa_irq_base_save_area { |
| #if XCHAL_HAVE_FP && defined(CONFIG_CPU_HAS_FPU) && defined(CONFIG_FPU_SHARING) |
| uintptr_t fcr; |
| uintptr_t fsr; |
| uintptr_t fpu0; |
| uintptr_t fpu1; |
| uintptr_t fpu2; |
| uintptr_t fpu3; |
| uintptr_t fpu4; |
| uintptr_t fpu5; |
| uintptr_t fpu6; |
| uintptr_t fpu7; |
| uintptr_t fpu8; |
| uintptr_t fpu9; |
| uintptr_t fpu10; |
| uintptr_t fpu11; |
| uintptr_t fpu12; |
| uintptr_t fpu13; |
| uintptr_t fpu14; |
| uintptr_t fpu15; |
| #endif |
| |
| #if XCHAL_HAVE_THREADPTR |
| uintptr_t threadptr; |
| #endif |
| |
| #if XCHAL_HAVE_S32C1I |
| uintptr_t scompare1; |
| #endif |
| |
| uintptr_t exccause; |
| |
| #if XCHAL_HAVE_LOOPS |
| uintptr_t lcount; |
| uintptr_t lend; |
| uintptr_t lbeg; |
| #endif |
| |
| uintptr_t sar; |
| uintptr_t ps; |
| uintptr_t pc; |
| uintptr_t a0; |
| uintptr_t scratch; |
| uintptr_t a2; |
| uintptr_t a3; |
| |
| uintptr_t caller_a0; |
| uintptr_t caller_a1; |
| uintptr_t caller_a2; |
| uintptr_t caller_a3; |
| }; |
| |
| typedef struct xtensa_irq_base_save_area _xtensa_irq_bsa_t; |
| |
| /** |
| * Raw interrupt stack frame. |
| * |
| * This provides a raw interrupt stack frame to make it |
| * easier to construct general purpose code in loops. |
| * Avoid using this if possible. |
| */ |
| struct xtensa_irq_stack_frame_raw { |
| _xtensa_irq_bsa_t *ptr_to_bsa; |
| |
| struct { |
| uintptr_t r0; |
| uintptr_t r1; |
| uintptr_t r2; |
| uintptr_t r3; |
| } blks[3]; |
| }; |
| |
| typedef struct xtensa_irq_stack_frame_raw _xtensa_irq_stack_frame_raw_t; |
| |
| /** |
| * Interrupt stack frame containing A0 - A15. |
| */ |
| struct xtensa_irq_stack_frame_a15 { |
| _xtensa_irq_bsa_t *ptr_to_bsa; |
| |
| uintptr_t a12; |
| uintptr_t a13; |
| uintptr_t a14; |
| uintptr_t a15; |
| |
| uintptr_t a8; |
| uintptr_t a9; |
| uintptr_t a10; |
| uintptr_t a11; |
| |
| uintptr_t a4; |
| uintptr_t a5; |
| uintptr_t a6; |
| uintptr_t a7; |
| |
| _xtensa_irq_bsa_t bsa; |
| }; |
| |
| typedef struct xtensa_irq_stack_frame_a15 _xtensa_irq_stack_frame_a15_t; |
| |
| /** |
| * Interrupt stack frame containing A0 - A11. |
| */ |
| struct xtensa_irq_stack_frame_a11 { |
| _xtensa_irq_bsa_t *ptr_to_bsa; |
| |
| uintptr_t a8; |
| uintptr_t a9; |
| uintptr_t a10; |
| uintptr_t a11; |
| |
| uintptr_t a4; |
| uintptr_t a5; |
| uintptr_t a6; |
| uintptr_t a7; |
| |
| _xtensa_irq_bsa_t bsa; |
| }; |
| |
| typedef struct xtensa_irq_stack_frame_a11 _xtensa_irq_stack_frame_a11_t; |
| |
| /** |
| * Interrupt stack frame containing A0 - A7. |
| */ |
| struct xtensa_irq_stack_frame_a7 { |
| _xtensa_irq_bsa_t *ptr_to_bsa; |
| |
| uintptr_t a4; |
| uintptr_t a5; |
| uintptr_t a6; |
| uintptr_t a7; |
| |
| _xtensa_irq_bsa_t bsa; |
| }; |
| |
| typedef struct xtensa_irq_stack_frame_a7 _xtensa_irq_stack_frame_a7_t; |
| |
| /** |
| * Interrupt stack frame containing A0 - A3. |
| */ |
| struct xtensa_irq_stack_frame_a3 { |
| _xtensa_irq_bsa_t *ptr_to_bsa; |
| |
| _xtensa_irq_bsa_t bsa; |
| }; |
| |
| typedef struct xtensa_irq_stack_frame_a3 _xtensa_irq_stack_frame_a3_t; |
| |
| #endif /* __ASSEMBLER__ */ |
| |
| #endif /* ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ */ |