📄 vectors.s
字号:
# set up stack
lwi sp,__interrupt_stack
mtspr SPRG0,sp # save in sprg0 for later use
# Set up exception handlers and VSR table, taking care not to
# step on any ROM monitor''s toes.
hal_mon_init
#if defined(CYG_HAL_STARTUP_ROM)
# Copy data from ROM to ram
lwi r3,__rom_data_start # r3 = rom start
lwi r4,__ram_data_start # r4 = ram start
lwi r5,__ram_data_end # r5 = ram end
cmplw r4,r5 # skip if no data
beq 2f
sub r5,r5,r4 # compute number of words to copy
srwi r5,r5,2
mtctr r5
subi r3,r3,4
subi r4,r4,4
1: lwzu r0,4(r3) # get word from ROM
stwu r0,4(r4) # store in RAM
bdnz 1b
2:
#endif
# clear BSS
lwi r3,__bss_start # r3 = start
lwi r4,__bss_end # r4 = end
li r0,0 # r0 = 0
cmplw r3,r4 # skip if no bss
beq 2f
sub r4,r4,r3 # compute number of words to clear
srwi r4,r4,2
mtctr r4
subi r3,r3,4
1: stwu r0,4(r3) # store zero & increment pointer
bdnz 1b
2:
# clear SBSS
lwi r3,__sbss_start # r3 = start
lwi r4,__sbss_end # r4 = end
cmplw r3,r4 # skip if no sbss
beq 2f
sub r4,r4,r3 # compute number of words to clear
srwi r4,r4,2
mtctr r4
subi r3,r3,4
1: stwu r0,4(r3) # store zero & increment pointer
bdnz 1b
2:
# It is now safe to call C functions which may rely on initialized
# data.
# Set up stack for calls to C code.
subi sp,sp,12 # make space on stack
li r0,0
stw r0,0(sp) # clear back chain
stw r0,8(sp) # zero return pc
stwu sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
# Variant HALs may need to do something special before we continue
bl hal_variant_init
# Platform initialization
bl hal_platform_init
# MMU and cache are controlled by the same option since caching
# on the PPC [typically] does not make sense without the MMU to mark
# regions which should not be cached.
#ifdef CYGHWR_HAL_POWERPC_ENABLE_MMU
# Initialize MMU.
bl hal_MMU_init
# Enable MMU (if desired) so we can safely enable caches.
lwi r3,CYG_MSR # interrupts enabled later
sync
mtmsr r3
sync
# Enable caches
bl hal_enable_caches
#endif // CYGHWR_HAL_POWERPC_ENABLE_MMU
# set up platform specific interrupt environment
bl hal_IRQ_init
# call c++ constructors
bl cyg_hal_invoke_constructors
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
bl initialize_stub
#endif
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
|| defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
.extern hal_ctrlc_isr_init
bl hal_ctrlc_isr_init
#endif
bl cyg_start # call cyg_start
9:
b 9b # if we return, loop
#---------------------------------------------------------------------------
# This code handles the common part of all exception handlers.
# It saves the machine state onto the stack and then calls
# a "C" routine to do the rest of the work. This work may result
# in thread switches, and changes to the saved state. When we return
# here the saved state is restored and execution is continued.
.text
.globl cyg_hal_default_exception_vsr
cyg_hal_default_exception_vsr:
# We come here with all register containing their
# pre-exception values except:
# R3 = ls 16 bits of vector address
# R4 = saved CR
# R5 = saved LR
# LR = VSR address
# SPRG1 = old R3
# SPRG2 = old R4
# SPRG3 = old R5
# SRR0 = old PC
# SRR1 = old MSR and the exception cause (the POW state is lost!)
subi sp,sp,CYGARC_PPC_EXCEPTION_DECREMENT
# leave space for registers and
# a safety margin
#ifdef CYGPKG_HAL_POWERPC_PPC40x
// The caches on this processor are always enabled when the MMU is on
// (and disabled when off). Thus we need to be careful about cache
// polution and staleness when changing the MMU state.
// At this point, the MMU is off due to the exception. We need to
// flush the part of the cache which may be touched before the MMU
// is reenabled so that memory will be consistent when that happens.
// Of course, this is complicated by the fact that there are no "free"
// registers at this point in the code.
dcbf 0,sp // Flushes first line
stw r3,0(sp) // This is now safe
li r3,CYGARC_PPCREG_VECTOR // Flush lines which will be changed
dcbf r3,sp
li r3,CYGARC_PPCREG_CR
dcbf r3,sp
li r3,CYGARC_PPCREG_LR
dcbf r3,sp
lwz r3,0(sp) // Restore register
#endif
# First, save away some registers
stw r3,CYGARC_PPCREG_VECTOR(sp) # stash vector
stw r4,CYGARC_PPCREG_CR(sp) # stash CR
stw r5,CYGARC_PPCREG_LR(sp) # stash LR
#ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
# Mark this fram as an Exception frame
lwi r3,0xDDDDDDE0
stw r3,CYGARC_PPCREG_WALL_HEAD(sp)
lwi r3,0xDDDDDDE1
stw r3,CYGARC_PPCREG_WALL_TAIL(sp)
#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,
# call into C to do something with it.
mr r3,sp # R3 = register dump
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
lwi r5,restore_state # get return link
mtlr r5 # to link register
.extern cyg_hal_exception_handler
b cyg_hal_exception_handler # call C code, r3 = registers
# When the call returns it will go to restore_state below.
##--------------------------------------------------------------------------
## The following macros are defined depending on whether the Interrupt
## system is using isr tables or chaining, and depending on the interrupt
## controller in the system.
#ifndef CYGPKG_HAL_POWERPC_INTC_DEFINED
## This is the simple version. No interrupt controller, CYGARC_PPCREG_VECTOR
## is updated with the decoded interrupt vector. Isr tables/chaining
## use same interrupt decoder.
## Bit 21 biffers between decrementer (0) and external (1).
# decode the interrupt
.macro hal_intc_decode dreg,state
lwz \dreg,CYGARC_PPCREG_VECTOR(\state) # retrieve vector number,
rlwinm \dreg,\dreg,22,31,31 # isolate bit 21 and update
stw \dreg,CYGARC_PPCREG_VECTOR(\state) # vector in state frame.
slwi \dreg,\dreg,2 # convert to word offset.
.endm
#endif // CYGPKG_HAL_POWERPC_INTC_DEFINED
#---------------------------------------------------------------------------
# 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:
# R3 = ls 16 bits of vector address
# R4 = saved CR
# R5 = saved LR
# LR = VSR address
# SPRG1 = old R3
# SPRG2 = old R4
# SPRG3 = old R5
# SRR0 = old PC
# SRR1 = old MSR
subi sp,sp,CYGARC_PPC_EXCEPTION_DECREMENT
# leave space for registers and
# a safety margin
#ifdef CYGPKG_HAL_POWERPC_PPC40x
// The caches on this processor are always enabled when the MMU is on
// (and disabled when off). Thus we need to be careful about cache
// polution and staleness when changing the MMU state.
// At this point, the MMU is off due to the exception. We need to
// flush the part of the cache which may be touched before the MMU
// is reenabled so that memory will be consistent when that happens.
// Of course, this is complicated by the fact that there are no "free"
// registers at this point in the code.
dcbf 0,sp // Flushes first line
stw r3,0(sp) // This is now safe
li r3,CYGARC_PPCREG_VECTOR // Flush lines which will be changed
dcbf r3,sp
li r3,CYGARC_PPCREG_CR
dcbf r3,sp
li r3,CYGARC_PPCREG_LR
dcbf r3,sp
lwz r3,0(sp) // Restore register
#endif
stw r3,CYGARC_PPCREG_VECTOR(sp) # stash vector
stw r4,CYGARC_PPCREG_CR(sp) # stash CR
stw r5,CYGARC_PPCREG_LR(sp) # stash LR
#ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
# Mark this fram as an 1nterrupt frame
lwi r3,0xDDDDDD10
stw r3,CYGARC_PPCREG_WALL_HEAD(sp)
lwi r3,0xDDDDDD11
stw r3,CYGARC_PPCREG_WALL_TAIL(sp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -