1/* 2 * Copyright (c) 2018, Synopsys, Inc. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6#define __ASSEMBLY__ 7#include "include/arc/arc.h" 8#include "include/arc/arc_asm_common.h" 9 10.global rt_interrupt_enter; 11.global rt_interrupt_leave; 12.global rt_thread_switch_interrupt_flag; 13.global rt_interrupt_from_thread; 14.global rt_interrupt_to_thread; 15.global exc_nest_count; 16.global set_hw_stack_check; 17 18 .text 19 .align 4 20dispatcher: 21 st sp, [r0] 22 ld sp, [r1] 23#if ARC_FEATURE_STACK_CHECK 24#if ARC_FEATURE_SEC_PRESENT 25 lr r0, [AUX_SEC_STAT] 26 bclr r0, r0, AUX_SEC_STAT_BIT_SSC 27 sflag r0 28#else 29 lr r0, [AUX_STATUS32] 30 bclr r0, r0, AUX_STATUS_BIT_SC 31 kflag r0 32#endif 33 jl set_hw_stack_check 34#if ARC_FEATURE_SEC_PRESENT 35 lr r0, [AUX_SEC_STAT] 36 bset r0, r0, AUX_SEC_STAT_BIT_SSC 37 sflag r0 38#else 39 lr r0, [AUX_STATUS32] 40 bset r0, r0, AUX_STATUS_BIT_SC 41 kflag r0 42#endif 43#endif 44 pop r0 45 j [r0] 46 47/* return routine when task dispatch happened in task context */ 48dispatch_r: 49 RESTORE_NONSCRATCH_REGS 50 RESTORE_R0_TO_R12 51 j [blink] 52 53/* 54 * rt_base_t rt_hw_interrupt_disable(); 55 */ 56 .global rt_hw_interrupt_disable 57 .align 4 58rt_hw_interrupt_disable: 59 clri r0 60 j [blink] 61 62 63/* 64 * void rt_hw_interrupt_enable(rt_base_t level); 65 */ 66 .global rt_hw_interrupt_enable 67 .align 4 68rt_hw_interrupt_enable: 69 seti r0 70 j [blink] 71 72 73 .global rt_hw_context_switch_interrupt 74 .align 4 75rt_hw_context_switch_interrupt: 76 ld r2, [rt_thread_switch_interrupt_flag] 77 breq r2, 1, _reswitch /* Check the flag, if it is 1, skip to reswitch */ 78 mov r2, 1 79 st r2, [rt_thread_switch_interrupt_flag] 80 st r0, [rt_interrupt_from_thread] 81_reswitch: 82 st r1, [rt_interrupt_to_thread] 83 j [blink] 84 85 86/* 87 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to); 88 * r0 --> from 89 * r1 --> to 90 */ 91 .global rt_hw_context_switch 92 .align 4 93rt_hw_context_switch: 94 SAVE_R0_TO_R12 95 SAVE_NONSCRATCH_REGS 96 mov r2, dispatch_r 97 push r2 98 b dispatcher 99 100 101/* 102 * void rt_hw_context_switch_to(rt_uint32 to); 103 * r0 --> to 104 */ 105 .global rt_hw_context_switch_to 106 .align 4 107rt_hw_context_switch_to: 108 ld sp, [r0] 109#if ARC_FEATURE_STACK_CHECK 110 mov r1, r0 111#if ARC_FEATURE_SEC_PRESENT 112 lr r0, [AUX_SEC_STAT] 113 bclr r0, r0, AUX_SEC_STAT_BIT_SSC 114 sflag r0 115#else 116 lr r0, [AUX_STATUS32] 117 bclr r0, r0, AUX_STATUS_BIT_SC 118 kflag r0 119#endif 120 jl set_hw_stack_check 121#if ARC_FEATURE_SEC_PRESENT 122 lr r0, [AUX_SEC_STAT] 123 bset r0, r0, AUX_SEC_STAT_BIT_SSC 124 sflag r0 125#else 126 lr r0, [AUX_STATUS32] 127 bset r0, r0, AUX_STATUS_BIT_SC 128 kflag r0 129#endif 130#endif 131 pop r0 132 j [r0] 133 134 .global start_r 135 .align 4 136start_r: 137 pop blink; 138 pop r1 139 pop r2 140 pop r0 141 142 j_s.d [r1] 143 kflag r2 144 145/* 146 * int __rt_ffs(int value); 147 * r0 --> value 148 */ 149 .global __rt_ffs 150 .align 4 151__rt_ffs: 152 breq r0, 0, __rt_ffs_return 153 ffs r1, r0 154 add r0, r1, 1 155__rt_ffs_return: 156 j [blink] 157 158/****** exceptions and interrupts handing ******/ 159/****** entry for exception handling ******/ 160 .global exc_entry_cpu 161 .align 4 162exc_entry_cpu: 163 164 EXCEPTION_PROLOGUE 165 166 mov blink, sp 167 mov r3, sp /* as exception handler's para(p_excinfo) */ 168 169 ld r0, [exc_nest_count] 170 add r1, r0, 1 171 st r1, [exc_nest_count] 172 brne r0, 0, exc_handler_1 173/* change to exception stack if interrupt happened in task context */ 174 mov sp, _e_stack 175exc_handler_1: 176 PUSH blink 177 178 lr r0, [AUX_ECR] 179 lsr r0, r0, 16 180 mov r1, exc_int_handler_table 181 ld.as r2, [r1, r0] 182 183 mov r0, r3 184 jl [r2] 185 186/* interrupts are not allowed */ 187ret_exc: 188 POP sp 189 mov r1, exc_nest_count 190 ld r0, [r1] 191 sub r0, r0, 1 192 st r0, [r1] 193 brne r0, 0, ret_exc_1 /* nest exception case */ 194 lr r1, [AUX_IRQ_ACT] /* nest interrupt case */ 195 brne r1, 0, ret_exc_1 196 197 ld r0, [rt_thread_switch_interrupt_flag] 198 brne r0, 0, ret_exc_2 199ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */ 200 EXCEPTION_EPILOGUE 201 rtie 202 203/* there is a dispatch request */ 204ret_exc_2: 205 /* clear dispatch request */ 206 mov r0, 0 207 st r0, [rt_thread_switch_interrupt_flag] 208 209 SAVE_CALLEE_REGS /* save callee save registers */ 210 211 /* clear exception bit to do exception exit by SW */ 212 lr r0, [AUX_STATUS32] 213 bclr r0, r0, AUX_STATUS_BIT_AE 214 kflag r0 215 216 mov r1, ret_exc_r /* save return address */ 217 PUSH r1 218 219 ld r0, [rt_interrupt_from_thread] 220 ld r1, [rt_interrupt_to_thread] 221 b dispatcher 222 223ret_exc_r: 224 /* recover exception status */ 225 lr r0, [AUX_STATUS32] 226 bset r0, r0, AUX_STATUS_BIT_AE 227 kflag r0 228 229 RESTORE_CALLEE_REGS 230 EXCEPTION_EPILOGUE 231 rtie 232 233/****** entry for normal interrupt exception handling ******/ 234 .global exc_entry_int /* entry for interrupt handling */ 235 .align 4 236exc_entry_int: 237#if ARC_FEATURE_FIRQ == 1 238/* check whether it is P0 interrupt */ 239#if ARC_FEATURE_RGF_NUM_BANKS > 1 240 lr r0, [AUX_IRQ_ACT] 241 btst r0, 0 242 jnz exc_entry_firq 243#else 244 PUSH r10 245 lr r10, [AUX_IRQ_ACT] 246 btst r10, 0 247 POP r10 248 jnz exc_entry_firq 249#endif 250#endif 251 INTERRUPT_PROLOGUE 252 253 mov blink, sp 254 255 clri /* disable interrupt */ 256 ld r3, [exc_nest_count] 257 add r2, r3, 1 258 st r2, [exc_nest_count] 259 seti /* enable higher priority interrupt */ 260 261 brne r3, 0, irq_handler_1 262/* change to exception stack if interrupt happened in task context */ 263 mov sp, _e_stack 264#if ARC_FEATURE_STACK_CHECK 265#if ARC_FEATURE_SEC_PRESENT 266 lr r0, [AUX_SEC_STAT] 267 bclr r0, r0, AUX_SEC_STAT_BIT_SSC 268 sflag r0 269#else 270 lr r0, [AUX_STATUS32] 271 bclr r0, r0, AUX_STATUS_BIT_SC 272 kflag r0 273#endif 274#endif 275irq_handler_1: 276 PUSH blink 277 278 jl rt_interrupt_enter 279 280 lr r0, [AUX_IRQ_CAUSE] 281 sr r0, [AUX_IRQ_SELECT] 282 mov r1, exc_int_handler_table 283 ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */ 284/* handle software triggered interrupt */ 285 lr r3, [AUX_IRQ_HINT] 286 cmp r3, r0 287 bne.d irq_hint_handled 288 xor r3, r3, r3 289 sr r3, [AUX_IRQ_HINT] 290irq_hint_handled: 291 lr r3, [AUX_IRQ_PRIORITY] 292 PUSH r3 /* save irq priority */ 293 294 jl [r2] /* jump to interrupt handler */ 295 jl rt_interrupt_leave 296ret_int: 297 clri /* disable interrupt */ 298 POP r3 /* irq priority */ 299 POP sp 300 mov r1, exc_nest_count 301 ld r0, [r1] 302 sub r0, r0, 1 303 st r0, [r1] 304/* if there are multi-bits set in IRQ_ACT, it's still in nest interrupt */ 305 lr r0, [AUX_IRQ_CAUSE] 306 sr r0, [AUX_IRQ_SELECT] 307 lr r3, [AUX_IRQ_PRIORITY] 308 lr r1, [AUX_IRQ_ACT] 309 bclr r2, r1, r3 310 brne r2, 0, ret_int_1 311 312 ld r0, [rt_thread_switch_interrupt_flag] 313 brne r0, 0, ret_int_2 314ret_int_1: /* return from non-task context */ 315 INTERRUPT_EPILOGUE 316 rtie 317/* there is a dispatch request */ 318ret_int_2: 319 /* clear dispatch request */ 320 mov r0, 0 321 st r0, [rt_thread_switch_interrupt_flag] 322 323 /* interrupt return by SW */ 324 lr r10, [AUX_IRQ_ACT] 325 PUSH r10 326 bclr r10, r10, r3 /* clear related bits in IRQ_ACT */ 327 sr r10, [AUX_IRQ_ACT] 328 329 SAVE_CALLEE_REGS /* save callee save registers */ 330 mov r1, ret_int_r /* save return address */ 331 PUSH r1 332 333 ld r0, [rt_interrupt_from_thread] 334 ld r1, [rt_interrupt_to_thread] 335 b dispatcher 336 337ret_int_r: 338 RESTORE_CALLEE_REGS 339 /* recover AUX_IRQ_ACT to restore the interrup status */ 340 POPAX AUX_IRQ_ACT 341 INTERRUPT_EPILOGUE 342 rtie 343 344/****** entry for fast irq exception handling ******/ 345 .global exc_entry_firq 346 .weak exc_entry_firq 347 .align 4 348exc_entry_firq: 349 SAVE_FIQ_EXC_REGS 350 351 lr r0, [AUX_IRQ_CAUSE] 352 mov r1, exc_int_handler_table 353/* r2 = _kernel_exc_tbl + irqno *4 */ 354 ld.as r2, [r1, r0] 355 356/* for the case of software triggered interrupt */ 357 lr r3, [AUX_IRQ_HINT] 358 cmp r3, r0 359 bne.d firq_hint_handled 360 xor r3, r3, r3 361 sr r3, [AUX_IRQ_HINT] 362firq_hint_handled: 363/* jump to interrupt handler */ 364 mov r0, sp 365 jl [r2] 366 367firq_return: 368 RESTORE_FIQ_EXC_REGS 369 rtie 370