📄 vectors.s
字号:
#endif
# Enable MMU & interrupt/FPU environment as configured
lwi r3,CYG_MSR
sync
mtmsr r3
sync
mfspr r3,SPRG1 # save original R3
stw r3,CYGARC_PPCREG_REGS+3*4(sp)
mfspr r4,SPRG2 # save original R4
stw r4,CYGARC_PPCREG_REGS+4*4(sp)
mfspr r5,SPRG3 # save original R5
stw r5,CYGARC_PPCREG_REGS+5*4(sp)
stw r0,CYGARC_PPCREG_REGS+0*4(sp) # save R0
stw r2,CYGARC_PPCREG_REGS+2*4(sp) # save R2
mr r3,sp # recreate original SP
addi r3,r3,CYGARC_PPC_EXCEPTION_DECREMENT
stw r3,CYGARC_PPCREG_REGS+1*4(sp) # and save it in state
# Save registers r6..r12/r31
.set _reg,6
.rept MAX_SAVE_REG+1-6
stw _reg,(CYGARC_PPCREG_REGS+_reg*4)(sp)
.set _reg,_reg+1
.endr
# Save registers used in vsr (r14+r15)
stw r14,CYGARC_PPCREG_REGS+14*4(sp)
stw r15,CYGARC_PPCREG_REGS+15*4(sp)
# get remaining family CPU registers
mfxer r3
mfctr r4
mfsrr0 r5
mfsrr1 r6
# and store them
stw r3,CYGARC_PPCREG_XER(sp)
stw r4,CYGARC_PPCREG_CTR(sp)
stw r5,CYGARC_PPCREG_PC(sp)
stw r6,CYGARC_PPCREG_MSR(sp)
# Save variant registers
hal_variant_save sp
# Save FPU registers
hal_fpu_save sp
# 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
.extern cyg_scheduler_sched_lock
lwi r3,cyg_scheduler_sched_lock
lwz r4,0(r3)
addi r4,r4,1
stw r4,0(r3)
#endif
mr r14,sp # r14 = register dump
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
lwi r3,__interrupt_stack # stack top
lwi r4,__interrupt_stack_base # stack base
sub. r5,sp,r4 # sp - base
blt 1f # if < 0 - not on istack
sub. r5,r3,sp # top - sp
bgt 2f # if > 0 - already on istack
1: mr sp,r3 # switch to istack
2: stwu r14,-4(sp) # save old SP on stack
#endif
subi sp,sp,CYGARC_PPC_STACK_FRAME_SIZE # make a null frame
li r0,0 # R0 = 0
stw r0,0(sp) # backchain = 0
stw r0,8(sp) # return pc = 0
stwu sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
# where C code can save LR
#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
lwi r3,0x0301 # r3 = type = INTR,RAISE
lwz r4,CYGARC_PPCREG_VECTOR(r14) # arg1 = vector address
srwi r4,r4,8 # arg1 = vector number
xor r5,r5,r5 # arg2 = 0
bl cyg_instrument # call instrument function
#endif
hal_intc_decode r15,r14 # get table index
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
|| defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
# If we are supporting Ctrl-C interrupts from GDB, we must squirrel
# away a pointer to the save interrupt state here so that we can
# plant a breakpoint at some later time.
.extern hal_saved_interrupt_state
lwi r3,hal_saved_interrupt_state
stw r14,0(r3)
#endif
#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
#ifdef CYGPKG_HAL_POWERPC_MPC8xx
# The CPM controller allows nested interrupts. However,
# it sits on the back of the SIU controller which has no
# HW support for this. In effect, SW masking of lower
# priority IRQs in the SIU would be required for this to work.
#endif
#endif
lwz r3,CYGARC_PPCREG_VECTOR(r14) # retrieve decoded vector #
lwi r6,hal_interrupt_handlers # get interrupt handler table
lwzx r6,r6,r15 # load routine pointer
lwi r4,hal_interrupt_data # get interrupt data table
lwzx r4,r4,r15 # load data pointer
# R4 = data argument
mr r5,r14 # R5 = saved registers
mtctr r6 # put isr address in ctr
bctrl # branch to ctr reg and link
#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.
lwz sp,CYGARC_PPC_STACK_FRAME_SIZE*2(sp) # sp = *sp
subi sp,sp,CYGARC_PPC_STACK_FRAME_SIZE # make a null frame
li r0,0 # R0 = 0
stw r0,0(sp) # backchain = 0
stw r0,8(sp) # return pc = 0
stwu sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
# where C code can save LR
#endif
# On return r3 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.
# Note that r14 and r15 are defined to be preserved across
# calls by the calling convention, so they still contain
# the register dump and the vector number respectively.
lwi r4,hal_interrupt_objects # get interrupt object table
lwzx r4,r4,r15 # load object pointer
mr r5,r14 # arg3 = saved register dump
.extern interrupt_end
bl interrupt_end # call into C to finish off
restore_state:
# All done, restore CPU state and continue
# retrieve CPU state pointer
addi sp,sp,CYGARC_PPC_STACK_FRAME_SIZE*2
# Restore FPU registers
hal_fpu_load sp
# Restore variant registers
hal_variant_load sp
# get sprs we want to restore
# stuff some of them into the CPU
lwz r3,CYGARC_PPCREG_XER(sp)
lwz r4,CYGARC_PPCREG_LR(sp)
lwz r5,CYGARC_PPCREG_CTR(sp)
mtxer r3
mtlr r4
mtctr r5
# Restore registers used in vsr (r14+r15)
lwz r14,CYGARC_PPCREG_REGS+14*4(r1)
lwz r15,CYGARC_PPCREG_REGS+15*4(r1)
# restore registers r6..r12/r31
.set _reg,6
.rept MAX_SAVE_REG+1-6
lwz _reg,(CYGARC_PPCREG_REGS+_reg*4)(sp)
.set _reg,_reg+1
.endr
hal_cpu_int_disable
# restore R0 and R2
lwz r0,CYGARC_PPCREG_REGS+0*4(sp)
lwz r2,CYGARC_PPCREG_REGS+2*4(sp)
# Here all the registers are loaded except
# sp = HAL_SavedRegisters
# r3 = ccr
# r4 = srr0 = pc
# r5 = srr1 = msr
#
# We have to disable interrupts while srr0 and
# srr1 are loaded, since another interrupt will
# destroy them.
lwz r3,CYGARC_PPCREG_CR(sp)
lwz r4,CYGARC_PPCREG_PC(sp)
lwz r5,CYGARC_PPCREG_MSR(sp)
mtcr r3 # set ccr
mtsrr0 r4 # load old pc
mtsrr1 r5 # load old msr
#ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
# Mark this frame as (almost) dead.
lwi r3,0xDDDDDDD0
stw r3,CYGARC_PPCREG_WALL_HEAD(sp)
lwi r3,0xDDDDDDD1
stw r3,CYGARC_PPCREG_WALL_TAIL(sp)
#endif
lwz r3,CYGARC_PPCREG_REGS+3*4(sp) # load r3 value
lwz r4,CYGARC_PPCREG_REGS+4*4(sp) # load r4 value
lwz r5,CYGARC_PPCREG_REGS+5*4(sp) # load r5 value
lwz sp,CYGARC_PPCREG_REGS+1*4(sp) # restore sp
sync # settle things down
isync
rfi # and return
##-----------------------------------------------------------------------------
## Execute pending DSRs on the interrupt stack with interrupts enabled.
## Note: this can only be called from code running on a thread stack
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
.extern cyg_interrupt_call_pending_DSRs
FUNC_START(hal_interrupt_stack_call_pending_DSRs)
# Change to interrupt stack, save state and set up stack for
# calls to C code.
mr r3,sp
lwi r4,__interrupt_stack
subi r4,r4,24 # make space on stack
mr sp,r4
stw r3,12(sp) # save old sp
mfmsr r3
stw r3,16(sp) # save old MSR
mflr r3
stw r3,20(sp) # save old LR
li r0,0
stw r0,0(sp) # clear back chain
stw r0,8(sp) # zero return pc
hal_cpu_int_enable
# Call into kernel which will execute DSRs
stwu sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp)
bl cyg_interrupt_call_pending_DSRs
addi sp,sp,CYGARC_PPC_STACK_FRAME_SIZE
lwz r3,20(sp) # restore LR
mtlr r3
lwz r5,12(sp) # get SP from saved state
lwz r3,16(sp) # restore interrupt setting
hal_cpu_int_merge r3
mr sp,r5 # restore stack pointer
blr # and return to caller
#endif
#---------------------------------------------------------------------------
## Temporary interrupt stack
.section ".bss"
.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,0,0,0,0
#---------------------------------------------------------------------------
# end of vectors.S
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -