summaryrefslogtreecommitdiff
path: root/hifi/xaf/hifi-dpf/ipc/xt-shmem/hikey/int_vector.S
diff options
context:
space:
mode:
Diffstat (limited to 'hifi/xaf/hifi-dpf/ipc/xt-shmem/hikey/int_vector.S')
-rw-r--r--hifi/xaf/hifi-dpf/ipc/xt-shmem/hikey/int_vector.S830
1 files changed, 830 insertions, 0 deletions
diff --git a/hifi/xaf/hifi-dpf/ipc/xt-shmem/hikey/int_vector.S b/hifi/xaf/hifi-dpf/ipc/xt-shmem/hikey/int_vector.S
new file mode 100644
index 00000000..d579a55e
--- /dev/null
+++ b/hifi/xaf/hifi-dpf/ipc/xt-shmem/hikey/int_vector.S
@@ -0,0 +1,830 @@
+/*******************************************************************************
+* Copyright (C) 2018 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 use this Software with Cadence processor cores only and
+* not with any other processors and platforms, 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.
+
+******************************************************************************/
+/******************************************************************************
+ int_vector.S
+******************************************************************************/
+#include <xtensa/coreasm.h>
+#include <xtensa/corebits.h>
+#include <xtensa/config/system.h>
+#include <xtensa/simcall.h>
+#include "arch_hifi330.h"
+
+// .data
+ .section .dram0.data, "aw"
+/* CP */
+ .type g_awVosCoprocSaOffset,@object
+ .align 16 /* minimize crossing cache boundaries */
+g_awVosCoprocSaOffset:
+ .word XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA
+ .word XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA
+
+/* CP n's CPENABLE bit. */
+ .type g_bVosCoprocMask,@object
+ .align 16,,8 /* try to keep it all in one cache line */
+g_bVosCoprocMask:
+ .byte 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
+
+/* Owner of CP (0 = unowned). */
+ .global g_awVosCoprocOwnerSa
+ .type g_awVosCoprocOwnerSa,@object
+ .align 16,,XCHAL_CP_MAX<<2 /* minimize crossing cache boundaries */
+g_awVosCoprocOwnerSa:
+ .space XCHAL_CP_MAX << 2,0
+
+ .global g_strVosPanicMessage
+ .align 4
+g_strVosPanicMessage:
+ .string "\npanic at addr 0x%08x.\n"
+
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .global OS_Panic
+ .type OS_Panic,@function
+ .align 4
+/*****************************************************************************
+ OS_Panic
+*****************************************************************************/
+OS_Panic:
+
+#ifdef ZOS_SIM
+ /*panic at addr*/
+ addi a4, a0, -3 /* point to call0 */
+ movi a3, g_strVosPanicMessage
+ movi a2, SYS_log_msg
+ simcall
+ movi a2, SYS_gdb_abort
+ simcall
+#else
+ /*low & med*/
+ rsil a2, XCHAL_EXCM_LEVEL /* disable all low & med ints */
+1: j 1b /* loop infinitely */
+#endif
+
+ .end literal_prefix
+
+ .begin literal_prefix .DebugExceptionVector
+ .section .DebugExceptionVector.text, "ax"
+ .global OS_DebugExceptionVector
+ .align 4
+/*****************************************************************************
+_DebugExceptionVector
+*****************************************************************************/
+OS_DebugExceptionVector:
+#ifdef ZOS_SIM
+ wsr a2, EXCSAVE+XCHAL_DEBUGLEVEL
+ movi a2, SYS_gdb_enter_sktloop
+ simcall
+#else
+ wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL
+ call0 OS_Panic
+ rfi XCHAL_DEBUGLEVEL
+#endif
+
+ .end literal_prefix
+
+
+ .begin literal_prefix .DoubleExceptionVector
+ .section .DoubleExceptionVector.text, "ax"
+ .global OS_DoubleExceptionVector
+ .align 4
+/*****************************************************************************
+ OS_DoubleExceptionVector
+*****************************************************************************/
+OS_DoubleExceptionVector:
+ call0 OS_Panic /* does not return */
+ rfde /* make a0 point here not later */
+
+ .end literal_prefix
+
+
+ .begin literal_prefix .KernelExceptionVector
+ .section .KernelExceptionVector.text, "ax"
+ .global OS_KernelExceptionVector
+ .align 4
+/*****************************************************************************
+ _KernelExceptionVector
+*****************************************************************************/
+OS_KernelExceptionVector:
+ call0 OS_Panic /* does not return */
+ rfe /* make a0 point here not later */
+
+ .end literal_prefix
+
+
+ .begin literal_prefix .UserExceptionVector
+ .section .UserExceptionVector.text, "ax"
+ .global OS_UserExceptionVector
+ .type OS_UserExceptionVector,@function
+ .align 4
+/*****************************************************************************
+ _UserExceptionVector
+*****************************************************************************/
+OS_UserExceptionVector:
+ wsr a0, EXCSAVE_1 /* preserve a0 */
+ call0 OS_UserExc /* user exception handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+
+ .align 4
+OS_CoProcessorExc:
+ s32i a5, sp, XT_STK_A5 /* save a5 */
+ addi a5, a0, -EXCCAUSE_CP0_DISABLED /* a0 = CP index */
+ bgei a5, XCHAL_CP_MAX, .L_xt_user_exc_not_coproc
+ call0 OS_CoProcessorException /* in window vectors section */
+ /* never returns here - call0 is used as a jump (see note at top) */
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .align 4
+OS_AllocExc:
+ call0 OS_AllocaException /* in window vectors section */
+ /* never returns here - call0 is used as a jump (see note at top) */
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .align 4
+OS_SyscallExc:
+ call0 OS_SyscallException
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .global OS_UserExc
+ .type OS_UserExc,@function
+ .align 4
+OS_UserExc:
+ rsr a0, EXCCAUSE
+ beqi a0, EXCCAUSE_ALLOCA, OS_AllocExc
+ beqi a0, EXCCAUSE_SYSCALL, OS_SyscallExc
+
+ mov a0, sp /* sp == a1 */
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
+ rsr a0, PS /* save interruptee's PS */
+ s32i a0, sp, XT_STK_PS
+ rsr a0, EPC_1 /* save interruptee's PC */
+ s32i a0, sp, XT_STK_PC
+ rsr a0, EXCSAVE_1 /* save interruptee's a0 */
+ s32i a0, sp, XT_STK_A0
+ movi a0, OS_UserExit /* save exit point for dispatch */
+ s32i a0, sp, XT_STK_EXIT
+
+ rsr a0, EXCCAUSE
+ bgeui a0, EXCCAUSE_CP0_DISABLED, OS_CoProcessorExc
+
+.L_xt_user_exc_not_coproc:
+
+
+ call0 XT_RTOS_INT_ENTER
+
+
+ movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
+ wsr a0, PS
+ rsync
+
+ rsr a2, EXCCAUSE
+ beqi a2, EXCCAUSE_LEVEL1INTERRUPT, .L_xt_user_int
+ mov a6,a2
+ mov a7,a1
+ /*User exception*/
+ call4 OS_UserexecHandler
+ j .L_xt_user_done
+
+.L_xt_user_int:
+ /* level 1 int */
+ rsr a2, INTENABLE
+ rsr a3, INTERRUPT
+ movi a4, XCHAL_INTLEVEL1_MASK
+ and a2, a2, a3
+ and a2, a2, a4
+ beqz a2, .L_int_done1
+
+ neg a3,a2
+ and a3,a3,a2
+ wsr a3,INTCLEAR
+
+ find_ls_one a2, a3
+ mov a6,a2
+ call4 OS_EnterIntHook
+
+ mov a6,a2
+ call4 OS_InterruptHandler
+
+ mov a6,a2
+ call4 OS_ExitIntHook
+ j .L_xt_user_int
+
+.L_int_done1:
+
+
+.L_xt_user_done:
+ call0 XT_RTOS_INT_EXIT
+
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .global OS_UserExit
+ .type OS_UserExit,@function
+ .align 4
+OS_UserExit:
+ l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
+ wsr a0, PS
+ l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
+ wsr a0, EPC_1
+ l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
+ l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
+ rsync /* ensure PS and EPC written */
+ rfe /* PS.EXCM is cleared */
+
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .type OS_SyscallException,@function
+ .align 4
+/*****************************************************************************
+ OS_SyscallException
+*****************************************************************************/
+OS_SyscallException:
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */
+ s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */
+ call0 OS_ContextSave
+
+
+ /*
+ 2)update PC*/
+ rsr a2, EPC_1
+ addi a3, a2, 3
+
+ rsr a0, LEND
+ bne a3, a0, 1f
+ rsr a0, LCOUNT
+ beqz a0, 1f
+ addi a0, a0, -1
+ rsr a3, LBEG
+ wsr a0, LCOUNT
+
+1: wsr a3, EPC_1
+
+ /* Restore context,exception */
+ call0 OS_ContextRestore
+ addi sp, sp, XT_STK_FRMSZ
+
+ movi a0, -1
+ movnez a2, a0, a2 /* return -1 if not syscall 0 */
+ rsr a0, EXCSAVE_1
+ rfe
+
+
+
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .type OS_CoProcessorException,@function
+ .align 4
+/*****************************************************************************
+ OS_CoProcessorException
+*****************************************************************************/
+OS_CoProcessorException: /* a5 = CP index */
+
+ s32i a2, sp, XT_STK_A2
+ s32i a3, sp, XT_STK_A3
+ s32i a4, sp, XT_STK_A4
+ s32i a15, sp, XT_STK_A15
+
+
+ /* co-processor old owner new owner. */
+ call0 XT_RTOS_CP_STATE /* a15 = new owner's save area */
+ beqz a15, .L_xt_coproc_invalid /* not in a thread (invalid) */
+
+ mov a0, a5 /* a0 = CP index */
+ movi a3, g_awVosCoprocOwnerSa
+ addx4 a3, a0, a3 /* a3 = &g_awVosCoprocOwnerSa[CP] */
+ l32i a2, a3, 0 /* a2 = old owner's save area */
+
+ /* Enable the co-processor's bit in CPENABLE. */
+ movi a4, g_bVosCoprocMask
+ rsr a5, CPENABLE /* a5 = CPENABLE */
+ add a4, a4, a0
+ l8ui a4, a4, 0 /* a4 = bitmask from CP index */
+ or a5, a5, a4 /* a5 = CPENABLE + CP */
+ wsr a5, CPENABLE
+
+
+ beq a15, a2, .L_xt_coproc_done /* new owner == old, we're done */
+
+ s32i a15, a3, 0 /* g_awVosCoprocOwnerSa[CP] = new */
+
+ l8ui a5, a15, XT_CPSTORED /* a5 = new owner's old CPSTORED */
+ neg a3, a4
+ addi a3, a3, -1 /* a3 = ~a4 (bitmask for CP) */
+ and a3, a5, a3 /* clr CP in new owner's CPSTORED */
+ s8i a3, a15, XT_CPSTORED /* update new owner's CPSTORED */
+
+ /* Adjust new owner's save area pointers to area for CP n. */
+ movi a3, g_awVosCoprocSaOffset
+ and a5, a5, a4 /* a5 = new owner's CP is stored */
+ addx4 a3, a0, a3 /* a3 = &OS_CoprocSaOffset[CP] */
+ l32i a3, a3, 0 /* a3 = XT_CP[CP]_SA */
+ add a15, a15, a3 /* a15 = new owner's area for CP */
+ moveqz a15, a5, a5 /* a15 = 0 if state not stored */
+
+ rsync /* ensure wsr.CPENABLE is complete */
+ beqz a2, .L_xt_coproc_new /* no old owner to save */
+
+ /* If old owner still needs CP, clear CP in CPENABLE and set in CPSTORED. */
+ l8ui a5, a2, XT_CPENABLE /* a5 = old owner's CPENABLE */
+ and a4, a5, a4 /* a4 = CP in old owner CPENABLE */
+ beqz a4, .L_xt_coproc_new /* discard old owner's CP state */
+
+ sub a5, a5, a4 /* clr CP in old owner's CPENABLE */
+ s8i a5, a2, XT_CPENABLE /* update old owner's CPENABLE */
+ l8ui a5, a2, XT_CPSTORED /* a5 = old owner's CPSTORED */
+ or a5, a5, a4 /* set CP in old owner's CPSTORED */
+ s8i a5, a2, XT_CPSTORED /* update old owner's CPSTORED */
+
+ /* Save co-processor state of old owner. */
+.Ln_xt_coproc_old:
+ add a2, a2, a3 /* a2 = old owner's area for CP */
+ mov a3, a0 /* a3 = CP index */
+ /*
+ The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.
+ It is theoretically possible for Xtensa processor designers to write TIE
+ that causes more address registers to be affected, but it is generally
+ unlikely. If that ever happens, more registers needs to be saved/restored
+ around this macro invocation, and the value in a15 needs to be recomputed.
+ */
+ xchal_cpi_store_funcbody
+
+ /* Restore co-processor state of new owner. */
+.L_xt_coproc_new:
+ beqz a15, .L_xt_coproc_done /* no valid state to restore */
+ mov a2, a15 /* a2 = new owner's area for CP */
+ mov a3, a0 /* a3 = CP index */
+
+ xchal_cpi_load_funcbody
+
+
+.L_xt_coproc_done:
+ l32i a15, sp, XT_STK_A15
+ l32i a5, sp, XT_STK_A5
+ l32i a4, sp, XT_STK_A4
+ l32i a3, sp, XT_STK_A3
+ l32i a2, sp, XT_STK_A2
+ call0 OS_UserExit
+
+.L_xt_coproc_invalid:
+ call0 OS_Panic /* not in a thread (invalid) */
+ .end literal_prefix
+
+ .begin literal_prefix .Level2InterruptVector
+ .section .Level2InterruptVector.text, "ax"
+ .global OS_Level2Vector
+ .type OS_Level2Vector,@function
+ .align 4
+/*****************************************************************************
+ _Level2Vector
+*****************************************************************************/
+OS_Level2Vector:
+ wsr a0, EXCSAVE_2 /* preserve a0 */
+ call0 OS_Medint2 /* load interrupt handler */
+
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .extern OS_InterruptHandler
+ .type OS_Medint2,@function
+ .align 4
+OS_Medint2:
+
+#movi a1, 0xdeadbeef
+ movi a1, 0xe8075000
+ movi a2, 0xe8075e30 /*HIFI_RESERVE1_LOCATION*/
+ s32i a1, a2, 0
+
+ mov a0, sp /* sp == a1 */
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
+ rsr a0, EPS_2 /* save interruptee's PS */
+ s32i a0, sp, XT_STK_PS
+ rsr a0, EPC_2 /* save interruptee's PC */
+ s32i a0, sp, XT_STK_PC
+ rsr a0, EXCSAVE_2 /* save interruptee's a0 */
+ s32i a0, sp, XT_STK_A0
+ movi a0, OS_Medint2Exit /* save exit point for dispatch */
+ s32i a0, sp, XT_STK_EXIT
+
+ call0 XT_RTOS_INT_ENTER
+
+ movi a0, PS_INTLEVEL(2) | PS_UM | PS_WOE
+ wsr a0, PS
+ rsync
+
+
+.L_ProcAllInt2:
+ rsr a2, INTENABLE
+ rsr a3, INTERRUPT
+ movi a4, XCHAL_INTLEVEL2_MASK
+ and a2, a2, a3
+ and a2, a2, a4
+ beqz a2, .L_int_done2
+
+ neg a3,a2
+ and a3,a3,a2
+ wsr a3,INTCLEAR
+
+ find_ls_one a2, a3
+ mov a6,a2
+ call4 OS_EnterIntHook
+
+ mov a6,a2
+ call4 OS_InterruptHandler
+
+ mov a6,a2
+ call4 OS_ExitIntHook
+ j .L_ProcAllInt2
+
+.L_int_done2:
+ call0 XT_RTOS_INT_EXIT
+
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .global OS_Medint2Exit
+ .type OS_Medint2Exit,@function
+ .align 4
+OS_Medint2Exit:
+ /* Restore only level-specific regs (the rest were already restored) */
+ l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
+ wsr a0, EPS_2
+ l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
+ wsr a0, EPC_2
+ l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
+ l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
+ rsync /* ensure EPS and EPC written */
+ rfi 2
+ .end literal_prefix
+
+
+ .begin literal_prefix .Level3InterruptVector
+ .section .Level3InterruptVector.text, "ax"
+ .global OS_Level3Vector
+ .type OS_Level3Vector,@function
+ .align 4
+/*****************************************************************************
+ _Level3Vector
+*****************************************************************************/
+OS_Level3Vector:
+ wsr a0, EXCSAVE_3 /* preserve a0 */
+ call0 OS_MedInt3 /* load interrupt handler */
+
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .extern OS_InterruptHandler
+ .type OS_MedInt3,@function
+ .align 4
+OS_MedInt3:
+
+ mov a0, sp /* sp == a1 */
+ addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
+ s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */
+ rsr a0, EPS_3 /* save interruptee's PS */
+ s32i a0, sp, XT_STK_PS
+ rsr a0, EPC_3 /* save interruptee's PC */
+ s32i a0, sp, XT_STK_PC
+ rsr a0, EXCSAVE_3 /* save interruptee's a0 */
+ s32i a0, sp, XT_STK_A0
+ movi a0, OS_Medint3Exit /* save exit point for dispatch */
+ s32i a0, sp, XT_STK_EXIT
+
+ call0 XT_RTOS_INT_ENTER
+
+ movi a0, PS_INTLEVEL(3) | PS_UM | PS_WOE
+ wsr a0, PS
+ rsync
+
+
+.L_ProcAllInt3:
+ rsr a2, INTENABLE
+ rsr a3, INTERRUPT
+ movi a4, XCHAL_INTLEVEL3_MASK
+ and a2, a2, a3
+ and a2, a2, a4
+ beqz a2, .L_int_done3
+
+ neg a3,a2
+ and a3,a3,a2
+ wsr a3,INTCLEAR
+
+ find_ls_one a2, a3
+ mov a6,a2
+ call4 OS_EnterIntHook
+
+ mov a6,a2
+ call4 OS_InterruptHandler
+
+ mov a6,a2
+ call4 OS_ExitIntHook
+ j .L_ProcAllInt3
+
+.L_int_done3:
+
+ call0 XT_RTOS_INT_EXIT
+
+ .end literal_prefix
+
+ .begin literal_prefix .iram0
+ .section .iram0.text, "ax"
+ .global OS_Medint3Exit
+ .type OS_Medint3Exit,@function
+ .align 4
+OS_Medint3Exit:
+ /* Restore only level-specific regs (the rest were already restored) */
+ l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */
+ wsr a0, EPS_3
+ l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */
+ wsr a0, EPC_3
+ l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */
+ l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */
+ rsync /* ensure EPS and EPC written */
+ rfi 3
+ .end literal_prefix
+
+
+ .begin literal_prefix .NMIExceptionVector
+ .section .NMIExceptionVector.text, "ax"
+ .global OS_NMIExceptionVector
+ .align 8
+/*****************************************************************************
+ OS_NMIExceptionVector
+*****************************************************************************/
+OS_NMIExceptionVector:
+ /*wsr a3, 213
+ wsr a4, 214*/
+
+ /*movi a3, 0x0
+ movi a4, 0xf711a510
+ s32i a3, a4, 0*/
+
+ /*rsr a3, 213
+ rsr a4, 214*/
+
+ movi a0, PS_INTLEVEL(3) | PS_UM | PS_WOE
+ wsr a0, PS
+ rsync
+ rsr a2, EXCCAUSE
+ mov a6,a2
+ mov a7,a1
+ call4 OS_NmiHook
+
+ rfi XCHAL_NMILEVEL
+
+ .end literal_prefix
+
+ .section .WindowVectors.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 _WindowOverflow4
+_WindowOverflow4:
+
+ 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 _WindowUnderflow4
+_WindowUnderflow4:
+
+ 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
+
+ .global OS_AllocaException
+ .align 4
+/*****************************************************************************
+ OS_AllocaException
+*****************************************************************************/
+OS_AllocaException:
+
+ 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, _WindowUnderflow4
+ rotw -1 /* original a0 goes to a8 */
+ _bbci.l a8, 30, _WindowUnderflow8
+ rotw -1
+ j _WindowUnderflow12
+
+
+
+/*
+--------------------------------------------------------------------------------
+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 _WindowOverflow8
+_WindowOverflow8:
+
+ 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 _WindowUnderflow8
+_WindowUnderflow8:
+
+ 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 _WindowOverflow12
+_WindowOverflow12:
+
+ 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 _WindowUnderflow12
+_WindowUnderflow12:
+
+ 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
+
+
+