1 /* 2 * Copyright (c) 2017, Intel Corporation 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 #ifndef ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ 7 #define ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ 8 9 #include <xtensa/corebits.h> 10 #include <xtensa/config/core-isa.h> 11 12 /* 13 * Stack frame layout for a saved processor context, in memory order, 14 * high to low address: 15 * 16 * SP-0 <-- Interrupted stack pointer points here 17 * 18 * SP-4 Caller A3 spill slot \ 19 * SP-8 Caller A2 spill slot | 20 * SP-12 Caller A1 spill slot + (Part of ABI standard) 21 * SP-16 Caller A0 spill slot / 22 * 23 * SP-20 Saved A3 24 * SP-24 Saved A2 25 * SP-28 Unused (not "Saved A1" because the SP is saved externally as a handle) 26 * SP-32 Saved A0 27 * 28 * SP-36 Saved PC (address to jump to following restore) 29 * SP-40 Saved/interrupted PS special register 30 * 31 * SP-44 Saved SAR special register 32 * 33 * SP-48 Saved LBEG special register (if loops enabled) 34 * SP-52 Saved LEND special register (if loops enabled) 35 * SP-56 Saved LCOUNT special register (if loops enabled) 36 * 37 * SP-60 Saved SCOMPARE special register (if S32C1I enabled) 38 * 39 * SP-64 Saved EXCCAUSE special register 40 * 41 * SP-68 Saved THREADPTR special register (if processor has thread pointer) 42 * 43 * (The above fixed-size region is known as the "base save area" in the 44 * code below) 45 * 46 * - 18 FPU registers (if FPU is present and CONFIG_FPU_SHARING enabled) 47 * 48 * - Saved A7 \ 49 * - Saved A6 | 50 * - Saved A5 +- If not in-use by another frame 51 * - Saved A4 / 52 * 53 * - Saved A11 \ 54 * - Saved A10 | 55 * - Saved A9 +- If not in-use by another frame 56 * - Saved A8 / 57 * 58 * - Saved A15 \ 59 * - Saved A14 | 60 * - Saved A13 +- If not in-use by another frame 61 * - Saved A12 / 62 * 63 * - Saved intermediate stack pointer (points to low word of base save 64 * area, i.e. the saved LCOUNT or SAR). The pointer to this value 65 * (i.e. the final stack pointer) is stored externally as the 66 * "restore handle" in the thread context. 67 * 68 * Essentially, you can recover a pointer to the BSA by loading *SP. 69 * Adding the fixed BSA size to that gets you back to the 70 * original/interrupted stack pointer. 71 */ 72 73 #ifndef __ASSEMBLER__ 74 75 #include <stdint.h> 76 #include <zephyr/toolchain.h> 77 78 /** 79 * Base Save Area (BSA) during interrupt. 80 * 81 * This saves the registers during interrupt entrance 82 * so they can be restored later. 83 * 84 * Note that only A0-A3 are saved here. High registers 85 * are saved after the BSA. 86 */ 87 struct xtensa_irq_base_save_area { 88 #if XCHAL_HAVE_FP && defined(CONFIG_CPU_HAS_FPU) && defined(CONFIG_FPU_SHARING) 89 uintptr_t fcr; 90 uintptr_t fsr; 91 uintptr_t fpu0; 92 uintptr_t fpu1; 93 uintptr_t fpu2; 94 uintptr_t fpu3; 95 uintptr_t fpu4; 96 uintptr_t fpu5; 97 uintptr_t fpu6; 98 uintptr_t fpu7; 99 uintptr_t fpu8; 100 uintptr_t fpu9; 101 uintptr_t fpu10; 102 uintptr_t fpu11; 103 uintptr_t fpu12; 104 uintptr_t fpu13; 105 uintptr_t fpu14; 106 uintptr_t fpu15; 107 #endif 108 109 #if XCHAL_HAVE_THREADPTR 110 uintptr_t threadptr; 111 #endif 112 113 #if XCHAL_HAVE_S32C1I 114 uintptr_t scompare1; 115 #endif 116 117 uintptr_t exccause; 118 119 #if XCHAL_HAVE_LOOPS 120 uintptr_t lcount; 121 uintptr_t lend; 122 uintptr_t lbeg; 123 #endif 124 125 uintptr_t sar; 126 uintptr_t ps; 127 uintptr_t pc; 128 uintptr_t a0; 129 uintptr_t scratch; 130 uintptr_t a2; 131 uintptr_t a3; 132 133 uintptr_t caller_a0; 134 uintptr_t caller_a1; 135 uintptr_t caller_a2; 136 uintptr_t caller_a3; 137 }; 138 139 typedef struct xtensa_irq_base_save_area _xtensa_irq_bsa_t; 140 141 /** 142 * Raw interrupt stack frame. 143 * 144 * This provides a raw interrupt stack frame to make it 145 * easier to construct general purpose code in loops. 146 * Avoid using this if possible. 147 */ 148 struct xtensa_irq_stack_frame_raw { 149 _xtensa_irq_bsa_t *ptr_to_bsa; 150 151 struct { 152 uintptr_t r0; 153 uintptr_t r1; 154 uintptr_t r2; 155 uintptr_t r3; 156 } blks[3]; 157 }; 158 159 typedef struct xtensa_irq_stack_frame_raw _xtensa_irq_stack_frame_raw_t; 160 161 /** 162 * Interrupt stack frame containing A0 - A15. 163 */ 164 struct xtensa_irq_stack_frame_a15 { 165 _xtensa_irq_bsa_t *ptr_to_bsa; 166 167 uintptr_t a12; 168 uintptr_t a13; 169 uintptr_t a14; 170 uintptr_t a15; 171 172 uintptr_t a8; 173 uintptr_t a9; 174 uintptr_t a10; 175 uintptr_t a11; 176 177 uintptr_t a4; 178 uintptr_t a5; 179 uintptr_t a6; 180 uintptr_t a7; 181 182 _xtensa_irq_bsa_t bsa; 183 }; 184 185 typedef struct xtensa_irq_stack_frame_a15 _xtensa_irq_stack_frame_a15_t; 186 187 /** 188 * Interrupt stack frame containing A0 - A11. 189 */ 190 struct xtensa_irq_stack_frame_a11 { 191 _xtensa_irq_bsa_t *ptr_to_bsa; 192 193 uintptr_t a8; 194 uintptr_t a9; 195 uintptr_t a10; 196 uintptr_t a11; 197 198 uintptr_t a4; 199 uintptr_t a5; 200 uintptr_t a6; 201 uintptr_t a7; 202 203 _xtensa_irq_bsa_t bsa; 204 }; 205 206 typedef struct xtensa_irq_stack_frame_a11 _xtensa_irq_stack_frame_a11_t; 207 208 /** 209 * Interrupt stack frame containing A0 - A7. 210 */ 211 struct xtensa_irq_stack_frame_a7 { 212 _xtensa_irq_bsa_t *ptr_to_bsa; 213 214 uintptr_t a4; 215 uintptr_t a5; 216 uintptr_t a6; 217 uintptr_t a7; 218 219 _xtensa_irq_bsa_t bsa; 220 }; 221 222 typedef struct xtensa_irq_stack_frame_a7 _xtensa_irq_stack_frame_a7_t; 223 224 /** 225 * Interrupt stack frame containing A0 - A3. 226 */ 227 struct xtensa_irq_stack_frame_a3 { 228 _xtensa_irq_bsa_t *ptr_to_bsa; 229 230 _xtensa_irq_bsa_t bsa; 231 }; 232 233 typedef struct xtensa_irq_stack_frame_a3 _xtensa_irq_stack_frame_a3_t; 234 235 #endif /* __ASSEMBLER__ */ 236 237 #endif /* ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_CONTEXT_H_ */ 238