move sboot to the root directory
[open-ath9k-htc-firmware.git] / sboot / magpie_1_1 / sboot / athos / src / xtos / int-medpri-dispatcher.S
diff --git a/sboot/magpie_1_1/sboot/athos/src/xtos/int-medpri-dispatcher.S b/sboot/magpie_1_1/sboot/athos/src/xtos/int-medpri-dispatcher.S
new file mode 100755 (executable)
index 0000000..d60d07e
--- /dev/null
@@ -0,0 +1,254 @@
+// 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 */
+