+++ /dev/null
-// Medium-Priority Interrupt Dispatcher Template
-// $Id: //depot/rel/Cottonwood/Xtensa/OS/xtos/int-medpri-dispatcher.S#4 $
-
-// Copyright (c) 2004-2010 Tensilica 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.
-
-//
-// By default, this file is included by inth-template.S .
-// The default Makefile defines _INTERRUPT_LEVEL when assembling
-// inth-template.S for each medium and high priority interrupt level.
-//
-// To use this template file, define a macro called _INTERRUPT_LEVEL
-// to be the interrupt priority level of the vector, then include this file.
-
-
-#include <xtensa/coreasm.h>
-#include "xtos-internal.h"
-
-
-#if XCHAL_HAVE_INTERRUPTS
-
-#define INTERRUPT_MASK XCHAL_INTLEVEL_MASK(_INTERRUPT_LEVEL)
-#define SINGLE_INTERRUPT ((INTERRUPT_MASK & (INTERRUPT_MASK - 1)) == 0)
-#define SINGLE_INT_NUM XCHAL_INTLEVEL_NUM(_INTERRUPT_LEVEL)
-
-
-// Strict non-preemptive prioritization
-
-
- .text
- .align 4
- .global LABEL(_Level,FromVector)
-LABEL(_Level,FromVector):
-
-/* Allocate an exception stack frame, save a2, a4, and a5, and fix PS as:
- *
- * if not Call0 ABI
- * - enable windowing for 'entry' (ps.woe=1, ps.excm=0)
- * - setup ps.callinc to simulate call4
- * endif
- * - preserve user mode
- * - mask all interrupts at EXCM_LEVEL and lower
- *
- * Then deallocate the stack, 'rsync' for the write to PS, then use
- * 'entry' to re-allocate the stack frame and rotate the register
- * window (like a call4, preserving a0..a3). */
-
-#if HAVE_XSR
- xsr a2, EXCSAVE_LEVEL
-#else
- rsr a2, EXCSAVE_LEVEL
-#endif
- addi a1, a1, -ESF_TOTALSIZE
- s32i a2, a1, UEXC_a2
-#ifdef __XTENSA_CALL0_ABI__
- movi a2, PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL)
-#else
- movi a2, PS_WOE|PS_CALLINC(1)|PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL)
-#endif
- s32i a4, a1, UEXC_a4
- s32i a5, a1, UEXC_a5
- wsr a2, PS
- rsync
-
-#ifdef __XTENSA_CALL0_ABI__
- s32i a0, a1, UEXC_a0
- s32i a3, a1, UEXC_a3
- s32i a6, a1, UEXC_a6
- s32i a7, a1, UEXC_a7
- s32i a8, a1, UEXC_a8
- s32i a9, a1, UEXC_a9
- s32i a10, a1, UEXC_a10
- s32i a11, a1, UEXC_a11
- s32i a12, a1, UEXC_a12
- s32i a13, a1, UEXC_a13
- s32i a14, a1, UEXC_a14
- s32i a15, a1, UEXC_a15
- movi a0, 0 /* terminate stack frames */
-# if XTOS_DEBUG_PC
- // TODO: setup return PC for call traceback through interrupt dispatch
-# endif
-#else
-# if XTOS_CNEST
- l32i a2, a1, ESF_TOTALSIZE-20 // save nested-C-func call-chain ptr
-# endif
- addi a1, a1, ESF_TOTALSIZE
-# if XTOS_DEBUG_PC
- rsr a4, EPC+_INTERRUPT_LEVEL // [for debug] get return PC
- movi a5, 0xC0000000 // [for debug] setup call size...
- or a4, a5, a4 // [for debug] set upper two bits of return PC
- addx2 a4, a5, a4 // [for debug] clear upper bit
-# else
- movi a4, 0 /* terminate stack frames, overflow check */
-# endif
- _entry a1, ESF_TOTALSIZE
-#endif
-
-/* Reset the interrupt level to mask all interrupts at the current
- * priority level and lower. Note the current priority level may be
- * less than or equal to EXCM_LEVEL. */
-
- rsil a15, _INTERRUPT_LEVEL
-
-#if SINGLE_INTERRUPT /* if only one interrupt at this priority level... */
-
-/* Preserve the SAR, loop, and MAC16 regs. Also, clear the interrupt. */
-
- rsr a14, SAR
- movi a12, INTERRUPT_MASK
- s32i a14, a1, UEXC_sar
- wsr a12, INTCLEAR // clear if edge-trig or s/w or wr/err (else no effect)
- save_loops_mac16 a1, a13, a14
-
-/* Load the handler from the table, initialize two args (interrupt
- * number and exception stack frame), then call the interrupt handler.
- * Note: The callx12 preserves the original user task's a4..a15.*/
-
- movi a12, _xtos_interrupt_table + MAPINT(SINGLE_INT_NUM)*XIE_SIZE
- l32i a13, a12, XIE_HANDLER
-# ifdef __XTENSA_CALL0_ABI__
- l32i a2, a12, XIE_ARG
- mov a3, a1
- callx0 a13
-# else
- l32i a14, a12, XIE_ARG
- mov a15, a1
- callx12 a13
-# endif
-
-#else /* > 1 interrupts at this priority level */
-
-/* Get bit list of pending interrupts at the current interrupt priority level.
- * If bit list is empty, interrupt is spurious (can happen if a
- * genuine interrupt brings control this direction, but the interrupt
- * goes away before we read the INTERRUPT register). Also save off
- * sar, loops, and mac16 registers. */
-
- rsr a15, INTERRUPT
- rsr a12, INTENABLE
- movi a13, INTERRUPT_MASK
- and a15, a15, a12
- and a15, a15, a13
- rsr a14, SAR
- _beqz a15, LABEL(spurious,int)
- s32i a14, a1, UEXC_sar
- save_loops_mac16 a1, a13, a14
-
-/* Loop to handle all pending interrupts. */
-
-LABEL(.L1,_loop0):
- neg a12, a15
- and a12, a12, a15
- wsr a12, INTCLEAR // clear if edge-trig or s/w or wr/err (else no effect)
- movi a13, _xtos_interrupt_table
- find_ms_setbit a15, a12, a14, 0
- mapint a15
- addx8 a12, a15, a13
- l32i a13, a12, XIE_HANDLER
-# ifdef __XTENSA_CALL0_ABI__
- l32i a2, a12, XIE_ARG
- mov a3, a1
- callx0 a13
-# else
- l32i a14, a12, XIE_ARG
- mov a15, a1
- callx12 a13
-# endif
- rsr a15, INTERRUPT
- rsr a12, INTENABLE
- movi a13, INTERRUPT_MASK
- and a15, a15, a12
- and a15, a15, a13
- _bnez a15, LABEL(.L1,_loop0)
-
-#endif /* SINGLE_INTERRUPT */
-
-/* Restore everything, and return. */
-
- restore_loops_mac16 a1, a13, a14, a15
- l32i a14, a1, UEXC_sar
-LABEL(spurious,int):
-
-#ifdef __XTENSA_CALL0_ABI__
- wsr a14, SAR
- l32i a0, a1, UEXC_a0
- l32i a2, a1, UEXC_a2
- l32i a3, a1, UEXC_a3
- l32i a4, a1, UEXC_a4
- l32i a5, a1, UEXC_a5
- l32i a6, a1, UEXC_a6
- l32i a7, a1, UEXC_a7
- l32i a8, a1, UEXC_a8
- l32i a9, a1, UEXC_a9
- l32i a10, a1, UEXC_a10
- l32i a11, a1, UEXC_a11
- l32i a12, a1, UEXC_a12
- l32i a13, a1, UEXC_a13
- l32i a14, a1, UEXC_a14
- l32i a15, a1, UEXC_a15
- addi a1, a1, ESF_TOTALSIZE // restore sp
- rfi _INTERRUPT_LEVEL
-
-#else /* windowed ABI: */
-
- movi a0, LABEL(return,from_exc)
- movi a13, 0xC0000000
- wsr a14, SAR
- or a0, a0, a13
- addx2 a0, a13, a0
-# if _INTERRUPT_LEVEL < XCHAL_EXCM_LEVEL
-/* Raise the interrupt mask before
- * returning to avoid a race condition where we deallocate the
- * exception stack frame but still have more register values to
- * restore from it. */
- rsil a14, XCHAL_EXCM_LEVEL
-# endif
- retw
-LABEL(return,from_exc):
-# if XTOS_CNEST
- s32i a2, a5, ESF_TOTALSIZE-20 // restore nested-C-func call-chain ptr
-# endif
- l32i a2, a5, UEXC_a2
- l32i a4, a5, UEXC_a4
- l32i a5, a5, UEXC_a5
- rfi _INTERRUPT_LEVEL
-#endif /* windowed ABI */
-
- .size LABEL(_Level,FromVector), . - LABEL(_Level,FromVector)
-
- // This symbol exists solely for the purpose of being able to pull-in this
- // dispatcher using _xtos_dispatch_level<n>() routines with the tiny-rt LSP:
- .global LABEL(_Level,HandlerLabel)
- .set LABEL(_Level,HandlerLabel), 0
-
-#endif /* XCHAL_HAVE_INTERRUPT */
-