/****************************************************************************** * * * License Agreement * * * * Copyright (c) 2003-2004 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 interrupt exception entry point code, which saves all the * registers and calls the interrupt handler. It should be pulled in using * a .globl from alt_irq_register.c. 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 compiler. */ .set noat /* * Pull in the exception handler register save code. */ .globl alt_exception .globl alt_irq_entry .section .exceptions.entry.label, "xa" alt_irq_entry: /* * Section .exceptions.entry is in alt_exception_entry.S * This saves all the caller saved registers and reads estatus into r5 */ .section .exceptions.irqtest, "xa" #ifdef ALT_CI_INTERRUPT_VECTOR_N /* * Use the interrupt vector custom instruction if present to accelerate * this code. * If the interrupt vector custom instruction returns a negative * value, there are no interrupts active (estatus.pie is 0 * or ipending is 0) so assume it is a software exception. */ custom ALT_CI_INTERRUPT_VECTOR_N, r4, r0, r0 blt r4, r0, .Lnot_irq #else /* * Test to see if the exception was a software exception or caused * by an external interrupt, and vector accordingly. */ rdctl r4, ipending andi r2, r5, 1 beq r2, zero, .Lnot_irq beq r4, zero, .Lnot_irq #endif /* ALT_CI_INTERRUPT_VECTOR_N */ .section .exceptions.irqhandler, "xa" /* * Now that all necessary registers have been preserved, call * alt_irq_handler() to process the interrupts. */ call alt_irq_handler .section .exceptions.irqreturn, "xa" br .Lexception_exit .section .exceptions.notirq.label, "xa" .Lnot_irq: /* * Section .exceptions.exit is in alt_exception_entry.S * This restores all the caller saved registers */ .section .exceptions.exit.label .Lexception_exit: