diff options
Diffstat (limited to 'cpukit/score/cpu/epiphany/epiphany-exception-handler.S')
-rw-r--r-- | cpukit/score/cpu/epiphany/epiphany-exception-handler.S | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/cpukit/score/cpu/epiphany/epiphany-exception-handler.S b/cpukit/score/cpu/epiphany/epiphany-exception-handler.S new file mode 100644 index 0000000000..09c88fd861 --- /dev/null +++ b/cpukit/score/cpu/epiphany/epiphany-exception-handler.S @@ -0,0 +1,304 @@ +/** + * @file + * + * @ingroup ScoreCPU + * + * @brief Epiphany exception support implementation. + */ + +/* + * Copyright (c) 2015 University of York. + * Hesham ALMatary <hmka501@york.ac.uk> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/score/cpu.h> + +#include <rtems/asm.h> +#include <rtems/score/percpu.h> + +EXTERN(bsp_start_vector_table_begin) +EXTERN(_Thread_Dispatch) +PUBLIC(ISR_Handler) + +.section .text, "ax" +.align 4 +TYPE_FUNC(ISR_Handler) +SYM(ISR_Handler): + /* Reserve space for CPU_Exception_frame */ + sub sp, sp, #(CPU_EXCEPTION_FRAME_SIZE) + + str r0, [sp] + str r1, [sp,1] + str r2, [sp,2] + str r3, [sp,3] + str r4, [sp,4] + str r5, [sp,5] + str r6, [sp,6] + str r7, [sp,7] + str r8, [sp,8] + str r9, [sp,9] + str r10, [sp,10] + str fp, [sp,11] + str r12, [sp,12] + + /* Save interrupted task stack pointer */ + add r1, sp, #(CPU_EXCEPTION_FRAME_SIZE + 8) + str r1,[sp,13] + + str lr, [sp,14] + str r15, [sp,15] + str r16, [sp,16] + str r17, [sp,17] + str r18, [sp,18] + str r19, [sp,19] + str r20, [sp,20] + str r21, [sp,21] + str r22, [sp,22] + str r23, [sp,23] + str r24, [sp,24] + str r25, [sp,25] + str r26, [sp,26] + str r27, [sp,27] + str r28, [sp,28] + str r29, [sp,29] + str r30, [sp,30] + str r31, [sp,31] + str r32, [sp,32] + str r33, [sp,33] + str r34, [sp,34] + str r35, [sp,35] + str r36, [sp,36] + str r37, [sp,37] + str r38, [sp,38] + str r39, [sp,39] + str r40, [sp,40] + str r41, [sp,41] + str r42, [sp,42] + str r43, [sp,43] + str r44, [sp,44] + str r45, [sp,45] + str r46, [sp,46] + str r47, [sp,47] + str r48, [sp,48] + str r49, [sp,49] + str r50, [sp,50] + str r51, [sp,51] + str r52, [sp,52] + str r53, [sp,53] + str r54, [sp,54] + str r55, [sp,55] + str r56, [sp,56] + str r57, [sp,57] + str r58, [sp,58] + str r59, [sp,59] + str r60, [sp,60] + str r61, [sp,61] + /* r62 and r63 are saved from start.S interrupt entry + * and hold vector number and _ISR_Handler address repsectively. + */ + + /* Save status register */ + movfs r1,status + str r1, [sp,62] + + /* Save config register */ + movfs r1,config + str r1, [sp,63] + + /* Save interrupt return address register */ + movfs r1,iret + str r1, [sp,64] + + mov r33, %low(__Per_CPU_Information) + movt r33, %high(__Per_CPU_Information) + + add r6, r33, #(PER_CPU_ISR_NEST_LEVEL) + add r8, r33, #(PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL) + + /* Increment nesting level and disable thread dispatch */ + ldr r5, [r6] + ldr r7, [r8] + add r5, r5, #1 + add r7, r7, #1 + str r5, [r6] + str r7, [r8] + + /* Keep sp (Exception frame address) in r32 - Callee saved */ + mov r32, sp + + /* Keep __Per_CPU_Information address in r33 - Callee saved */ + mov r33, r18 + + /* Call the exception handler from vector table. + * First function arg for C handler is vector number, + * and the second is a pointer to exception frame. + */ + mov r0, r62 + mov r1, sp + + mov r27, r62 + lsl r27, r27, #2 + mov r26, %low(_bsp_start_vector_table_begin) + movt r15, #0 + add r27, r27, r26 + ldr r27, [r27] + + /* Do not switch stacks if we are in a nested interrupt. At + * this point r5 should be holding ISR_NEST_LEVEL value. + */ + sub r37, r5, #1 + bgtu jump_to_c_handler + + /* Switch to RTEMS dedicated interrupt stack */ + add sp, r18, #(PER_CPU_INTERRUPT_STACK_HIGH) + ldr sp, [sp] + +jump_to_c_handler: + jalr r27 + + /* Switch back to the interrupted task stack */ + mov sp, r32 + + /* Get the address of __Per_CPU_Information */ + mov r18, r33 + + /* Decrement nesting level and enable multitasking */ + add r6, r18, #(PER_CPU_ISR_NEST_LEVEL) + add r8, r18, #(PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL) + + ldr r5, [r6] + ldr r7, [r8] + sub r5, r5, #1 + sub r7, r7, #1 + str r5, [r6] + str r7, [r8] + + /* Check if _ISR_Nest_level > 0 */ + sub r37, r5, #0 + bgtu exception_frame_restore + + /* Check if _Thread_Dispatch_disable_level > 0 */ + sub r37, r7, #0 + bgtu exception_frame_restore + + /* Check if dispatch needed */ + add r31, r18, #(PER_CPU_DISPATCH_NEEDED) + ldr r31, [r31] + + sub r35, r31, #0 + beq exception_frame_restore + + mov r35, %low(__Thread_Dispatch) + movt r35, %high(__Thread_Dispatch) + jalr r35 + +exception_frame_restore: + + ldr r1, [sp,1] + ldr r2, [sp,2] + ldr r3, [sp,3] + ldr r4, [sp,4] + ldr r5, [sp,5] + ldr r6, [sp,6] + ldr r7, [sp,7] + ldr r8, [sp,8] + ldr r9, [sp,9] + ldr r10, [sp,10] + ldr fp, [sp,11] + ldr r12, [sp,12] + ldr lr, [sp,14] + ldr r15, [sp,15] + ldr r16, [sp,16] + ldr r17, [sp,17] + ldr r18, [sp,18] + ldr r19, [sp,19] + ldr r20, [sp,20] + ldr r21, [sp,21] + ldr r22, [sp,22] + ldr r23, [sp,23] + ldr r24, [sp,24] + ldr r25, [sp,25] + ldr r26, [sp,26] + ldr r27, [sp,27] + ldr r28, [sp,28] + ldr r29, [sp,29] + ldr r30, [sp,30] + ldr r31, [sp,31] + ldr r32, [sp,32] + ldr r34, [sp,34] + ldr r36, [sp,36] + ldr r38, [sp,38] + ldr r39, [sp,39] + ldr r40, [sp,40] + ldr r41, [sp,41] + ldr r42, [sp,42] + ldr r43, [sp,43] + ldr r44, [sp,44] + ldr r45, [sp,45] + ldr r46, [sp,46] + ldr r47, [sp,47] + ldr r48, [sp,48] + ldr r49, [sp,49] + ldr r50, [sp,50] + ldr r51, [sp,51] + ldr r52, [sp,52] + ldr r53, [sp,53] + ldr r54, [sp,54] + ldr r55, [sp,55] + ldr r56, [sp,56] + ldr r57, [sp,57] + ldr r58, [sp,58] + ldr r59, [sp,59] + ldr r60, [sp,60] + ldr r61, [sp,61] + + /* Restore status register */ + ldr r0,[sp,62] + movts status, r0 + + /* Restore config register */ + ldr r0, [sp,63] + movts config, r0 + + /* Restore interrupt return address register */ + ldr r0, [sp,64] + movts iret, r0 + + ldr r0,[sp] + + /* Restore interrupted task's stack pointer */ + ldr sp, [sp,13] + + /* r62 and r63 are saved from start.S interrupt entry + * and hold vector number and _ISR_Handler address repsectively. + */ + ldr r62, [sp, -8] + ldr r63, [sp, -4] + + /* return from interrupt */ + rti |