1 /* 2 * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #pragma once 8 9 #include "xtensa/xtruntime.h" 10 11 #define RSR(reg, at) __asm__ volatile ("rsr %0, %1" : "=r" (at) : "i" (reg)) 12 #define WSR(reg, at) __asm__ volatile ("wsr %0, %1" : : "r" (at), "i" (reg)) 13 #define XSR(reg, at) __asm__ volatile ("xsr %0, %1" : "+r" (at) : "i" (reg)) 14 15 #define RER(reg, at) __asm__ volatile ("rer %0, %1" : "=r" (at) : "r" (reg)) 16 17 #define WITLB(at, as) __asm__ volatile ("witlb %0, %1; \n isync \n " : : "r" (at), "r" (as)) 18 #define WDTLB(at, as) __asm__ volatile ("wdtlb %0, %1; \n dsync \n " : : "r" (at), "r" (as)) 19 20 #define EXTRA_SAVE_AREA_SIZE 32 21 #define BASE_SAVE_AREA_SIZE 16 22 #define SAVE_AREA_OFFSET (EXTRA_SAVE_AREA_SIZE + BASE_SAVE_AREA_SIZE) 23 #define BASE_AREA_SP_OFFSET 12 24 25 /* The SET_STACK implements a setting a new stack pointer (sp or a1). 26 * to do this the need reset PS_WOE, reset WINDOWSTART, update SP, and return PS_WOE. 27 * 28 * In addition, if a windowOverflow8/12 happens the exception handler expects to be able to look at 29 * the previous frames stackpointer to find the extra save area. So this function will reserve space 30 * for this area as well as initialise the previous sp that points to it 31 * 32 * Note: It has 2 implementations one for using in assembler files (*.S) and one for using in C. 33 * 34 * C code prototype for SET_STACK: 35 * uint32_t ps_reg; 36 * uint32_t w_base; 37 * 38 * uint32_t sp = (uint32_t)new_sp - SAVE_AREA_OFFSET; \ 39 *(uint32_t*)(sp - 12) = (uint32_t)new_sp; \ 40 41 * RSR(PS, ps_reg); 42 * ps_reg &= ~(PS_WOE_MASK | PS_OWB_MASK | PS_CALLINC_MASK); 43 * WSR(PS, ps_reg); 44 * 45 * RSR(WINDOWBASE, w_base); 46 * WSR(WINDOWSTART, (1 << w_base)); 47 * 48 * asm volatile ( "movi sp, "XTSTR( (SOC_DRAM_LOW + (SOC_DRAM_HIGH - SOC_DRAM_LOW) / 2) )""); 49 * 50 * RSR(PS, ps_reg); 51 * ps_reg |= (PS_WOE_MASK); 52 * WSR(PS, ps_reg); 53 */ 54 #ifdef __ASSEMBLER__ 55 .macro SET_STACK new_sp tmp1 tmp2 56 addi tmp1, new_sp, -SAVE_AREA_OFFSET 57 addi tmp2, tmp1, -BASE_AREA_SP_OFFSET 58 s32i new_sp, tmp2, 0 59 addi new_sp, tmp1, 0 60 rsr.ps \tmp1 61 movi \tmp2, ~(PS_WOE_MASK | PS_OWB_MASK | PS_CALLINC_MASK) 62 and \tmp1, \tmp1, \tmp2 63 wsr.ps \tmp1 64 rsync 65 66 rsr.windowbase \tmp1 67 ssl \tmp1 68 movi \tmp1, 1 69 sll \tmp1, \tmp1 70 wsr.windowstart \tmp1 71 rsync 72 73 mov sp, \new_sp 74 75 rsr.ps \tmp1 76 movi \tmp2, (PS_WOE) 77 or \tmp1, \tmp1, \tmp2 78 wsr.ps \tmp1 79 rsync 80 .endm 81 #else 82 83 #define SET_STACK(new_sp) \ 84 do { \ 85 uint32_t sp = (uint32_t)new_sp - SAVE_AREA_OFFSET; \ 86 *(uint32_t*)(sp - BASE_AREA_SP_OFFSET) = (uint32_t)new_sp; \ 87 const uint32_t mask = ~(PS_WOE_MASK | PS_OWB_MASK | PS_CALLINC_MASK); \ 88 uint32_t tmp1 = 0, tmp2 = 0; \ 89 __asm__ volatile ( \ 90 "rsr.ps %1 \n"\ 91 "and %1, %1, %3 \n"\ 92 "wsr.ps %1 \n"\ 93 "rsync \n"\ 94 " \n"\ 95 "rsr.windowbase %1 \n"\ 96 "ssl %1 \n"\ 97 "movi %1, 1 \n"\ 98 "sll %1, %1 \n"\ 99 "wsr.windowstart %1 \n"\ 100 "rsync \n"\ 101 " \n"\ 102 "movi a0, 0\n" \ 103 "mov sp, %0 \n"\ 104 "rsr.ps %1 \n"\ 105 " \n"\ 106 "movi %2, " XTSTR( PS_WOE_MASK ) "\n"\ 107 " \n"\ 108 "or %1, %1, %2 \n"\ 109 "wsr.ps %1 \n"\ 110 "rsync \n"\ 111 : "+r"(sp), "+r"(tmp1), "+r"(tmp2) : "r"(mask)); \ 112 } while (0); 113 #endif // __ASSEMBLER__ 114