📄 alt_exception_entry.s
字号:
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2003-2005 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* 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. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* *
******************************************************************************/
#include "system.h"
/*
* This is the exception entry point code, which saves all the caller saved
* registers and then handles the appropriate exception. It should be pulled
* in using a .globl from all the exception handler routines. This scheme is
* used so that if an interrupt is never registered, then this code will not
* appear in the generated executable, thereby improving code footprint.
*/
/*
* Explicitly allow the use of r1 (the assembler temporary register)
* within this code. This register is normally reserved for the use of
* the assembler.
*/
.set noat
/*
* The top and bottom of the exception stack
*/
#ifdef ALT_EXCEPTION_STACK
.globl __alt_exception_stack_pointer
#ifdef ALT_STACK_CHECK
.globl __alt_exception_stack_limit
/*
* We need to store the value of the stack limit after interrupt somewhere.
*/
.globl alt_exception_old_stack_limit
#endif
#endif
.section .exceptions.entry.label, "xa"
.globl alt_exception
.type alt_exception, @function
alt_exception:
.section .exceptions.entry, "xa"
#ifdef ALT_EXCEPTION_STACK
#ifdef ALT_STACK_CHECK
stw et, %gprel(alt_exception_old_stack_limit)(gp)
#endif
movhi et, %hiadj(__alt_exception_stack_pointer - 80)
addi et, et, %lo(__alt_exception_stack_pointer - 80)
stw sp, 76(et)
mov sp, et
#ifdef ALT_STACK_CHECK
movhi et, %hiadj(__alt_exception_stack_limit)
addi et, et, %lo(__alt_exception_stack_limit)
stw et, %gprel(alt_stack_limit_value)(gp)
#endif
#else
/*
* Process an exception. For all exceptions we must preserve all
* caller saved registers on the stack (See the Nios2 ABI
* documentation for details).
*/
addi sp, sp, -76
#ifdef ALT_STACK_CHECK
bltu sp, et, .Lstack_overflow
#endif
#endif
stw ra, 0(sp)
/*
* Leave a gap in the stack frame at 4(sp) for the muldiv handler to
* store zero into.
*/
stw r1, 8(sp)
stw r2, 12(sp)
stw r3, 16(sp)
stw r4, 20(sp)
stw r5, 24(sp)
stw r6, 28(sp)
stw r7, 32(sp)
rdctl r5, estatus
stw r8, 36(sp)
stw r9, 40(sp)
stw r10, 44(sp)
stw r11, 48(sp)
stw r12, 52(sp)
stw r13, 56(sp)
stw r14, 60(sp)
stw r15, 64(sp)
stw r5, 68(sp)
addi r15, ea, -4 /* re-issue the interrupted instruction */
stw r15, 72(sp)
/*
* The interrupt testing code goes here. If an interrupt is active
* then it stores ea-4 into 72(sp), handles the interrupt and jumps to
* .exceptions.exit. If there is no interrupt then it continues
*/
.section .exceptions.notirq, "xa"
stw ea, 72(sp) /* Return after the instruction which caused the exception */
ldw r2, -4(ea)
/*
* The other exception handling code goes here.
*/
.section .exceptions.unknown
/*
* If you get here then one of the following could have happened:
*
* - Your program could have been compiled for a full-featured Nios II
* core, but it is running on a smaller core, and instruction emulation
* has been disabled by defining ALT_NO_INSTRUCTION_EMULATION.
*
* You can work around the problem by re-enabling instruction emulation,
* or you can figure out why your program is being compiled for a system
* other than the one that it is running on.
*
* - Your program has executed a trap instruction, but has not implemented
* a handler for this instruction.
*
* - Your program has executed an illegal instruction (one which is not
* defined in the instruction set).
*
* - Your hardware is broken and is generating spurious interrupts (a
* peripheral which deasserts its interrupt output before its interrupt
* handler has been executed will cause spurious interrupts).
*
*/
#ifdef NIOS2_HAS_DEBUG_STUB
/*
* Either tell the user now (if there is a debugger attached) or go into
* the debug monitor which will loop until a debugger is attached.
*/
break
#else
/*
* If there is no debug stub then a BREAK will probably cause a reboot.
* An infinate loop will probably be more useful.
*/
0:
br 0b
#endif
.section .exceptions.exit, "xa"
/*
* Restore the saved registers, so that all general purpose registers
* have been restored to their state at the time the interrupt occured.
*/
ldw r5, 68(sp)
ldw ea, 72(sp)
ldw ra, 0(sp)
wrctl estatus, r5
ldw r1, 8(sp)
ldw r2, 12(sp)
ldw r3, 16(sp)
ldw r4, 20(sp)
ldw r5, 24(sp)
ldw r6, 28(sp)
ldw r7, 32(sp)
#ifdef ALT_EXCEPTION_STACK
#ifdef ALT_STACK_CHECK
ldw et, %gprel(alt_exception_old_stack_limit)(gp)
#endif
#endif
ldw r8, 36(sp)
ldw r9, 40(sp)
ldw r10, 44(sp)
ldw r11, 48(sp)
ldw r12, 52(sp)
ldw r13, 56(sp)
ldw r14, 60(sp)
ldw r15, 64(sp)
#ifdef ALT_EXCEPTION_STACK
#ifdef ALT_STACK_CHECK
stw et, %gprel(alt_stack_limit_value)(gp)
stw zero, %gprel(alt_exception_old_stack_limit)(gp)
#endif
ldw sp, 76(sp)
#else
addi sp, sp, 76
#endif
/*
* Return to the interrupted instruction.
*/
eret
#ifdef ALT_STACK_CHECK
.Lstack_overflow:
break 3
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -