📄 int3_medpri_dispatcher.s
字号:
// Medium-Priority Interrupt Dispatcher Template// $Id: //depot/rel/BearValley/Xtensa/OS/xtos/int-medpri-dispatcher.S#1 $// Customer ID=4654; Build=0x116b0; Copyright (c) 2004 by Tensilica Inc. ALL RIGHTS RESERVED.// These coded instructions, statements, and computer programs are the// copyrighted works and confidential proprietary information of Tensilica Inc.// They may not be modified, copied, reproduced, distributed, or disclosed to// third parties in any manner, medium, or form, in whole or in part, without// the prior written consent of Tensilica Inc.//// 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 "internal.h"#define _INTERRUPT_LEVEL 3#define INTERRUPT_MASK XCHAL_INTLEVEL_MASK(_INTERRUPT_LEVEL)#define SINGLE_INT_NUM XCHAL_INTLEVEL_NUM(_INTERRUPT_LEVEL)#define STRUCT_BEGIN .pushsection .text; .struct 0#define STRUCT_FIELD(ctype,size,pre,name) pre##name: .space size#define STRUCT_AFIELD(ctype,size,pre,name,n) pre##name: .space (size)*(n)#define STRUCT_END(sname) sname##Size:; .popsectionSTRUCT_BEGINSTRUCT_FIELD (long,4,UEXC_,pc)STRUCT_FIELD (long,4,UEXC_,ps)STRUCT_FIELD (long,4,UEXC_,sar)STRUCT_FIELD (long,4,UEXC_,vpri)/*STRUCT_AFIELD(long,4,UEXC_,areg, 4)*/ /* a2,a3,a4,a5 OR a2,a3,a8,a9 */STRUCT_FIELD (long,4,UEXC_,a2)STRUCT_FIELD (long,4,UEXC_,a3)STRUCT_FIELD (long,4,UEXC_,a4_a8) /* a8 if call8-only configured */STRUCT_FIELD (long,4,UEXC_,a5_a9) /* a9 if call8-only configured */STRUCT_FIELD (long,4,UEXC_,exccause) /* NOTE: can probably rid of this one (pass direct) *//*STRUCT_FIELD (long,4,UEXC_,excvaddr)*/#if XCHAL_HAVE_LOOPSSTRUCT_FIELD (long,4,UEXC_,lcount)STRUCT_FIELD (long,4,UEXC_,lbeg)STRUCT_FIELD (long,4,UEXC_,lend)#endif#if XCHAL_HAVE_MAC16STRUCT_FIELD (long,4,UEXC_,acclo)STRUCT_FIELD (long,4,UEXC_,acchi)STRUCT_AFIELD(long,4,UEXC_,mr, 4)#endif#define ALIGNPAD ((3 + XCHAL_HAVE_LOOPS + XCHAL_HAVE_MAC16*2) & 3) /* 16-byte alignment padding */#if ALIGNPADSTRUCT_AFIELD(long,4,UEXC_,pad, ALIGNPAD) /* 16-byte alignment padding */#endif/*STRUCT_AFIELD(char,1,UEXC_,ureg, (XCHAL_CPEXTRA_SA_SIZE_TOR2+3)&-4)*/ /* not used, and doesn't take alignment into account */STRUCT_END(UserFrame)// Strict non-preemptive prioritization#if XCHAL_HAVE_CALL4AND12# define A4 a4# define A5 a5#else# define A4 a8# define A5 a9#endif/* Check for UserFrameSize small enough not to require rounding...: */ /* Skip 16-byte save area, then 16-byte GCC nested func chaining area, * then exception stack frame, then space for 8 regs for call12 below: */ .set UserFrameTotalSize, 16+16+UserFrameSize+32 /* Greater than 112 bytes? (max range of ADDI, both signs, when aligned to 16 bytes): */ .ifgt UserFrameTotalSize-112 /* Round up to 256-byte multiple to accelerate immediate adds: */ .set UserFrameTotalSize, ((UserFrameTotalSize+255) & 0xFFFFFF00) .endif# define ESF_TOTALSIZE UserFrameTotalSize// Strict non-preemptive prioritization .text .align 4 .global _Level3InterruptHandler_Level3InterruptHandler:/* Allocate an exception stack frame, save a2, a4, and a5, and fix PS as: * * - enable windowing for 'entry' (ps.woe=1, ps.excm=0) * - setup ps.callinc to simulate call4 * - 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). */ rsr a2, EXCSAVE_3 addi a1, a1, -ESF_TOTALSIZE s32i a2, a1, UEXC_a2 movi a2, PS_WOE|PS_CALLINC(1)|PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL) s32i a4, a1, UEXC_a4_a8 s32i a5, a1, UEXC_a5_a9 wsr a2, PS addi a1, a1, ESF_TOTALSIZE rsync movi a4, 0 /* terminate stack frames, overflow check */ _entry a1, ESF_TOTALSIZE/* 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/* 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, spurious_int s32i a14, a1, UEXC_sar save_loops_mac16 a1, a13, a14/* Loop to handle all pending interrupts. */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, intHandlers find_ms_setbit a15, a12, a14, 0 addx4 a12, a15, a13 l32i a13, a12, 0 mov a15, a1 callx12 a13 rsr a15, INTERRUPT rsr a12, INTENABLE movi a13, INTERRUPT_MASK and a15, a15, a12 and a15, a15, a13 _bnez a15, L1_loop0/* Restore everything, and return. 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. */ restore_loops_mac16 a1, a13, a14, a15 l32i a14, a1, UEXC_sarspurious_int: movi a0, return_from_exc movi a13, 0xC0000000 wsr a14, SAR or a0, a0, a13 addx2 a0, a13, a0#if _INTERRUPT_LEVEL < XCHAL_EXCM_LEVEL rsil a14, XCHAL_EXCM_LEVEL#endif retwreturn_from_exc: l32i a2, a5, UEXC_a2 l32i a4, a5, UEXC_a4_a8 l32i a5, a5, UEXC_a5_a9 rfi _INTERRUPT_LEVEL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -