📄 vectors.s
字号:
# Common interrupt handling code. .globl _cyg_hal_default_interrupt_vsr_cyg_hal_default_interrupt_vsr: # We come here with all register containing their # pre-exception values except: # r0_b-r7_b = saved r0-r7 # r7 = vector # # spc = saved pc # ssr = saved sr # Save away some registers mov r15,r1 ! entry sp#ifdef __DEBUG mov.l $int_state_marker,r0 mov.l r0,@-r15 mov #CYGARC_REG_INTEVT,r0 mov.l @r0,r0 mov.l r0,@-r15#endif #ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT add #-12,r15 ! Space for cause, gbr, and vbr#else add #-4,r15 ! Space for cause stc gbr,r0 ! GBR mov.l r0,@-r15 stc vbr,r0 ! VBR mov.l r0,@-r15#endif stc spc,r0 mov.l r0,@-r15 ! PC stc ssr,r0 mov.l r0,@-r15 ! SR sts.l pr,@-r15 ! PR sts.l mach,@-r15 ! mach sts.l macl,@-r15 ! macl mov.l r1,@-r15 ! entry sp mov.l r14,@-r15 ! r14-r0 mov.l r13,@-r15 mov.l r12,@-r15 mov.l r11,@-r15 mov.l r10,@-r15 mov.l r9,@-r15 mov.l r8,@-r15 stc.l r7_bank,@-r15 stc.l r6_bank,@-r15 stc.l r5_bank,@-r15 stc.l r4_bank,@-r15 stc.l r3_bank,@-r15 stc.l r2_bank,@-r15 stc.l r1_bank,@-r15 stc.l r0_bank,@-r15 # After setting the SR it will be possible to use breakpoints. mov.l $nCYG_SR2,r1 ldc r1,sr # ------------------------------------------------------------ # Register bank has changed now. #ifdef __DEBUG # It is safe to use breakpoints below this point. .globl _cyg_hal_default_interrupt_vsr_bp_safe_cyg_hal_default_interrupt_vsr_bp_safe:#endif # The entire CPU state is now stashed on the stack, # call into C to do something with it. # The entire CPU state is now stashed on the stack, # increment the scheduler lock and call the ISR # for this vector.#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT mov.l $cyg_scheduler_sched_lock,r0 mov.l @r0,r1 add #1,r1 mov.l r1,@r0#endif mov r15,r8 ! R8 = register dump#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK mov.l $__interrupt_stack_base,r0 mov.l $__interrupt_stack,r1 cmp/hi r15,r0 ! if r0 > r15 or bt 2f cmp/hi r1,r15 ! if r15 > r1 bf 1f2: mov r1,r15 ! change to supervisor stack1: mov.l r8,@-r15 ! save old stack pointer#endif#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR) mov.l $n0301,r4 ! arg0 = type = INTR,RAISE mov r7,r5 ! arg1 = vector number mov.l $_cyg_instrument,r0 mov #0,r6 ! arg2 = 0 jsr @r0 ! call instrument function nop bra 1f nop .align 2$n0301: .long 0x0301$_cyg_instrument: .extern _cyg_instrument .long _cyg_instrument1:#endif # Decode the interrupt vector mov #CYGARC_REG_INTEVT,r0 mov.l @r0,r4 mov #-5,r0 ! divide cause by 0x20 shld r0,r4 add #-14,r4 ! adjust so NMI becomes 0 mov #CYGARC_SHREG_EVENT,r0 mov.l r4,@(r0,r8) ! store decoded vector number back ! to saved state. // Find ISR index.#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN#define CYG_ISR_TABLE_SIZE 1 mov #0,r9 ! only one ISR in the table#else // CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN#define CYG_ISR_TABLE_SIZE CYGNUM_HAL_ISR_COUNT mov r4,r9 shll2 r9 ! get from vector number to ISR index#endif // CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT mov #CYGNUM_HAL_INTERRUPT_SCI_RXI,r1 cmp/eq r1,r4 bf 2f mov r4,r10 ! save across call. mov #CYGARC_SHREG_PC,r4 add r8,r4 mov.l @r4,r4 mov.l $_cyg_hal_gdb_isr,r1 jsr @r1 ! returns 1 if the proper isr must be nop ! called (i.e., if it was not a GDB mov r10,r4 ! interrupt) cmp/eq #0,r0 bt skip_isr_proper bra 2f nop .align 2 .extern _cyg_hal_gdb_isr$_cyg_hal_gdb_isr: .long _cyg_hal_gdb_isr2:#endif#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING#ifdef CYGPKG_HAL_SH_EDK7708 # The interrupt mask bits in the SR are not updated by the # CPU. Proper nested operation requires the level to be # found and put in the SR. # R4 contains the vector number: # CYGNUM_HAL_INTERRUPT_NMI: # Ix = 15 # CYGNUM_HAL_INTERRUPT_LVL0-CYGNUM_HAL_INTERRUPT_LVL14: # Ix = 15-(CYGNUM_HAL_INTERRUPT_LVL0-R4) # IRA sources: # Get level from IRA # IRB sources: # Get level from IRB # However, doing mutiple checks and branches here is not smart. # Instead rely on alternative implementation where all programmed # priorities are also kept in a table. mov.l $cyg_hal_ILVL_table,r0 mov.b @(r0,r4),r0 shll2 r0 shll2 r0 mov.l $unmasked_SR,r1 or r0,r1 ldc r1,sr#endif#endif mov r9,r0 mov.l $_hal_interrupt_handlers,r1 ! get interrupt handler mov.l @(r0,r1),r1 mov.l $_hal_interrupt_data,r5 ! get interrupt data mov.l @(r0,r5),r5 jsr @r1 ! r4=vector, r5=data nop#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT # If interrupt was caused by GDB, the ISR call above # is skipped by jumping here.skip_isr_proper:#endif#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK # If we are returning from the last nested interrupt, move back # to the thread stack. interrupt_end() must be called on the # thread stack since it potentially causes a context switch. # Since we have arranged for the top of stack location to # contain the sp we need to go back to here, just pop it off # and put it in SP. mov.l @r15,r15#endif#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT # We only need to call _interrupt_end() when there is a kernel # present to do any tidying up. # on return r0 bit 1 will indicate whether a DSR is # to be posted. Pass this together with a pointer to # the interrupt object we have just used to the # interrupt tidy up routine. mov r0,r4 ! arg1 = isr_ret # Note that r8 and r9 are defined to be preserved across # calls by the calling convention, so they still contain # the register dump and the vector table index respectively. mov.l $_hal_interrupt_objects,r0 ! get interrupt object table mov.l @(r0,r9),r5 ! arg2 = interrupt object mov.l $_interrupt_end,r0 mov r8,r6 ! arg3 = saved register dump jsr @r0 ! call into C to finish off nop#endifrestore_state: # All done, restore CPU state and continue#ifdef __DEBUG mov.l $_safe_addr,r0 mov.l @r0,r1 add #1,r1 mov.l r1,@r0 add #4,r0 mov r15,r1 mov #CYGARC_SH_EXCEPTION_SIZE/4,r21: mov.l @r1+,r3 mov.l r3,@r0 add #4,r0 dt r2 bf 1b bra 2f nop .align 2$_safe_addr: .long 0x080d0000-42: #endif # Disable interrupts and switch register bank during the restore # operation mov.l $nCYG_SR_BANK1,r1 ldc r1,sr # ------------------------------------------------------------ # Register bank has changed now. # # Single step debugging becomes impossible after this point! # mov r15,r0 ldc.l @r0+,r0_bank ldc.l @r0+,r1_bank ldc.l @r0+,r2_bank ldc.l @r0+,r3_bank ldc.l @r0+,r4_bank ldc.l @r0+,r5_bank ldc.l @r0+,r6_bank ldc.l @r0+,r7_bank mov.l @r0+,r8 mov.l @r0+,r9 mov.l @r0+,r10 mov.l @r0+,r11 mov.l @r0+,r12 mov.l @r0+,r13 mov.l @r0+,r14 mov.l @r0+,r15 ! return SP lds.l @r0+,macl ! macl lds.l @r0+,mach ! mach lds.l @r0+,pr ! PR mov.l @r0+,r2 ldc r2,ssr ! return SR mov.l @r0+,r2 ldc r2,spc ! return PC#ifndef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT mov.l @r0+,r2 ldc r2,vbr ! return VBR mov.l @r0+,r2 ldc r2,gbr ! return GBR#endif rte nop#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK##-----------------------------------------------------------------------------## Execute pending DSRs on the interrupt stack with interrupts enabled.## Note: this can only be called from code running on a thread stack .globl _hal_interrupt_stack_call_pending_DSRs_hal_interrupt_stack_call_pending_DSRs: # Change to interrupt stack mov r15,r2 mov.l $__interrupt_stack,r15 mov.l r2,@-r15 ! save old stack pointer sts.l pr,@-r15 ! save pr on stack stc sr,r3 mov.l r3,@-r15 ! save sr on stack # enable interrupts hal_cpu_int_enable r0,r1 # Call into kernel which will execute DSRs mov.l $_cyg_interrupt_call_pending_DSRs,r0 jsr @r0 nop # Get old sr, pr, and stack values mov.l @r15+,r3 ! get old sr lds.l @r15+,pr ! get old pr mov.l @r15+,r15 ! get old stack pointer # Restore SR interrupt state hal_cpu_int_merge r3,r0,r1 rts nop#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK#endif // CYGFUN_HAL_COMMON_KERNEL_SUPPORT .align 2 #ifdef __DEBUG$int_state_marker: .long 0x77777771#endif#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK $__interrupt_stack: .long __interrupt_stack$__interrupt_stack_base: .long __interrupt_stack_base#endif$nCYG_SR2: .long CYG_SR$nCYG_SR_BANK1: .long CYG_SR_BANK1$_hal_interrupt_handlers: .long _hal_interrupt_handlers$_hal_interrupt_data: .long _hal_interrupt_data$_hal_interrupt_objects: .long _hal_interrupt_objects#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING$cyg_hal_ILVL_table: .long _cyg_hal_ILVL_table$unmasked_SR: .long (CYG_SR & ~CYGARC_REG_SR_IMASK)#endif // CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT .extern _cyg_scheduler_sched_lock .extern _interrupt_end .extern _cyg_interrupt_call_pending_DSRs$_cyg_interrupt_call_pending_DSRs: .long _cyg_interrupt_call_pending_DSRs$cyg_scheduler_sched_lock: .long cyg_scheduler_sched_lock$_interrupt_end: .long _interrupt_end#endif#---------------------------------------------------------------------------# Interrupt vector tables.# These tables contain the isr, data and object pointers used to deliver# interrupts to user code. .data .extern _hal_default_isr .globl _hal_interrupt_handlers_hal_interrupt_handlers: .rept CYG_ISR_TABLE_SIZE .long _hal_default_isr .endr .globl _hal_interrupt_data_hal_interrupt_data: .rept CYG_ISR_TABLE_SIZE .long 0 .endr .globl _hal_interrupt_objects_hal_interrupt_objects: .rept CYG_ISR_TABLE_SIZE .long 0 .endr#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING .globl _cyg_hal_ILVL_table_cyg_hal_ILVL_table: # The first entries in the table have static priorities. .byte 0xf // NMI .byte 0xf // Reserved .byte 0xf // LVL0 .byte 0xe // LVL1 .byte 0xd // LVL2 .byte 0xc // LVL3 .byte 0xb // LVL4 .byte 0xa // LVL5 .byte 0x9 // LVL6 .byte 0x8 // LVL7 .byte 0x7 // LVL8 .byte 0x6 // LVL9 .byte 0x5 // LVL10 .byte 0x4 // LVL11 .byte 0x3 // LVL12 .byte 0x2 // LVL13 .byte 0x1 // LVL14 .byte 0xf // Reserved # The rest of the table consists of programmable levels, maintained # by the HAL_INTERRUPT_SET_LEVEL macro.#ifdef CYGPKG_HAL_SH_EDK7708 .rept (CYGNUM_HAL_ISR_MAX-CYGNUM_HAL_INTERRUPT_RESERVED_3E0) .byte 0xf .endr#endif // CYGPKG_HAL_SH_EDK7708#endif // CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING#---------------------------------------------------------------------------## Temporary interrupt stack .section ".bss"#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK .balign 16 .global _cyg_interrupt_stack_base_cyg_interrupt_stack_base:__interrupt_stack_base: .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE .byte 0 .endr .balign 16 .global _cyg_interrupt_stack_cyg_interrupt_stack:__interrupt_stack: .long 0,0,0,0#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK#ifdef CYGSEM_HAL_ROM_MONITOR // Enough space for stub to handle downloads. If using thread capabilities // it will be using the RAM application's stack.# define STARTUP_STACK_SIZE 1024#else# ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK // Enough space to run constructors. // FIXME: 512 is enough for all tests. doc/examples/twothreads // calls printf on this stack though, and so requires more space.# define STARTUP_STACK_SIZE 1024# else# define STARTUP_STACK_SIZE CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE# endif#endif .balign 16__startup_stack_base: .rept STARTUP_STACK_SIZE .byte 0 .endr .balign 16__startup_stack: .long 0,0,0,0#---------------------------------------------------------------------------# end of vectors.S
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -