diff --git a/arch/xtensa/src/common/xtensa_abi.h b/arch/xtensa/src/common/xtensa_abi.h new file mode 100644 index 00000000000..e4c0878c152 --- /dev/null +++ b/arch/xtensa/src/common/xtensa_abi.h @@ -0,0 +1,114 @@ +/**************************************************************************** + * arch/xtensa/src/common/xtensa_cpuint.S + * + * Adapted from use in NuttX by: + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Derives from logic originally provided by Cadence Design Systems Inc. + * + * Copyright (c) 2006-2015 Cadence Design Systems Inc. + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_COMMON_XTENSA_ABI_H +#define __ARCH_XTENSA_SRC_COMMON_XTENSA_ABI_H 1 + +/* Windowed ABI + * + * Windowed Register Usage + * Callee Register Usage + * Register Name + * a0 Return address + * a1/sp Stack pointer + * a2..a7 In, out, inout, and return values + * + * Calls to routines that use only a2..a3 as parameters may use the CALL4, + * CALL8, or CALL12 instructions to save 4, 8, or 12 live registers. Calls + * to routines that use a2..a7 for parameters may use only CALL8 or CALL12. + * + * Call 0 ABI + * + * CALL0 AR Register Usage + * Callee Register Usage + * Register Name + * a0 Return Address + * a1/sp Stack pointer + * a2..a7 In, out, inout, and return values + * a8 Static Chain + * a12..a15 Callee-saved + * a15 Stack-Frame Pointer (optional) + * + * CALL0 is used. The return address is placed in A0 and the CPU simply + * jumps to the CALL0 function entry point. + */ + +/**************************************************************************** + * Pre-processor Defintions + ****************************************************************************/ + +/* MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN + * + * Convenient where the frame size requirements are the same for both ABIs. + * ENTRY(sz), RET(sz) are for framed functions (have locals or make calls). + * ENTRY0, RET0 are for frameless functions (no locals, no calls). + * + * where size = size of stack frame in bytes (must be >0 and aligned to 16). + * For framed functions the frame is created and the return address saved at + * base of frame (Call0 ABI) or as determined by hardware (Windowed ABI). + * For frameless functions, there is no frame and return address remains in a0. + * Note: Because CPP macros expand to a single line, macros requiring multi-line + * expansions are implemented as assembler macros. + */ + +#ifdef __ASSEMBLY__ +#ifdef CONFIG_XTENSA_CALL0_ABI + /* Call0 */ + + .macro entry1 size=0x10 + addi sp, sp, -\size + s32i a0, sp, 0 + .endm + + .macro ret1 size=0x10 + l32i a0, sp, 0 + addi sp, sp, \size + ret + .endm + +# define ENTRY(sz) entry1 sz +# define ENTRY0 +# define RET(sz) ret1 sz +# define RET0 ret + +#else + /* Windowed */ + +# define ENTRY(sz) entry sp, sz +# define ENTRY0 entry sp, 0x10 +# define RET(sz) retw +# define RET0 retw +#endif +#endif /* __ASSEMBLY_ */ + +#endif /* __ARCH_XTENSA_SRC_COMMON_XTENSA_ABI_H */ diff --git a/arch/xtensa/src/common/xtensa_window_vector.S b/arch/xtensa/src/common/xtensa_window_vector.S new file mode 100644 index 00000000000..5b8314042e4 --- /dev/null +++ b/arch/xtensa/src/common/xtensa_window_vector.S @@ -0,0 +1,279 @@ +/**************************************************************************** + * arch/xtensa/src/common/xtensa_window_vector.S + * + * Adapted from use in NuttX by: + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Derives from logic originally provided by Cadence Design Systems Inc. + * + * Copyright (c) 2006-2015 Cadence Design Systems Inc. + * + * 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_vectors.S" + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Window Vectors + ****************************************************************************/ + +/* WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER + * + * Here is the code for each window overflow/underflow exception vector and + * (interspersed) efficient code for handling the alloca exception cause. + * Window exceptions are handled entirely in the vector area and are very + * tight for performance. The alloca exception is also handled entirely in + * the window vector area so comes at essentially no cost in code size. + * Users should never need to modify them and Cadence Design Systems recommends + * they do not. + * + * Window handlers go at predetermined vector locations according to the + * Xtensa hardware configuration, which is ensured by their placement in a + * special section known to the Xtensa linker support package (LSP). Since + * their offsets in that section are always the same, the LSPs do not define + * a section per vector. + * + * These things are coded for XEA2 only (XEA1 is not supported). + * + * Note on Underflow Handlers: + * The underflow handler for returning from call[i+1] to call[i] + * must preserve all the registers from call[i+1]'s window. + * In particular, a0 and a1 must be preserved because the RETW instruction + * will be reexecuted (and may even underflow if an intervening exception + * has flushed call[i]'s registers). + * Registers a2 and up may contain return values. + */ + +*******************************************************************************/ + +#if XCHAL_HAVE_WINDOWED + + .section .window_vectors.text, "ax" + +/* Window Overflow Exception for Call4. + * + * Invoked if a call[i] referenced a register (a4-a15) that contains data from + * ancestor call[j]; call[j] had done a call4 to call[j+1]. + * + * On entry here: + * window rotated to call[j] start point; + * a0-a3 are registers to be saved; + * a4-a15 must be preserved; + * a5 is call[j+1]'s stack pointer. + */ + + .org 0x0 + .global _window_overflow4 +_window_overflow4: + + s32e a0, a5, -16 /* save a0 to call[j+1]'s stack frame */ + s32e a1, a5, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a5, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a5, -4 /* save a3 to call[j+1]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* Window Underflow Exception for Call4 + * + * Invoked by RETW returning from call[i+1] to call[i] where call[i]'s + * registers must be reloaded (not live in ARs); where call[i] had done a + * call4 to call[i+1]. + * + * On entry here: + * window rotated to call[i] start point; + * a0-a3 are undefined, must be reloaded with call[i].reg[0..3]; + * a4-a15 must be preserved (they are call[i+1].reg[0..11]); + * a5 is call[i+1]'s stack pointer. + */ + + .org 0x40 + .global _window_underflow4 +_window_underflow4: + + l32e a0, a5, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a5, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a5, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a3, a5, -4 /* restore a3 from call[i+1]'s stack frame */ + rfwu + +/* Handle alloca exception generated by interruptee executing 'movsp'. + * This uses space between the window vectors, so is essentially "free". + * All interruptee's regs are intact except a0 which is saved in EXCSAVE_1, + * and PS.EXCM has been set by the exception hardware (can't be interrupted). + * The fact the alloca exception was taken means the registers associated with + * the base-save area have been spilled and will be restored by the underflow + * handler, so those 4 registers are available for scratch. + * The code is optimized to avoid unaligned branches and minimize cache misses. + */ + + .align 4 + .global _xt_alloca_exc +_xt_alloca_exc: + + rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */ + rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */ + rsr a2, PS + extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS + xor a3, a3, a4 /* bits changed from old to current windowbase */ + rsr a4, EXCSAVE_1 /* restore original a0 (now in a4) */ + slli a3, a3, XCHAL_PS_OWB_SHIFT + xor a2, a2, a3 /* flip changed bits in old window base */ + wsr a2, PS /* update PS.OWB to new window base */ + rsync + + _bbci.l a4, 31, _window_underflow4 + rotw -1 /* original a0 goes to a8 */ + _bbci.l a8, 30, _window_underflow8 + rotw -1 + j _window_underflow12 + +/* Window Overflow Exception for Call8 + * + * Invoked if a call[i] referenced a register (a4-a15) that contains data from + * ancestor call[j]; call[j] had done a call8 to call[j+1]. + * + * On entry here: + * window rotated to call[j] start point; + * a0-a7 are registers to be saved; + * a8-a15 must be preserved; + * a9 is call[j+1]'s stack pointer. + */ + + .org 0x80 + .global _window_overflow8 +_window_overflow8: + + s32e a0, a9, -16 /* save a0 to call[j+1]'s stack frame */ + l32e a0, a1, -12 /* a0 <- call[j-1]'s sp + * (used to find end of call[j]'s frame) */ + s32e a1, a9, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a9, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a9, -4 /* save a3 to call[j+1]'s stack frame */ + s32e a4, a0, -32 /* save a4 to call[j]'s stack frame */ + s32e a5, a0, -28 /* save a5 to call[j]'s stack frame */ + s32e a6, a0, -24 /* save a6 to call[j]'s stack frame */ + s32e a7, a0, -20 /* save a7 to call[j]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* Window Underflow Exception for Call8 + * + * Invoked by RETW returning from call[i+1] to call[i] where call[i]'s + * registers must be reloaded (not live in ARs); where call[i] had done a + * call8 to call[i+1]. + * + * On entry here: + * window rotated to call[i] start point; + * a0-a7 are undefined, must be reloaded with call[i].reg[0..7]; + * a8-a15 must be preserved (they are call[i+1].reg[0..7]); + * a9 is call[i+1]'s stack pointer. + */ + + .org 0xC0 + .global _window_underflow8 +_window_underflow8: + + l32e a0, a9, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a9, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a9, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a7, a1, -12 /* a7 <- call[i-1]'s sp + * (used to find end of call[i]'s frame) */ + l32e a3, a9, -4 /* restore a3 from call[i+1]'s stack frame */ + l32e a4, a7, -32 /* restore a4 from call[i]'s stack frame */ + l32e a5, a7, -28 /* restore a5 from call[i]'s stack frame */ + l32e a6, a7, -24 /* restore a6 from call[i]'s stack frame */ + l32e a7, a7, -20 /* restore a7 from call[i]'s stack frame */ + rfwu + +/* Window Overflow Exception for Call12 + * + * Invoked if a call[i] referenced a register (a4-a15) that contains data + * from ancestor call[j]; call[j] had done a call12 to call[j+1]. + * + * On entry here: + * window rotated to call[j] start point; + * a0-a11 are registers to be saved; + * a12-a15 must be preserved; + * a13 is call[j+1]'s stack pointer. + */ + + .org 0x100 + .global _window_overflow12 +_window_overflow12: + + s32e a0, a13, -16 /* save a0 to call[j+1]'s stack frame */ + l32e a0, a1, -12 /* a0 <- call[j-1]'s sp + * (used to find end of call[j]'s frame) */ + s32e a1, a13, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a13, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a13, -4 /* save a3 to call[j+1]'s stack frame */ + s32e a4, a0, -48 /* save a4 to end of call[j]'s stack frame */ + s32e a5, a0, -44 /* save a5 to end of call[j]'s stack frame */ + s32e a6, a0, -40 /* save a6 to end of call[j]'s stack frame */ + s32e a7, a0, -36 /* save a7 to end of call[j]'s stack frame */ + s32e a8, a0, -32 /* save a8 to end of call[j]'s stack frame */ + s32e a9, a0, -28 /* save a9 to end of call[j]'s stack frame */ + s32e a10, a0, -24 /* save a10 to end of call[j]'s stack frame */ + s32e a11, a0, -20 /* save a11 to end of call[j]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* Window Underflow Exception for Call12 + * + * Invoked by RETW returning from call[i+1] to call[i] where call[i]'s + * registers must be reloaded (not live in ARs); where call[i] had done a + * call12 to call[i+1]. + * + * On entry here: + * window rotated to call[i] start point; + * a0-a11 are undefined, must be reloaded with call[i].reg[0..11]; + * a12-a15 must be preserved (they are call[i+1].reg[0..3]); + * a13 is call[i+1]'s stack pointer. + */ + + .org 0x140 + .global _window_underflow12 +_window_underflow12: + + l32e a0, a13, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a13, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a13, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a11, a1, -12 /* a11 <- call[i-1]'s sp + * (used to find end of call[i]'s frame) */ + l32e a3, a13, -4 /* restore a3 from call[i+1]'s stack frame */ + l32e a4, a11, -48 /* restore a4 from end of call[i]'s stack frame */ + l32e a5, a11, -44 /* restore a5 from end of call[i]'s stack frame */ + l32e a6, a11, -40 /* restore a6 from end of call[i]'s stack frame */ + l32e a7, a11, -36 /* restore a7 from end of call[i]'s stack frame */ + l32e a8, a11, -32 /* restore a8 from end of call[i]'s stack frame */ + l32e a9, a11, -28 /* restore a9 from end of call[i]'s stack frame */ + l32e a10, a11, -24 /* restore a10 from end of call[i]'s stack frame */ + l32e a11, a11, -20 /* restore a11 from end of call[i]'s stack frame */ + rfwu + +#endif /* XCHAL_HAVE_WINDOWED */ diff --git a/configs/esp32-core/scripts/esp32_common.ld b/configs/esp32-core/scripts/esp32_common.ld index 540a4f4ad6a..680c71a7844 100644 --- a/configs/esp32-core/scripts/esp32_common.ld +++ b/configs/esp32-core/scripts/esp32_common.ld @@ -19,7 +19,7 @@ SECTIONS /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ . = 0x0; - KEEP(*(.WindowVectors.text)); + KEEP(*(.window_vectors.text)); . = 0x180; KEEP(*(.xtensa_level2_vector.text)); . = 0x1c0;