1/* 2 * Copyright (c) 2018, Synopsys, Inc. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6#define __ASSEMBLY__ 7#include "inc/arc/arc.h" 8#include "inc/arc/arc_asm_common.h" 9 10.global rt_interrupt_enter; .type rt_interrupt_enter, %function 11.global rt_interrupt_leave; .type rt_interrupt_leave, %function 12.global context_switch_reqflg; .type context_switch_reqflg, %object 13.global rt_interrupt_from_thread; .type rt_interrupt_from_thread, %object 14.global rt_interrupt_to_thread; .type rt_interrupt_to_thread, %object 15 16 .text 17 .align 4 18dispatcher: 19 st sp, [r0] 20 ld sp, [r1] 21 pop r0 22 j [r0] 23 24/* return routine when task dispatch happened in task context */ 25dispatch_r: 26 RESTORE_NONSCRATCH_REGS 27 j [blink] 28 29/* 30 * rt_base_t rt_hw_interrupt_disable(); 31 */ 32.global rt_hw_interrupt_disable 33.type rt_hw_interrupt_disable, %function 34rt_hw_interrupt_disable: 35 clri r0 36 j [blink] 37 38 39/* 40 * void rt_hw_interrupt_enable(rt_base_t level); 41 */ 42.global rt_hw_interrupt_enable 43.type rt_hw_interrupt_enable, %function 44rt_hw_interrupt_enable: 45 seti r0 46 j [blink] 47 48 49.global rt_hw_context_switch_interrupt 50.type rt_hw_context_switch_interrupt, %function 51rt_hw_context_switch_interrupt: 52 st r0, [rt_interrupt_from_thread] 53 st r1, [rt_interrupt_to_thread] 54 mov r0, 1 55 st r0, [context_switch_reqflg] 56 j [blink] 57 58 59/* 60 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 61 * r0 --> from 62 * r1 --> to 63 */ 64.global rt_hw_context_switch 65.type rt_hw_context_switch, %function 66rt_hw_context_switch: 67 SAVE_NONSCRATCH_REGS 68 mov r2, dispatch_r 69 push r2 70 b dispatcher 71 72 73/* 74 * void rt_hw_context_switch_to(rt_uint32 to); 75 * r0 --> to 76 */ 77.global rt_hw_context_switch_to 78.type rt_hw_context_switch_to, %function 79rt_hw_context_switch_to: 80 ld sp, [r0] 81 pop r0 82 j [r0] 83 84.global start_r 85.type start_r, %function 86start_r: 87 pop blink; 88 pop r1 89 pop r2 90 pop r0 91 92 j_s.d [r1] 93 kflag r2 94 95/****** exceptions and interrupts handing ******/ 96/****** entry for exception handling ******/ 97 .global exc_entry_cpu 98 .align 4 99exc_entry_cpu: 100 101 EXCEPTION_PROLOGUE 102 103 mov blink, sp 104 mov r3, sp /* as exception handler's para(p_excinfo) */ 105 106 ld r0, [exc_nest_count] 107 add r1, r0, 1 108 st r1, [exc_nest_count] 109 cmp r0, 0 110 bne exc_handler_1 111/* change to exception stack if interrupt happened in task context */ 112 mov sp, _e_stack 113exc_handler_1: 114 PUSH blink 115 116 lr r0, [AUX_ECR] 117 lsr r0, r0, 16 118 mov r1, exc_int_handler_table 119 ld.as r2, [r1, r0] 120 121 mov r0, r3 122 jl [r2] 123 124/* interrupts are not allowed */ 125ret_exc: 126 POP sp 127 mov r1, exc_nest_count 128 ld r0, [r1] 129 sub r0, r0, 1 130 cmp r0, 0 131 bne.d ret_exc_1 132 st r0, [r1] 133 134 ld r0, [context_switch_reqflg] 135 cmp r0, 0 136 bne ret_exc_2 137ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */ 138 EXCEPTION_EPILOGUE 139 rtie 140 141/* there is a dispatch request */ 142ret_exc_2: 143 /* clear dispatch request */ 144 mov r0, 0 145 st r0, [context_switch_reqflg] 146 147 SAVE_CALLEE_REGS /* save callee save registers */ 148 149 /* clear exception bit to do exception exit by SW */ 150 lr r0, [AUX_STATUS32] 151 bclr r0, r0, AUX_STATUS_BIT_AE 152 kflag r0 153 154 mov r1, ret_exc_r /* save return address */ 155 PUSH r1 156 157 ld r0, [rt_interrupt_from_thread] 158 ld r1, [rt_interrupt_to_thread] 159 b dispatcher 160 161ret_exc_r: 162 /* recover exception status */ 163 lr r0, [AUX_STATUS32] 164 bset r0, r0, AUX_STATUS_BIT_AE 165 kflag r0 166 167 RESTORE_CALLEE_REGS 168 EXCEPTION_EPILOGUE 169 rtie 170 171/****** entry for normal interrupt exception handling ******/ 172 .global exc_entry_int /* entry for interrupt handling */ 173 .align 4 174exc_entry_int: 175#if ARC_FEATURE_FIRQ == 1 176/* check whether it is P0 interrupt */ 177#if ARC_FEATURE_RGF_NUM_BANKS > 1 178 lr r0, [AUX_IRQ_ACT] 179 btst r0, 0 180 jnz exc_entry_firq 181#else 182 PUSH r10 183 lr r10, [AUX_IRQ_ACT] 184 btst r10, 0 185 POP r10 186 jnz exc_entry_firq 187#endif 188#endif 189 INTERRUPT_PROLOGUE 190 191 mov blink, sp 192 193 clri /* disable interrupt */ 194 ld r3, [exc_nest_count] 195 add r2, r3, 1 196 st r2, [exc_nest_count] 197 seti /* enable higher priority interrupt */ 198 199 cmp r3, 0 200 bne irq_handler_1 201/* change to exception stack if interrupt happened in task context */ 202 mov sp, _e_stack 203irq_handler_1: 204 PUSH blink 205 206 jl rt_interrupt_enter 207 208 lr r0, [AUX_IRQ_CAUSE] 209 sr r0, [AUX_IRQ_SELECT] 210 mov r1, exc_int_handler_table 211 ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */ 212/* handle software triggered interrupt */ 213 lr r3, [AUX_IRQ_HINT] 214 cmp r3, r0 215 bne.d irq_hint_handled 216 xor r3, r3, r3 217 sr r3, [AUX_IRQ_HINT] 218irq_hint_handled: 219 lr r3, [AUX_IRQ_PRIORITY] 220 PUSH r3 /* save irq priority */ 221 222 jl [r2] /* jump to interrupt handler */ 223 jl rt_interrupt_leave 224ret_int: 225 clri /* disable interrupt */ 226 POP r3 /* irq priority */ 227 POP sp 228 mov r1, exc_nest_count 229 ld r0, [r1] 230 sub r0, r0, 1 231 cmp r0, 0 232 bne.d ret_int_1 233 st r0, [r1] 234 235 ld r0, [context_switch_reqflg] 236 cmp r0, 0 237 bne ret_int_2 238ret_int_1: /* return from non-task context */ 239 INTERRUPT_EPILOGUE 240 rtie 241/* there is a dispatch request */ 242ret_int_2: 243 /* clear dispatch request */ 244 mov r0, 0 245 st r0, [context_switch_reqflg] 246 247 /* interrupt return by SW */ 248 lr r10, [AUX_IRQ_ACT] 249 PUSH r10 250 bclr r10, r10, r3 /* clear related bits in IRQ_ACT */ 251 sr r10, [AUX_IRQ_ACT] 252 253 SAVE_CALLEE_REGS /* save callee save registers */ 254 mov r1, ret_int_r /* save return address */ 255 PUSH r1 256 257 ld r0, [rt_interrupt_from_thread] 258 ld r1, [rt_interrupt_to_thread] 259 b dispatcher 260 261ret_int_r: 262 RESTORE_CALLEE_REGS 263 /* recover AUX_IRQ_ACT to restore the interrup status */ 264 POPAX AUX_IRQ_ACT 265 INTERRUPT_EPILOGUE 266 rtie