diff options
Diffstat (limited to 'cpukit/score/cpu/or1k/or1k-exception-handler-low.S')
-rw-r--r-- | cpukit/score/cpu/or1k/or1k-exception-handler-low.S | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/cpukit/score/cpu/or1k/or1k-exception-handler-low.S b/cpukit/score/cpu/or1k/or1k-exception-handler-low.S new file mode 100644 index 0000000000..964a05477d --- /dev/null +++ b/cpukit/score/cpu/or1k/or1k-exception-handler-low.S @@ -0,0 +1,216 @@ +/** + * @file + * + * @ingroup ScoreCPU + * + * @brief OR1K exception support implementation. + */ + +/* + * COPYRIGHT (c) 2014 Hesham ALMatary <heshamelmatary@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/asm.h> +#include <rtems/score/percpu.h> +#include "rtems/score/or1k-utility.h" + +.align 4 +.text +PUBLIC(_ISR_Handler) +.type _ISR_Handler,@function + + SYM(_ISR_Handler): + + l.addi r1, r1, -140 + + l.sw 8(r1),r2 + /* r3 is saved by BSP exception handler */ + l.sw 16(r1),r4 + l.sw 20(r1),r5 + l.sw 24(r1),r6 + l.sw 28(r1),r7 + l.sw 32(r1),r8 + l.sw 36(r1),r9 + l.sw 40(r1),r10 + l.sw 44(r1),r11 + l.sw 48(r1),r12 + l.sw 52(r1),r13 + l.sw 56(r1),r14 + l.sw 60(r1),r15 + l.sw 64(r1),r16 + l.sw 68(r1),r17 + l.sw 72(r1),r18 + l.sw 76(r1),r19 + l.sw 80(r1),r20 + l.sw 84(r1),r21 + l.sw 88(r1),r22 + l.sw 92(r1),r23 + l.sw 96(r1),r24 + l.sw 100(r1),r25 + l.sw 104(r1),r26 + l.sw 108(r1),r27 + l.sw 112(r1),r28 + l.sw 116(r1),r29 + l.sw 120(r1),r30 + l.sw 124(r1),r31 + + /* Exception level related registers */ + + /* EPCR */ + l.mfspr r13, r0, CPU_OR1K_SPR_EPCR0 + l.sw 128(r1), r13 /* epcr */ + + /* EEAR */ + l.mfspr r13, r0, CPU_OR1K_SPR_EEAR0 + l.sw 132(r1), r13 /* eear */ + + /* ESR */ + l.mfspr r13, r0, CPU_OR1K_SPR_ESR0 + l.sw 136(r1), r13 /* esr */ + + /* Increment nesting level */ + l.movhi r6, hi(ISR_NEST_LEVEL) + l.ori r6, r6, lo(ISR_NEST_LEVEL) + + /* Disable multitasking */ + l.movhi r8, hi(THREAD_DISPATCH_DISABLE_LEVEL) + l.ori r8, r8, lo(THREAD_DISPATCH_DISABLE_LEVEL) + + l.lwz r5, 0(r6) + l.lwz r7, 0(r8) + l.addi r5, r5, 1 + l.addi r7, r7, 1 + l.sw 0(r6), r5 + l.sw 0(r8), r7 + + /* Save interrupted task stack pointer */ + l.addi r4, r1, 144 + l.sw 4(r1), r4 + + /* Save interrupted task r3 (first arg) value */ + l.addi r4, r1, 140 + l.lwz r4, 0(r4) + l.sw 12(r1), r4 + + /* Keep r1 (Exception frame address) in r14 */ + l.add r14, r1, r0 + + /* 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. + */ + l.add r13, r3, r0 + l.add r4, r1, r0 + l.slli r13, r13, 2 + l.addi r13, r13, lo(bsp_start_vector_table_begin) + l.lwz r13, 0(r13) + + /* Do not switch stacks if we are in a nested interrupt. At + * this point r5 should be holding ISR_NEST_LEVEL value. + */ + l.sfgtui r5, 2 + l.bf jump_to_c_handler + l.nop + + /* Switch to RTEMS dedicated interrupt stack */ + l.movhi r1, hi(INTERRUPT_STACK_HIGH) + l.ori r1, r1, lo(INTERRUPT_STACK_HIGH) + l.lwz r1, 0(r1) + +jump_to_c_handler: + l.jalr r13 + l.nop + + /* Switch back to the interrupted task stack */ + l.add r1, r14, r0 + + /* Check if dispatch needed */ + l.movhi r31, hi(DISPATCH_NEEDED) + l.ori r31, r31, lo(DISPATCH_NEEDED) + l.lwz r31, 0(r31) + l.sfeq r31, r0 + l.bf exception_frame_restore + l.nop + + l.movhi r13, hi(_Thread_Dispatch) + l.ori r13, r13, lo(_Thread_Dispatch) + l.jalr r13 + l.nop + + SYM(exception_frame_restore): + + /* Exception level related registers */ + + /* EPCR */ + l.lwz r13, 128(r1) + l.mtspr r0, r13, CPU_OR1K_SPR_EPCR0 + + /* EEAR */ + l.lwz r13, 132(r1) + l.mtspr r0, r13, CPU_OR1K_SPR_EEAR0 + + /* ESR */ + l.lwz r13, 136(r1) + l.mtspr r0, r13, CPU_OR1K_SPR_ESR0 + + /* Increment nesting level */ + l.movhi r6, hi(ISR_NEST_LEVEL) + l.ori r6, r6, lo(ISR_NEST_LEVEL) + + /* Disable multitasking */ + l.movhi r8, hi(THREAD_DISPATCH_DISABLE_LEVEL) + l.ori r8, r8, lo(THREAD_DISPATCH_DISABLE_LEVEL) + + l.lwz r5, 0(r6) + l.lwz r7, 0(r8) + l.addi r5, r5, -1 + l.addi r7, r7, -1 + l.sw 0(r6), r5 + l.sw 0(r8), r7 + + l.lwz r2, 8(r1) + l.lwz r3, 12(r1) + l.lwz r4, 16(r1) + l.lwz r5, 20(r1) + l.lwz r6, 24(r1) + l.lwz r7, 28(r1) + l.lwz r8, 32(r1) + l.lwz r9, 36(r1) + l.lwz r10, 40(r1) + l.lwz r11, 44(r1) + l.lwz r12, 48(r1) + l.lwz r13, 52(r1) + l.lwz r14, 56(r1) + l.lwz r15, 60(r1) + l.lwz r16, 64(r1) + l.lwz r17, 68(r1) + l.lwz r18, 72(r1) + l.lwz r19, 76(r1) + l.lwz r20, 80(r1) + l.lwz r21, 84(r1) + l.lwz r22, 88(r1) + l.lwz r23, 92(r1) + l.lwz r24, 96(r1) + l.lwz r25, 100(r1) + l.lwz r26, 104(r1) + l.lwz r27, 108(r1) + l.lwz r28, 112(r1) + l.lwz r29, 116(r1) + l.lwz r30, 120(r1) + + l.addi r1, r1, 140 + + l.addi r1, r1, 4 + + l.rfe + l.nop |