/* SPDX-License-Identifier: BSD-2-Clause */ /** * @file * * @ingroup RTEMSScoreCPUMicroBlaze * * @brief MicroBlaze interrupt handler implementation */ /* * Copyright (C) 2021 On-Line Applications Research Corporation (OAR) * * 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 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. */ #include #include .text .globl _ISR_Handler .align 2 _ISR_Handler: /* Save stack frame */ swi r3, r1, MICROBLAZE_INTERRUPT_FRAME_R3 swi r4, r1, MICROBLAZE_INTERRUPT_FRAME_R4 swi r6, r1, MICROBLAZE_INTERRUPT_FRAME_R6 swi r7, r1, MICROBLAZE_INTERRUPT_FRAME_R7 swi r8, r1, MICROBLAZE_INTERRUPT_FRAME_R8 swi r9, r1, MICROBLAZE_INTERRUPT_FRAME_R9 swi r10, r1, MICROBLAZE_INTERRUPT_FRAME_R10 swi r11, r1, MICROBLAZE_INTERRUPT_FRAME_R11 swi r12, r1, MICROBLAZE_INTERRUPT_FRAME_R12 swi r15, r1, MICROBLAZE_INTERRUPT_FRAME_R15 swi r18, r1, MICROBLAZE_INTERRUPT_FRAME_R18 xori r3, r5, 0xFFFF beqi r3, do_exception /* Disable dispatching */ lwi r3, r0, _Per_CPU_Information + 16 addik r3, r3, 1 swi r3, r0, _Per_CPU_Information + 16 swi r14, r1, MICROBLAZE_INTERRUPT_FRAME_R14 /* Is SP < INTERRUPT_STACK_LOW? */ lwi r4, r0, _Per_CPU_Information rsubk r3, r4, r1 blei r3, switch_to_interrupt_stack /* Is SP > INTERRUPT_STACK_HIGH? */ lwi r4, r0, _Per_CPU_Information + 4 rsubk r3, r4, r1 bgei r3, switch_to_interrupt_stack bri on_interrupt_stack switch_to_interrupt_stack: add r4, r0, r1 lwi r1, r0, _Per_CPU_Information + 4 addik r1, r1, -52 swi r4, r1, 0 on_interrupt_stack: /* Add 1 to ISR_NEST_LEVEL */ lwi r3, r0, _Per_CPU_Information + 8 addik r3, r3, 1 swi r3, r0, _Per_CPU_Information + 8 bralid r15, bsp_interrupt_dispatch nop /* Subtract 1 from ISR_NEST_LEVEL */ lwi r3, r0, _Per_CPU_Information + 8 addik r3, r3, -1 swi r3, r0, _Per_CPU_Information + 8 /* Is ISR_NEST_LEVEL > 0? */ bgti r3, after_stack_switch /* Switch back to interrupted thread stack */ lwi r1, r1, 0 after_stack_switch: /* Subtract 1 from THREAD_DISPATCH_DISABLE_LEVEL */ lwi r3, r0, _Per_CPU_Information + 16 addik r3, r3, -1 swi r3, r0, _Per_CPU_Information + 16 /* Is THREAD_DISPATCH_DISABLE_LEVEL != 0? */ bnei r3, quick_exit /* Is DISPATCH_NEEDED == 0? */ lwi r3, r0, _Per_CPU_Information + 20 beqi r3, quick_exit /* Return to interrupted thread and make it do a dispatch */ addik r14, r0, thread_dispatch rtid r14, 0 nop quick_exit: /* Simple return from nested interrupt */ /* Restore registers */ lwi r3, r1, MICROBLAZE_INTERRUPT_FRAME_R3 lwi r4, r1, MICROBLAZE_INTERRUPT_FRAME_R4 lwi r5, r1, MICROBLAZE_INTERRUPT_FRAME_R5 lwi r6, r1, MICROBLAZE_INTERRUPT_FRAME_R6 lwi r7, r1, MICROBLAZE_INTERRUPT_FRAME_R7 lwi r8, r1, MICROBLAZE_INTERRUPT_FRAME_R8 lwi r9, r1, MICROBLAZE_INTERRUPT_FRAME_R9 lwi r10, r1, MICROBLAZE_INTERRUPT_FRAME_R10 lwi r11, r1, MICROBLAZE_INTERRUPT_FRAME_R11 lwi r12, r1, MICROBLAZE_INTERRUPT_FRAME_R12 lwi r14, r1, MICROBLAZE_INTERRUPT_FRAME_R14 lwi r15, r1, MICROBLAZE_INTERRUPT_FRAME_R15 lwi r18, r1, MICROBLAZE_INTERRUPT_FRAME_R18 /* Remove stack frame */ addik r1, r1, 52 rtid r14, 0 nop thread_dispatch: /* Reserve stack */ addik r1, r1, -52 /* Save scratch registers */ swi r3, r1, MICROBLAZE_INTERRUPT_FRAME_R3 swi r4, r1, MICROBLAZE_INTERRUPT_FRAME_R4 swi r5, r1, MICROBLAZE_INTERRUPT_FRAME_R5 swi r6, r1, MICROBLAZE_INTERRUPT_FRAME_R6 swi r7, r1, MICROBLAZE_INTERRUPT_FRAME_R7 swi r8, r1, MICROBLAZE_INTERRUPT_FRAME_R8 swi r9, r1, MICROBLAZE_INTERRUPT_FRAME_R9 swi r10, r1, MICROBLAZE_INTERRUPT_FRAME_R10 swi r11, r1, MICROBLAZE_INTERRUPT_FRAME_R11 swi r12, r1, MICROBLAZE_INTERRUPT_FRAME_R12 swi r14, r1, MICROBLAZE_INTERRUPT_FRAME_R14 swi r15, r1, MICROBLAZE_INTERRUPT_FRAME_R15 swi r18, r1, MICROBLAZE_INTERRUPT_FRAME_R18 bralid r15, _Thread_Dispatch nop /* Restore scratch registers */ lwi r3, r1, MICROBLAZE_INTERRUPT_FRAME_R3 lwi r4, r1, MICROBLAZE_INTERRUPT_FRAME_R4 lwi r5, r1, MICROBLAZE_INTERRUPT_FRAME_R5 lwi r6, r1, MICROBLAZE_INTERRUPT_FRAME_R6 lwi r7, r1, MICROBLAZE_INTERRUPT_FRAME_R7 lwi r8, r1, MICROBLAZE_INTERRUPT_FRAME_R8 lwi r9, r1, MICROBLAZE_INTERRUPT_FRAME_R9 lwi r10, r1, MICROBLAZE_INTERRUPT_FRAME_R10 lwi r11, r1, MICROBLAZE_INTERRUPT_FRAME_R11 lwi r12, r1, MICROBLAZE_INTERRUPT_FRAME_R12 lwi r14, r1, MICROBLAZE_INTERRUPT_FRAME_R14 lwi r15, r1, MICROBLAZE_INTERRUPT_FRAME_R15 lwi r18, r1, MICROBLAZE_INTERRUPT_FRAME_R18 /* Free stack space */ addik r1, r1, 52 bri quick_exit do_exception: /* exception no longer in progress */ mfs r3, rmsr andni r3, r3, 0x200 mts rmsr, r3 addi r5, r0, 9 add r6, r0, r1 brai _Terminate