#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:
Maintained by John Loomis, last updated 15 November 2008