Mercurial > nand-ecoscentric
view packages/hal/powerpc/arch/current/src/vectors.S @ 38:e7ba79f6d3a8 ecos-sw-1999-09-23
Merge from eCos master repository on 1999-09-23-20:10:25-BST
| author | jlarmour |
|---|---|
| date | Thu, 23 Sep 1999 19:52:27 +0000 |
| parents | e97d78785e2d |
| children | c38311975d4f |
line wrap: on
line source
##========================================================================== ## ## vectors.S ## ## PowerPC exception vectors ## ##========================================================================== #####COPYRIGHTBEGIN#### # # ------------------------------------------- # The contents of this file are subject to the Cygnus eCos Public License # Version 1.0 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://sourceware.cygnus.com/ecos # # 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 Cygnus Operating System, released # September 30, 1998. # # The Initial Developer of the Original Code is Cygnus. Portions created # by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. 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#### ## ##========================================================================== #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" #include "cyg/hal/ppc.inc" #=========================================================================== .file "vectors.S" .extern hal_interrupt_handlers .extern hal_interrupt_data .extern hal_interrupt_objects .extern cyg_instrument .extern hal_hardware_init #=========================================================================== # 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_IR | MSR_DR | MSR_RI) #if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_STUBS) # ifdef CYG_HAL_POWERPC_COPY_VECTORS # define CYG_MSR CYG_MSR_COMMON # else # define CYG_MSR (CYG_MSR_COMMON | MSR_IP) # endif #endif #ifdef CYG_HAL_STARTUP_RAM #define CYG_MSR CYG_MSR_COMMON #endif #ifdef CYG_HAL_POWERPC_SIM # When building for SIM, don~t enable MMU -- it~s not needed since caches # are disabled, and there is a runtime simulation overhead. #undef CYG_MSR #define CYG_MSR (CYG_MSR_COMMON & ~(MSR_IR | MSR_DR)) #endif #define CYG_MSR_NO_INTS (CYG_MSR & ~MSR_ME) #=========================================================================== # 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 #=========================================================================== # Start by defining the exceptions vectors that must be placed at # locations 0xFFF00000 and 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. In RAM loaded configurations, this code may # be placed at 0x00000000 during loading. .section ".vectors","ax" #--------------------------------------------------------------------------- # Unused first vector. Jump to special handler, trapping null-pointer calls. rom_vectors: .extern hal_null_call b hal_null_call #--------------------------------------------------------------------------- # Reset vector. .p2align 8 .globl reset_vector reset_vector: lwi r3,_start mtlr r3 blr #--------------------------------------------------------------------------- # Macro for generating an exception vector service routine .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 address 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 address blr # go to common code .endm #--------------------------------------------------------------------------- # Define the exception vectors. # These are the architecture defined vectors that # are always present. exception_vector machine_check exception_vector data_storage exception_vector instruction_storage exception_vector external exception_vector alignment #if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_STUBS) \ || defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) exception_vector program #else # Provide a crude hook to the GDB exception handler in ROM. # This allows the testing infrastructure to rely on breakpoints # to terminate tests, even when the tests are compiled without # the GDB stub. # It is _not_ a generic solution to the problem; in particular it # is not possible to continue after a breakpoint is hit. # # Note that for platforms where StubROM vectors are copied into RAM # at 0x00000000, simply skipping the copy of vector 0x700 is a # better solution. See CYGPRI_STUBROM_HAS_RAM_VECTORS below. .p2align 8 .globl __exception_program __exception_program: bl _init_CPU # disable caches. lwi r3,0xfff00700 # address of trap handler mtlr r3 # in ROM. blr # jump to it. #endif 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 # There are some additional vectors defined # on various implementations. #ifdef CYG_HAL_POWERPC_MPC8xx # MPC8xx vectors exception_vector software_emu exception_vector instruction_tlb_miss exception_vector data_tlb_miss exception_vector instruction_tlb_error exception_vector data_tlb_error exception_vector reserved_01500 exception_vector reserved_01600 exception_vector reserved_01700 exception_vector reserved_01800 exception_vector reserved_01900 exception_vector reserved_01A00 exception_vector reserved_01B00 exception_vector data_breakpoint exception_vector instruction_breakpoint exception_vector peripheral_breakpoint exception_vector NMI_port #endif rom_vectors_end: #=========================================================================== # Real startup code. We jump here from the various reset vectors to set up # the world. .text .globl _start _start: # Initialize CPU bl _init_CPU #ifdef CYG_HAL_POWERPC_MPC8xx # Disable special MPC8xx "development support" which # suppresses trace exceptions. The CPU seems to hang, not # executing from offset 0x1e00(?) as expected. lwi r3,0x00000007 mtspr ICTRL,r3 li r3,0 mtspr DER, r3 #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 #if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_STUBS) # 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 #ifdef CYG_HAL_POWERPC_COPY_VECTORS // only for StubRom-supported startup #ifdef CYG_HAL_POWERPC_MBX # define CYGPRI_STUBROM_HAS_RAM_VECTORS #endif #ifdef CYGPRI_STUBROM_HAS_RAM_VECTORS # ifdef CYG_HAL_STARTUP_RAM # ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS # define CYGPRI_SKIP_BREAKPOINT_VECTOR # endif // no stubs # endif // RAM startup #endif // Stubrom vectors are in RAM # Copy RAM exception vectors from ROM (or load place) to RAM lwi r3,rom_vectors # r3 = rom start lwi r4,0 # r4 = ram start #ifdef CYGPRI_SKIP_BREAKPOINT_VECTOR lwi r5,__exception_program # r5 = end of first leg of copy #else lwi r5,rom_vectors_end # r5 = rom end #endif cmplw r3,r5 # skip if no vectors 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 r3,r5 # compare blt 1b # loop if not yet done 2: #ifdef CYGPRI_SKIP_BREAKPOINT_VECTOR cmplwi r4,__exception_program@L bne 3f # is it the breakpoint vector? addi r4,r4,0x100 # if so, leave it well alone addi r3,r3,0x100 lwi r5,rom_vectors_end # r5 = rom end b 1b # and do the rest of the copy 3: #endif // Skip copying the breakpoint vector #endif # clear BSS .extern __bss_start .extern __bss_end 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 .extern __sbss_start .extern __sbss_end 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,-ppc_stack_frame_size(sp) # create new stack frame # Initialize MMU. .extern hal_MMU_init bl hal_MMU_init # Enable MMU so we can safely enable caches. lwi r3,CYG_MSR_NO_INTS # interrupts enabled later sync mtmsr r3 sync # Enable caches .extern hal_enable_caches bl hal_enable_caches # call c++ constructors .extern cyg_hal_invoke_constructors bl cyg_hal_invoke_constructors # set up platform specific interrupt environment .extern hal_IRQ_init bl hal_IRQ_init #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS .extern initialize_stub bl initialize_stub #endif .extern cyg_start 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 .extern __default_exception_vsr __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 r1,r1,ppc_exception_decrement # leave space for registers and # a safety margin # First, save away some registers stw r3,ppcreg_vector(r1) # stash vector stw r4,ppcreg_cr(r1) # stash CR stw r5,ppcreg_lr(r1) # stash LR # Enable MMU. lwi r3,CYG_MSR_NO_INTS sync mtmsr r3 sync mfspr r3,SPRG1 # save original R3 stw r3,ppcreg_regs+3*4(r1) mfspr r4,SPRG2 # save original R4 stw r4,ppcreg_regs+4*4(r1) mfspr r5,SPRG3 # save original R5 stw r5,ppcreg_regs+5*4(r1) stw r0,ppcreg_regs(r1) # save R0 stw r2,ppcreg_regs+2*4(r1) # save R2 mr r3,r1 # recreate original R1 addi r3,r3,ppc_exception_decrement stw r3,ppcreg_regs+1*4(r1) # and save it in state # Save registers r6..r12/r31 .set _reg,6 .rept MAX_SAVE_REG+1-6 stw _reg,(ppcreg_regs+_reg*4)(r1) .set _reg,_reg+1 .endr # Save registers used in vsr (r14+r15) stw r14,(ppcreg_regs+14*4)(r1) stw r15,(ppcreg_regs+15*4)(r1) # get remaining CPU registers mfxer r3 mfctr r5 mfdar r6 mfdsisr r7 mfpvr r8 mfsrr0 r9 mfsrr1 r10 # and store them stw r3,ppcreg_xer(r1) stw r5,ppcreg_ctr(r1) stw r6,ppcreg_dar(r1) stw r7,ppcreg_dsisr(r1) stw r8,ppcreg_pvr(r1) stw r9,ppcreg_pc(r1) stw r10,ppcreg_msr(r1) # 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,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,-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. ## Note: CYG_ISR_TABLE_SIZE must match CYG_ISR_COUNT defined in hal_intr.h. #ifdef CYG_HAL_POWERPC_MPC8xx ## First level decoding of MPC8xx SIU interrupt controller. #define CYG_ISR_TABLE_SIZE 59 # decode the interrupt .macro decode_interrupt dreg,state lwz \dreg,ppcreg_vector(\state) # retrieve vector number, rlwinm. \dreg,\dreg,22,31,31 # isolate bit 21 beq 0f # done if decrementer (vec 0) lwi \dreg,CYGARC_REG_IMM_SIVEC # if external, get SIU lbz \dreg,0(\dreg) # vector. srwi \dreg,\dreg,2 addi \dreg,\dreg,1 # Skip decrementer vector 0: stw \dreg,ppcreg_vector(\state) # update vector in state frame. slwi \dreg,\dreg,2 # convert to byte offset. .endm #else ## This is the simple version. No interrupt controller, 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). #define CYG_ISR_TABLE_SIZE 2 # decode the interrupt .macro decode_interrupt dreg,state lwz \dreg,ppcreg_vector(\state) # retrieve vector number, rlwinm \dreg,\dreg,22,31,31 # isolate bit 21 and update stw \dreg,ppcreg_vector(\state) # vector in state frame. slwi \dreg,\dreg,2 # convert to word offset. .endm #endif #--------------------------------------------------------------------------- # Common interrupt handling code. .extern __default_interrupt_vsr __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 r1,r1,ppc_exception_decrement # leave space for registers and # a safety margin stw r3,ppcreg_vector(r1) # stash vector stw r4,ppcreg_cr(r1) # stash CR stw r5,ppcreg_lr(r1) # stash LR # Enable MMU. lwi r3,CYG_MSR_NO_INTS sync mtmsr r3 sync mfspr r3,SPRG1 # save original R3 stw r3,ppcreg_regs+3*4(r1) mfspr r4,SPRG2 # save original R4 stw r4,ppcreg_regs+4*4(r1) mfspr r5,SPRG3 # save original R5 stw r5,ppcreg_regs+5*4(r1) stw r0,ppcreg_regs(r1) # save R0 stw r2,ppcreg_regs+2*4(r1) # save R2 mr r3,r1 # recreate original R1 addi r3,r3,ppc_exception_decrement stw r3,ppcreg_regs+1*4(r1) # and save it in state # Save registers r6..r12/r31 .set _reg,6 .rept MAX_SAVE_REG+1-6 stw _reg,(ppcreg_regs+_reg*4)(r1) .set _reg,_reg+1 .endr # Save registers used in vsr (r14+r15) stw r14,(ppcreg_regs+14*4)(r1) stw r15,(ppcreg_regs+15*4)(r1) # get remaining CPU registers mfxer r3 mfctr r5 mfsrr0 r6 mfsrr1 r7 # and store them stw r3,ppcreg_xer(r1) stw r5,ppcreg_ctr(r1) stw r6,ppcreg_pc(r1) stw r7,ppcreg_msr(r1) # 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,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,-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,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 decode_interrupt r15,r14 # get table index #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT .extern cyg_hal_gdb_isr lwz r3,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 CYG_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,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,ppc_stack_frame_size*2(sp) # sp = *sp subi sp,sp,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,-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. # Note: The instructions restoring the msr mask out the POW bit. # When eCos gets power management aware, this bit will have to be # set to the correct state rather than just cleared. lwi r4,hal_interrupt_objects # get interrupt object table lwzx r4,r4,r15 # load object pointer lwz r6,ppcreg_msr(r14) # restore msr, including lis r5,0xfffe # interrupt enable. andc r6,r6,r5 # mask out reserved bits sync # (and POW!) mtmsr r6 sync 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 addi sp,sp,ppc_stack_frame_size*2 # retrieve CPU state pointer # get sprs we want to restore lwz r3,ppcreg_cr(sp) lwz r4,ppcreg_pc(sp) lwz r5,ppcreg_msr(sp) lwz r6,ppcreg_xer(sp) lwz r7,ppcreg_lr(sp) lwz r8,ppcreg_ctr(sp) # stuff some of them into the CPU mtxer r6 mtlr r7 mtctr r8 # restore R0 and R2 lwz r0,ppcreg_regs(sp) lwz r2,ppcreg_regs+2*4(sp) # Restore registers used in vsr (r14+r15) lwz r14,(ppcreg_regs+14*4)(r1) lwz r15,(ppcreg_regs+15*4)(r1) # restore registers r6..r12/r31 .set _reg,6 .rept MAX_SAVE_REG+1-6 lwz _reg,(ppcreg_regs+_reg*4)(r1) .set _reg,_reg+1 .endr # Here all the registers are loaded except # r1 = ppcregs # 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. mtcr r3 # set ccr lwi r3,CYG_MSR_NO_INTS # do rest with ints disabled sync mtmsr r3 sync mtsrr0 r4 # load old pc mtsrr1 r5 # load old msr lwz r3,ppcreg_regs+3*4(r1) # load r3 value lwz r4,ppcreg_regs+4*4(r1) # load r4 value lwz r5,ppcreg_regs+5*4(r1) # load r5 value lwz r1,ppcreg_regs+1*4(r1) # restore r1 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) # Disable interrupts mfmsr r4 lis r3,0 ori r3,r3,0x8000 andc r5,r4,r3 mtmsr r5 # Change to interrupt stack mr r3,sp lwi sp,__interrupt_stack stwu r3,-4(sp) # store old stackptr on stack mflr r3 stwu r3,-4(sp) # store lr on stack stwu r4,-4(sp) # store msr values on stack stwu r5,-4(sp) # 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,-ppc_stack_frame_size(sp) # create new stack frame # Restore interrupt state mtmsr r4 # Call into kernel which will execute DSRs bl cyg_interrupt_call_pending_DSRs # Unwind stack and get msr values lwzu r5,12+ppc_stack_frame_size(sp) lwz r4,4(sp) lwz r3,8(sp) mtlr r3 # Disable interrupts mtmsr r5 # Restore original stack pointer, original interrupt state and return lwz sp,12(sp) mtmsr r4 blr #endif #--------------------------------------------------------------------------- # Code for putting the CPU in a post-reset state; disabling MMU and caches. _init_CPU: #ifdef CYG_HAL_POWERPC_MPC8xx lwi r3,CYGARC_REG_DC_CMD_CD sync mtspr CYGARC_REG_DC_CST,r3 lwi r3,CYGARC_REG_IC_CMD_CD isync mtspr CYGARC_REG_IC_CST,r3 isync #endif # Set up MSR (disable MMU for now) lwi r3,(CYG_MSR & ~(MSR_IR | MSR_DR)) sync mtmsr r3 sync blr #--------------------------------------------------------------------------- # This table contains a VSR pointer for each defined exception. # All of these except 5 and 9 point to the __default_exception_vsr # above, 5 and 9 point to the __default_interrupt_vsr. Entries in # this table may be changed using Cyg_Interrupt::set_vsr(). .data .globl hal_vsr_table hal_vsr_table: # Architecture defined vectors .long __default_exception_vsr # reserved .long __default_exception_vsr # system reset .long __default_exception_vsr # machine check .long __default_exception_vsr # data storage .long __default_exception_vsr # instruction storage .long __default_interrupt_vsr # external interrupt .long __default_exception_vsr # alignment .long __default_exception_vsr # program .long __default_exception_vsr # floating point unavailable .long __default_interrupt_vsr # decrementer .long __default_exception_vsr # reserved 0x0a00 .long __default_exception_vsr # reserved 0x0b00 .long __default_exception_vsr # system call .long __default_exception_vsr # trace .long __default_exception_vsr # floating point assist .long __default_exception_vsr # reserved 0x0f00 #ifdef CYG_HAL_POWERPC_MPC8xx # Implementation defined vectors .long __default_exception_vsr # software emulation .long __default_exception_vsr # instruction TLB miss .long __default_exception_vsr # data TLB miss .long __default_exception_vsr # instruction TLB error .long __default_exception_vsr # data TLB error .long __default_exception_vsr # reserved 0x1500 .long __default_exception_vsr # reserved 0x1600 .long __default_exception_vsr # reserved 0x1700 .long __default_exception_vsr # reserved 0x1800 .long __default_exception_vsr # reserved 0x1900 .long __default_exception_vsr # reserved 0x1a00 .long __default_exception_vsr # reserved 0x1b00 .long __default_exception_vsr # data breakpoint .long __default_exception_vsr # instruction breakpoint .long __default_exception_vsr # peripheral breakpoint .long __default_exception_vsr # non maskable development port #endif #--------------------------------------------------------------------------- # Interrupt vector tables. # These tables contain the isr, data and object pointers used to deliver # interrupts to user code. #if (CYG_ISR_TABLE_SIZE > 2) .data #else .section ".sdata","aw" #endif .extern hal_default_decrementer_isr .extern hal_default_isr .globl hal_interrupt_handlers hal_interrupt_handlers: .long hal_default_decrementer_isr .rept CYG_ISR_TABLE_SIZE-1 .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 #--------------------------------------------------------------------------- ## 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
