Mercurial > ecos
view packages/hal/powerpc/arch/current/src/vectors.S @ 82:6736c52df507 ecos-sw-2000-04-14
Merge from eCos master repository on 2000-04-14-13:35:46-BST
| author | jlarmour |
|---|---|
| date | Tue, 18 Apr 2000 21:51:55 +0000 |
| parents | 435cced73e2f |
| children | c37d3a9e1b28 |
line wrap: on
line source
##========================================================================== ## ## vectors.S ## ## PowerPC exception vectors ## ##========================================================================== #####COPYRIGHTBEGIN#### # # ------------------------------------------- # The contents of this file are subject to the Red Hat eCos Public License # Version 1.1 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.redhat.com/ # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the # License for the specific language governing rights and limitations under # the License. # # The Original Code is eCos - Embedded Configurable Operating System, # released September 30, 1998. # # The Initial Developer of the Original Code is Red Hat. # Portions created by Red Hat are # Copyright (C) 1998, 1999, 2000 Red Hat, Inc. # All Rights Reserved. # ------------------------------------------- # #####COPYRIGHTEND#### ##========================================================================== #######DESCRIPTIONBEGIN#### ## ## Author(s): nickg, jskov ## Contributors: nickg, jskov ## Date: 1999-02-20 ## Purpose: PowerPC exception vectors ## Description: This file defines the code placed into the exception ## vectors. It also contains the first level default VSRs ## that save and restore state for both exceptions and ## interrupts. ## ######DESCRIPTIONEND#### ## ##========================================================================== #=========================================================================== # # The PowerPC exception handling has changed as of version 1.3.1. # The primary motivation for rewriting the code was to bring it more # in line with the other HALs, in particular to allow a RAM application # to cleanly take over only a subset of vectors from a running ROM # monitor. # # GDB stubs (and CygMon, should it be ported to PPC) copies # exception vector entry handler code to address 0. These vector entry # handlers (defined by the exception_vector macro below) compute # a vector index into the hal_vsr_table, fetch the pointer, and # jump to the HAL vector service routine (VSR). # # The hal_vsr_table is located immediately after the vector # handlers (at address 0x3000), allowing RAM applications to # change VSRs as necessary, while still keeping desired ROM # monitor functionality available for debugging. # # ROM applications can still be configured to leave the vector entry # handlers at 0xff000000, but there is at the moment no # provision for reclaiming the reserved vector space in RAM to # application usage. # # RAM applications can also be configured to provide exception # handlers which are copied to address 0 on startup, thus taking # full control of the target. # # # Default configuration is for RAM applications to rely on an # existing ROM monitor to provide debugging functionality, and # for ROM applications to copy vectors to address 0. # # # Unfortunately the new exception scheme is not compatible with the # old scheme. Stubs and applications must be compiled using the same # scheme (i.e., old binaries will not run with new stubs, and new # binaries will not run with old stubs). # #=========================================================================== #include <pkgconf/hal.h> #ifdef CYGPKG_KERNEL #include <pkgconf/kernel.h> // CYGPKG_KERNEL_INSTRUMENT #endif #define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS #include <cyg/hal/ppc_regs.h> #=========================================================================== .file "vectors.S" .extern hal_interrupt_data .extern hal_interrupt_handlers .extern hal_interrupt_objects .extern hal_vsr_table .extern cyg_hal_invoke_constructors .extern cyg_instrument .extern cyg_start .extern hal_IRQ_init .extern hal_MMU_init .extern hal_enable_caches .extern hal_hardware_init .extern initialize_stub .extern __bss_start .extern __bss_end .extern __sbss_start .extern __sbss_end #=========================================================================== # MSR initialization value # zero all bits except: # FP = floating point available # ME = machine check enabled # IP = vectors at 0xFFFxxxxx (ROM startup only) # IR = instruction address translation # DR = data address translation # RI = recoverable interrupt #define CYG_MSR_COMMON (MSR_FP | MSR_ME | MSR_RI) #if (CYGHWR_HAL_POWERPC_VECTOR_BASE == 0xfff00000) # define IP_BIT MSR_IP #else # define IP_BIT 0 #endif #ifdef CYGHWR_HAL_POWERPC_ENABLE_MMU # define IR_DR_BITS (MSR_IR | MSR_DR) #else # define IR_DR_BITS 0 #endif #define CYG_MSR (CYG_MSR_COMMON | IP_BIT | IR_DR_BITS) # Include variant macros after MSR definition. #include <cyg/hal/arch.inc> #include <cyg/hal/ppc_offsets.inc> #=========================================================================== # If the following option is enabled, we only save registers up to R12. # The PowerPC ABI defines registers 13..31 as callee saved and thus we do # not need to save them when calling C functions. #ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT # define MAX_SAVE_REG 12 #else # define MAX_SAVE_REG 31 #endif #if defined(CYGHWR_HAL_POWERPC_NEED_VECTORS) #=========================================================================== # Start by defining the exceptions vectors that must be placed at # locations 0xFFF00000 or 0x00000000. The following code will normally # be located at 0xFFF00000 in the ROM. It may optionally be copied out # to 0x00000000 if we want to use the RAM vectors. For this reason this code # MUST BE POSITION INDEPENDENT. .section ".vectors","ax" #--------------------------------------------------------------------------- # Macros for generating an exception vector service routine # Reset vector macro .macro reset_vector name .p2align 8 .globl __exception_\name __exception_\name: lwi r3,_start mtlr r3 blr .endm # Generic vector macro .macro exception_vector name .p2align 8 .globl __exception_\name __exception_\name: mtspr SPRG1,r3 # stash some work registers away mtspr SPRG2,r4 mtspr SPRG3,r5 mfcr r4 # stash CR li r5,__exception_\name@L # load low half of vector addr srwi r5,r5,6 # shift right by 6 lwi r3,hal_vsr_table # table base lwzx r3,r3,r5 # address of vsr mflr r5 # save link register mtlr r3 # put vsr address into it li r3,__exception_\name@L # reload low half of vector addr blr # go to common code .endm #--------------------------------------------------------------------------- # Define the exception vectors. rom_vectors: # These are the architecture defined vectors that # are always present. exception_vector reserved_00000 reset_vector reset exception_vector machine_check exception_vector data_storage exception_vector instruction_storage exception_vector external exception_vector alignment exception_vector program exception_vector floatingpoint_unavailable exception_vector decrementer exception_vector reserved_00a00 exception_vector reserved_00b00 exception_vector system_call exception_vector trace exception_vector floatingpoint_assist exception_vector reserved_00f00 # Variants may define extra vectors. hal_extra_vectors rom_vectors_end: #else // CYGHWR_HAL_POWERPC_NEED_VECTORS # When vectors are not included this is the primary entry point. .globl __exception_reset __exception_reset: lwi r3,_start mtlr r3 blr #endif // CYGHWR_HAL_POWERPC_NEED_VECTORS #=========================================================================== # Real startup code. We jump here from the various reset vectors to set up # the world. .text .globl _start _start: # Initialize CPU to a post-reset state, ensuring the ground doesn''t # shift under us while we try to set things up. hal_cpu_init #if !defined(CYG_HAL_STARTUP_ROM) && defined(CYGSEM_HAL_POWERPC_COPY_VECTORS) lwi r3,rom_vectors-4 lwi r4,(CYGHWR_HAL_POWERPC_VECTOR_BASE - 4) lwi r5,rom_vectors_end-4 0: lwzu r0,4(r3) stwu r0,4(r4) cmplw r3,r5 bne 0b #endif # Set up global offset table lwi r2,_GLOBAL_OFFSET_TABLE_ # set up time base register to zero xor r3,r3,r3 mtspr TBL_W,r3 xor r4,r4,r4 mtspr TBU_W,r4 # Call platform specific hardware initialization # This may include memory controller initialization. It is not # safe to access RAM until after this point. bl hal_hardware_init # this is platform dependent # 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 1: lwz r0,0(r3) # get word from ROM stw r0,0(r4) # store in RAM addi r3,r3,4 # increment by 1 word addi r4,r4,4 # increment by 1 word cmplw r4,r5 # compare blt 1b # loop if not yet done 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 1: stw r0,0(r3) # store zero addi r3,r3,4 # increment by 1 word cmplw r3,r4 # compare blt 1b # loop if not yet done 2: # clear SBSS lwi r3,__sbss_start # r3 = start lwi r4,__sbss_end # r4 = end cmplw r3,r4 # skip if no sbss beq 2f 1: stw r0,0(r3) # store zero addi r3,r3,4 # increment by 1 word cmplw r3,r4 # compare blt 1b # loop if not yet done 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 # MMU and cache are controlled by the same option since caching # on the PPC 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 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 # call c++ constructors bl cyg_hal_invoke_constructors # set up platform specific interrupt environment bl hal_IRQ_init #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS bl initialize_stub #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 # 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. 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 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) #endif # Enable MMU. 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 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT .extern cyg_hal_gdb_isr lwz r3,CYGARC_PPCREG_PC(r14) # for serial receive irq. bl cyg_hal_gdb_isr # (arg1 is PC) cmpwi r3,0x0000 # Call ISR proper? beq 2f # (r3 is 0 when skipping # to avoid DSR call) 1: #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 mtctr r6 # put isr address in ctr bctrl # branch to ctr reg and link #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT # If interrupt was caused by GDB, the ISR call above # is skipped by jumping here. 2: #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. 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 #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 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 #endif 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
