blob: 366bea47babe550998fdd682b736ebb090773313 [file] [log] [blame]
/*
* 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_ */