123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- /*
- * Copyright (c) 2018, Synopsys, Inc.
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #define __ASSEMBLY__
- #include "include/arc/arc.h"
- #include "include/arc/arc_asm_common.h"
- .global rt_interrupt_enter;
- .global rt_interrupt_leave;
- .global rt_thread_switch_interrupt_flag;
- .global rt_interrupt_from_thread;
- .global rt_interrupt_to_thread;
- .global exc_nest_count;
- .global set_hw_stack_check;
- .text
- .align 4
- dispatcher:
- st sp, [r0]
- ld sp, [r1]
- #if ARC_FEATURE_STACK_CHECK
- #if ARC_FEATURE_SEC_PRESENT
- lr r0, [AUX_SEC_STAT]
- bclr r0, r0, AUX_SEC_STAT_BIT_SSC
- sflag r0
- #else
- lr r0, [AUX_STATUS32]
- bclr r0, r0, AUX_STATUS_BIT_SC
- kflag r0
- #endif
- jl set_hw_stack_check
- #if ARC_FEATURE_SEC_PRESENT
- lr r0, [AUX_SEC_STAT]
- bset r0, r0, AUX_SEC_STAT_BIT_SSC
- sflag r0
- #else
- lr r0, [AUX_STATUS32]
- bset r0, r0, AUX_STATUS_BIT_SC
- kflag r0
- #endif
- #endif
- pop r0
- j [r0]
- /* return routine when task dispatch happened in task context */
- dispatch_r:
- RESTORE_NONSCRATCH_REGS
- RESTORE_R0_TO_R12
- j [blink]
- /*
- * rt_base_t rt_hw_interrupt_disable();
- */
- .global rt_hw_interrupt_disable
- .align 4
- rt_hw_interrupt_disable:
- clri r0
- j [blink]
- /*
- * void rt_hw_interrupt_enable(rt_base_t level);
- */
- .global rt_hw_interrupt_enable
- .align 4
- rt_hw_interrupt_enable:
- seti r0
- j [blink]
- .global rt_hw_context_switch_interrupt
- .align 4
- rt_hw_context_switch_interrupt:
- ld r2, [rt_thread_switch_interrupt_flag]
- breq r2, 1, _reswitch /* Check the flag, if it is 1, skip to reswitch */
- mov r2, 1
- st r2, [rt_thread_switch_interrupt_flag]
- st r0, [rt_interrupt_from_thread]
- _reswitch:
- st r1, [rt_interrupt_to_thread]
- j [blink]
- /*
- * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
- * r0 --> from
- * r1 --> to
- */
- .global rt_hw_context_switch
- .align 4
- rt_hw_context_switch:
- SAVE_R0_TO_R12
- SAVE_NONSCRATCH_REGS
- mov r2, dispatch_r
- push r2
- b dispatcher
- /*
- * void rt_hw_context_switch_to(rt_uint32 to);
- * r0 --> to
- */
- .global rt_hw_context_switch_to
- .align 4
- rt_hw_context_switch_to:
- ld sp, [r0]
- #if ARC_FEATURE_STACK_CHECK
- mov r1, r0
- #if ARC_FEATURE_SEC_PRESENT
- lr r0, [AUX_SEC_STAT]
- bclr r0, r0, AUX_SEC_STAT_BIT_SSC
- sflag r0
- #else
- lr r0, [AUX_STATUS32]
- bclr r0, r0, AUX_STATUS_BIT_SC
- kflag r0
- #endif
- jl set_hw_stack_check
- #if ARC_FEATURE_SEC_PRESENT
- lr r0, [AUX_SEC_STAT]
- bset r0, r0, AUX_SEC_STAT_BIT_SSC
- sflag r0
- #else
- lr r0, [AUX_STATUS32]
- bset r0, r0, AUX_STATUS_BIT_SC
- kflag r0
- #endif
- #endif
- pop r0
- j [r0]
- .global start_r
- .align 4
- start_r:
- pop blink;
- pop r1
- pop r2
- pop r0
- j_s.d [r1]
- kflag r2
- /*
- * int __rt_ffs(int value);
- * r0 --> value
- */
- .global __rt_ffs
- .align 4
- __rt_ffs:
- breq r0, 0, __rt_ffs_return
- ffs r1, r0
- add r0, r1, 1
- __rt_ffs_return:
- j [blink]
- /****** exceptions and interrupts handing ******/
- /****** entry for exception handling ******/
- .global exc_entry_cpu
- .align 4
- exc_entry_cpu:
- EXCEPTION_PROLOGUE
- mov blink, sp
- mov r3, sp /* as exception handler's para(p_excinfo) */
- ld r0, [exc_nest_count]
- add r1, r0, 1
- st r1, [exc_nest_count]
- brne r0, 0, exc_handler_1
- /* change to exception stack if interrupt happened in task context */
- mov sp, _e_stack
- exc_handler_1:
- PUSH blink
- lr r0, [AUX_ECR]
- lsr r0, r0, 16
- mov r1, exc_int_handler_table
- ld.as r2, [r1, r0]
- mov r0, r3
- jl [r2]
- /* interrupts are not allowed */
- ret_exc:
- POP sp
- mov r1, exc_nest_count
- ld r0, [r1]
- sub r0, r0, 1
- st r0, [r1]
- brne r0, 0, ret_exc_1 /* nest exception case */
- lr r1, [AUX_IRQ_ACT] /* nest interrupt case */
- brne r1, 0, ret_exc_1
- ld r0, [rt_thread_switch_interrupt_flag]
- brne r0, 0, ret_exc_2
- ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */
- EXCEPTION_EPILOGUE
- rtie
- /* there is a dispatch request */
- ret_exc_2:
- /* clear dispatch request */
- mov r0, 0
- st r0, [rt_thread_switch_interrupt_flag]
- SAVE_CALLEE_REGS /* save callee save registers */
- /* clear exception bit to do exception exit by SW */
- lr r0, [AUX_STATUS32]
- bclr r0, r0, AUX_STATUS_BIT_AE
- kflag r0
- mov r1, ret_exc_r /* save return address */
- PUSH r1
- ld r0, [rt_interrupt_from_thread]
- ld r1, [rt_interrupt_to_thread]
- b dispatcher
- ret_exc_r:
- /* recover exception status */
- lr r0, [AUX_STATUS32]
- bset r0, r0, AUX_STATUS_BIT_AE
- kflag r0
- RESTORE_CALLEE_REGS
- EXCEPTION_EPILOGUE
- rtie
- /****** entry for normal interrupt exception handling ******/
- .global exc_entry_int /* entry for interrupt handling */
- .align 4
- exc_entry_int:
- #if ARC_FEATURE_FIRQ == 1
- /* check whether it is P0 interrupt */
- #if ARC_FEATURE_RGF_NUM_BANKS > 1
- lr r0, [AUX_IRQ_ACT]
- btst r0, 0
- jnz exc_entry_firq
- #else
- PUSH r10
- lr r10, [AUX_IRQ_ACT]
- btst r10, 0
- POP r10
- jnz exc_entry_firq
- #endif
- #endif
- INTERRUPT_PROLOGUE
- mov blink, sp
- clri /* disable interrupt */
- ld r3, [exc_nest_count]
- add r2, r3, 1
- st r2, [exc_nest_count]
- seti /* enable higher priority interrupt */
- brne r3, 0, irq_handler_1
- /* change to exception stack if interrupt happened in task context */
- mov sp, _e_stack
- #if ARC_FEATURE_STACK_CHECK
- #if ARC_FEATURE_SEC_PRESENT
- lr r0, [AUX_SEC_STAT]
- bclr r0, r0, AUX_SEC_STAT_BIT_SSC
- sflag r0
- #else
- lr r0, [AUX_STATUS32]
- bclr r0, r0, AUX_STATUS_BIT_SC
- kflag r0
- #endif
- #endif
- irq_handler_1:
- PUSH blink
- jl rt_interrupt_enter
- lr r0, [AUX_IRQ_CAUSE]
- sr r0, [AUX_IRQ_SELECT]
- mov r1, exc_int_handler_table
- ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */
- /* handle software triggered interrupt */
- lr r3, [AUX_IRQ_HINT]
- cmp r3, r0
- bne.d irq_hint_handled
- xor r3, r3, r3
- sr r3, [AUX_IRQ_HINT]
- irq_hint_handled:
- lr r3, [AUX_IRQ_PRIORITY]
- PUSH r3 /* save irq priority */
- jl [r2] /* jump to interrupt handler */
- jl rt_interrupt_leave
- ret_int:
- clri /* disable interrupt */
- POP r3 /* irq priority */
- POP sp
- mov r1, exc_nest_count
- ld r0, [r1]
- sub r0, r0, 1
- st r0, [r1]
- /* if there are multi-bits set in IRQ_ACT, it's still in nest interrupt */
- lr r0, [AUX_IRQ_CAUSE]
- sr r0, [AUX_IRQ_SELECT]
- lr r3, [AUX_IRQ_PRIORITY]
- lr r1, [AUX_IRQ_ACT]
- bclr r2, r1, r3
- brne r2, 0, ret_int_1
- ld r0, [rt_thread_switch_interrupt_flag]
- brne r0, 0, ret_int_2
- ret_int_1: /* return from non-task context */
- INTERRUPT_EPILOGUE
- rtie
- /* there is a dispatch request */
- ret_int_2:
- /* clear dispatch request */
- mov r0, 0
- st r0, [rt_thread_switch_interrupt_flag]
- /* interrupt return by SW */
- lr r10, [AUX_IRQ_ACT]
- PUSH r10
- bclr r10, r10, r3 /* clear related bits in IRQ_ACT */
- sr r10, [AUX_IRQ_ACT]
- SAVE_CALLEE_REGS /* save callee save registers */
- mov r1, ret_int_r /* save return address */
- PUSH r1
- ld r0, [rt_interrupt_from_thread]
- ld r1, [rt_interrupt_to_thread]
- b dispatcher
- ret_int_r:
- RESTORE_CALLEE_REGS
- /* recover AUX_IRQ_ACT to restore the interrup status */
- POPAX AUX_IRQ_ACT
- INTERRUPT_EPILOGUE
- rtie
- /****** entry for fast irq exception handling ******/
- .global exc_entry_firq
- .weak exc_entry_firq
- .align 4
- exc_entry_firq:
- SAVE_FIQ_EXC_REGS
- lr r0, [AUX_IRQ_CAUSE]
- mov r1, exc_int_handler_table
- /* r2 = _kernel_exc_tbl + irqno *4 */
- ld.as r2, [r1, r0]
- /* for the case of software triggered interrupt */
- lr r3, [AUX_IRQ_HINT]
- cmp r3, r0
- bne.d firq_hint_handled
- xor r3, r3, r3
- sr r3, [AUX_IRQ_HINT]
- firq_hint_handled:
- /* jump to interrupt handler */
- mov r0, sp
- jl [r2]
- firq_return:
- RESTORE_FIQ_EXC_REGS
- rtie
|