Xtensa: Add Window vector

This commit is contained in:
Gregory Nutt
2016-10-29 12:30:24 -06:00
parent 804f9c5de7
commit c993a0267c
3 changed files with 394 additions and 1 deletions
+114
View File
@@ -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 <gnutt@nuttx.org>
*
* 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 */
@@ -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 <gnutt@nuttx.org>
*
* 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 <arch/xtensa/xtensa_specregs.h>
#include <arch/xtensa/core.h>
#include <arch/esp32/core-isa.h>
/****************************************************************************
* 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 */
+1 -1
View File
@@ -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;