/************************************************************ * up_vectors.S * * Copyright (C) 2007 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name Gregory Nutt nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ************************************************************/ /************************************************************ * Included Files ************************************************************/ #include #include #include "c5471.h" /************************************************************ * Definitions ************************************************************/ /************************************************************ * Global Data ************************************************************/ .data up_irqtmp: .word 0 /* Saved lr */ .word 0 /* Saved spsr */ up_undeftmp: .word 0 /* Saved lr */ .word 0 /* Saved spsr */ up_aborttmp: .word 0 /* Saved lr */ .word 0 /* Saved spsr */ /************************************************************ * Macros ************************************************************/ /************************************************************ * Private Functions ************************************************************/ .text /************************************************************ * Public Functions ************************************************************/ .text /************************************************************ * Name: up_vectorirq * * Description: * Interrupt excetpion. Entered in IRQ mode with spsr = SVC * CPSR, lr = SVC PC ************************************************************/ .global up_vectorirq .type up_vectorirq, %function up_vectorirq: /* On entry, we are in IRQ mode. We are free to use * the IRQ mode r13 and r14. * */ ldr r13, .Lirqtmp sub lr, lr, #4 str lr, [r13] @ save lr_IRQ mrs lr, spsr str lr, [r13, #4] @ save spsr_IRQ /* Then switch back to SVC mode */ bic lr, lr, #MODE_MASK /* Keep F and T bits */ orr lr, lr, #I_BIT | SVC_MODE msr spsr_c, lr /* Swith to SVC mode */ /* Create a context structure */ sub sp, sp, #XCPTCONTEXT_SIZE stmia sp, {r0-r14} /* Save the SVC mode regs */ ldr r0, .Lirqtmp /* Points to temp storage */ ldmia r0, {r1, r2} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ add r0, sp, #(4*REG_PC) /* Offset to pc, cpsr storage */ stmia r0, {r1, r2} /* Now decode the interrupt */ #if 0 ldr lr, =SRC_IRQ_BIN_REG /* Fetch encoded IRQ */ ldr r0, [lr] and r0, r0, #0x0f /* Valid range is 0..15 */ /* Problems here... cannot read SRC_IRQ_BIN_REQ (and/or * SRC_IRQ_REQ because this will clear edge triggered * interrupts. Plus, no way to validate spurious * interrupt. */ #else ldr r6, =SRC_IRQ_REG ldr r6, [r6] /* Get source IRQ reg */ mov r0, #0 /* Assume IRQ0_IRQ set */ .Lmorebits: tst r6, #1 /* Is IRQ set? */ bne .Lhaveirq /* Yes... we have the IRQ */ add r0, r0, #1 /* Setup next IRQ */ mov r6, r6, lsr #1 /* Shift right one */ cmp r0, #16 /* Only 16 valid bits */ bcc .Lmorebits /* Keep until we have looked * at all bits */ b .Lnoirqset /* If we get here, there is * no pending interrupt */ .Lhaveirq: #endif /* Then call the data abort handler with interrupt disabled. * rq_dispatch(int irq, struct xcptcontext *xcp) */ mov fp, #0 /* Init frame pointer */ mov r1, sp /* Get r1=xcp */ bl up_doirq /* Call the handler */ /* Restore the CPSR, SVC modr registers and return */ .Lnoirqset: ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ msr spsr, r0 ldmia sp, {r0-r15}^ /* Return */ .Lirqtmp: .word up_irqtmp .align 5 /************************************************************ * Function: up_vectorswi * * Description: * SWI interrupt. We enter the SWI in SVC mode ************************************************************/ .global up_vectorswi .type up_vectorswi, %function up_vectorswi: /* The c547x rrload bootloader intemediates all * interrupts. For the* case of the SWI, it mucked * with the stack to create some temporary registers. * We'll have to recover from this mucking here. */ ldr r14, [sp,#-0x4] /* rrload workaround */ /* Create a context structure */ sub sp, sp, #XCPTCONTEXT_SIZE stmia sp, {r0-r14} /* Save the SVC mode regs */ mrs r2, spsr /* Get the saved CPSR */ mov r1, r14 /* Save r14 as the PC */ add r0, sp, #(4*REG_PC) /* Offset to pc, cpsr storage */ stmia r0, {r1, r2} /* Then call the SWI handler with interrupt disabled. * void up_syscall(struct xcptcontext *xcp) */ mov fp, #0 /* Init frame pointer */ mov r0, sp /* Get r0=xcp */ bl up_syscall /* Call the handler */ /* Restore the CPSR, SVC modr registers and return */ ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ msr spsr, r0 ldmia sp, {r0-r15}^ /* Return */ .align 5 /************************************************************ * Name: up_vectordata * * Description: * Data abort Exception dispatcher. Give control to data * abort handler. This function is entered in ABORT mode * with spsr = SVC CPSR, lr = SVC PC * ************************************************************/ .global up_vectordata .type up_vectordata, %function up_vectordata: /* On entry we are free to use the ABORT mode registers * r13 and r14 */ ldr r13, .Ldaborttmp /* Points to temp storage */ sub lr, lr, #8 /* Fixup return */ str lr, [r13] /* Save in temp storage */ mrs lr, spsr /* Get SPSR */ str lr, [r13, #4] /* Save in temp storage */ /* Then switch back to SVC mode */ bic lr, lr, #MODE_MASK /* Keep F and T bits */ orr lr, lr, #I_BIT | SVC_MODE msr spsr_c, lr /* Swith to SVC mode */ /* Create a context structure */ sub sp, sp, #XCPTCONTEXT_SIZE stmia sp, {r0-r14} /* Save the SVC mode regs */ ldr r0, .Ldaborttmp /* Points to temp storage */ ldmia r0, {r1, r2} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ add r0, sp, #(4*REG_PC) /* Offset to pc, cpsr storage */ stmia r0, {r1, r2} /* Then call the data abort handler with interrupt disabled. * void up_dataabort(struct xcptcontext *xcp) */ mov fp, #0 /* Init frame pointer */ mov r0, sp /* Get r0=xcp */ bl up_dataabort /* Call the handler */ /* Restore the CPSR, SVC modr registers and return */ ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ msr spsr, r0 ldmia sp, {r0-r15}^ /* Return */ .Ldaborttmp: .word up_aborttmp .align 5 /************************************************************ * Name: up_vectorprefetch * * Description: * Prefetch abort exception. Entered in ABT mode with * spsr = SVC CPSR, lr = SVC PC ************************************************************/ .global up_vectorprefetch .type up_vectorprefetch, %function up_vectorprefetch: /* On entry we are free to use the ABORT mode registers * r13 and r14 */ ldr r13, .Lpaborttmp /* Points to temp storage */ sub lr, lr, #4 /* Fixup return */ str lr, [r13] /* Save in temp storage */ mrs lr, spsr /* Get SPSR */ str lr, [r13, #4] /* Save in temp storage */ /* Then switch back to SVC mode */ bic lr, lr, #MODE_MASK /* Keep F and T bits */ orr lr, lr, #I_BIT | SVC_MODE msr spsr_c, lr /* Swith to SVC mode */ /* Create a context structure */ sub sp, sp, #XCPTCONTEXT_SIZE stmia sp, {r0-r14} /* Save the SVC mode regs */ ldr r0, .Lpaborttmp /* Points to temp storage */ ldmia r0, {r1, r2} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ add r0, sp, #(4*REG_PC) /* Offset to pc, cpsr storage */ stmia r0, {r1, r2} /* Then call the data abort handler with interrupt disabled. * void up_prefetchabort(struct xcptcontext *xcp) */ mov fp, #0 /* Init frame pointer */ mov r0, sp /* Get r0=xcp */ bl up_prefetchabort /* Call the handler */ /* Restore the CPSR, SVC modr registers and return */ ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ msr spsr, r0 ldmia sp, {r0-r15}^ /* Return */ .Lpaborttmp: .word up_aborttmp .align 5 /************************************************************ * Name: up_vectorundefinsn * * Description: * Undefined instruction entry exception. Entered in * UND mode, spsr = SVC CPSR, lr = SVC PC * ************************************************************/ .global up_vectorundefinsn .type up_vectorundefinsn, %function up_vectorundefinsn: /* On entry we are free to use the UND mode registers * r13 and r14 */ ldr r13, .Lundeftmp /* Points to temp storage */ str lr, [r13] /* Save in temp storage */ mrs lr, spsr /* Get SPSR */ str lr, [r13, #4] /* Save in temp storage */ /* Then switch back to SVC mode */ bic lr, lr, #MODE_MASK /* Keep F and T bits */ orr lr, lr, #I_BIT | SVC_MODE msr spsr_c, lr /* Swith to SVC mode */ /* Create a context structure */ sub sp, sp, #XCPTCONTEXT_SIZE stmia sp, {r0-r14} /* Save the SVC mode regs */ ldr r0, .Lundeftmp /* Points to temp storage */ ldmia r0, {r1, r2} /* Recover r1=lr_IRQ, r2=spsr_IRQ */ add r0, sp, #(4*REG_PC) /* Offset to pc, cpsr storage */ stmia r0, {r1, r2} /* Then call the data abort handler with interrupt disabled. * void up_undefinedinsn(struct xcptcontext *xcp) */ mov fp, #0 /* Init frame pointer */ mov r0, sp /* Get r0=xcp */ bl up_undefinedinsn /* Call the handler */ /* Restore the CPSR, SVC modr registers and return */ ldr r0, [sp, #(4*REG_CPSR)] /* Setup the SVC mode SPSR */ msr spsr, r0 ldmia sp, {r0-r15}^ /* Return */ .Lundeftmp: .word up_undeftmp .align 5 /************************************************************ * Name: up_vectorfiq * * Description: * Shouldn't happen ************************************************************/ .global up_vectorfiq .type up_vectorfiq, %function up_vectorfiq: subs pc, lr, #4 /************************************************************ * Name: up_vectoraddrexcption * * Description: * Shouldn't happen * ************************************************************/ .global up_vectoraddrexcptn .type up_vectoraddrexcptn, %function up_vectoraddrexcptn: b up_vectoraddrexcptn .end