1 ##==========================================================================
5 ## PowerPC exception vectors
7 ##==========================================================================
8 #####ECOSGPLCOPYRIGHTBEGIN####
9 ## -------------------------------------------
10 ## This file is part of eCos, the Embedded Configurable Operating System.
11 ## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 ## Copyright (C) 2002 Gary Thomas
14 ## eCos is free software; you can redistribute it and/or modify it under
15 ## the terms of the GNU General Public License as published by the Free
16 ## Software Foundation; either version 2 or (at your option) any later version.
18 ## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 ## WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 ## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 ## You should have received a copy of the GNU General Public License along
24 ## with eCos; if not, write to the Free Software Foundation, Inc.,
25 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 ## As a special exception, if other files instantiate templates or use macros
28 ## or inline functions from this file, or you compile this file and link it
29 ## with other works to produce a work based on this file, this file does not
30 ## by itself cause the resulting work to be covered by the GNU General Public
31 ## License. However the source code for this file must still be made available
32 ## in accordance with section (3) of the GNU General Public License.
34 ## This exception does not invalidate any other reasons why a work based on
35 ## this file might be covered by the GNU General Public License.
37 ## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 ## at http://sources.redhat.com/ecos/ecos-license/
39 ## -------------------------------------------
40 #####ECOSGPLCOPYRIGHTEND####
41 ##==========================================================================
42 #######DESCRIPTIONBEGIN####
44 ## Author(s): nickg, jskov
45 ## Contributors: nickg, jskov
47 ## Purpose: PowerPC exception vectors
48 ## Description: This file defines the code placed into the exception
49 ## vectors. It also contains the first level default VSRs
50 ## that save and restore state for both exceptions and
53 ######DESCRIPTIONEND####
55 ##==========================================================================
57 #===========================================================================
59 # The PowerPC exception handling has changed as of version 1.3.1.
60 # The primary motivation for rewriting the code was to bring it more
61 # in line with the other HALs, in particular to allow a RAM application
62 # to cleanly take over only a subset of vectors from a running ROM
65 # GDB stubs (and CygMon, should it be ported to PPC) copies
66 # exception vector entry handler code to address 0. These vector entry
67 # handlers (defined by the exception_vector macro below) compute
68 # a vector index into the hal_vsr_table, fetch the pointer, and
69 # jump to the HAL vector service routine (VSR).
71 # The hal_vsr_table is located immediately after the vector
72 # handlers (at address 0x3000), allowing RAM applications to
73 # change VSRs as necessary, while still keeping desired ROM
74 # monitor functionality available for debugging.
76 # ROM applications can still be configured to leave the vector entry
77 # handlers at 0xff000000, but there is at the moment no
78 # provision for reclaiming the reserved vector space in RAM to
81 # RAM applications can also be configured to provide exception
82 # handlers which are copied to address 0 on startup, thus taking
83 # full control of the target.
86 # Default configuration is for RAM applications to rely on an
87 # existing ROM monitor to provide debugging functionality, and
88 # for ROM applications to copy vectors to address 0.
91 # Unfortunately the new exception scheme is not compatible with the
92 # old scheme. Stubs and applications must be compiled using the same
93 # scheme (i.e., old binaries will not run with new stubs, and new
94 # binaries will not run with old stubs).
96 #===========================================================================
98 #include <pkgconf/hal.h>
101 #include <pkgconf/kernel.h> // CYGPKG_KERNEL_INSTRUMENT
104 #define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS
105 #include <cyg/hal/ppc_regs.h>
107 #===========================================================================
111 .extern hal_interrupt_data
112 .extern hal_interrupt_handlers
113 .extern hal_interrupt_objects
114 .extern hal_vsr_table
116 .extern cyg_hal_invoke_constructors
117 .extern cyg_instrument
121 .extern hal_enable_caches
122 .extern hal_hardware_init
123 .extern initialize_stub
130 #===========================================================================
131 # MSR initialization value
132 # zero all bits except:
133 # FP = floating point available
134 # ME = machine check enabled
135 # IP = vectors at 0xFFFxxxxx (ROM startup only)
136 # IR = instruction address translation
137 # DR = data address translation
138 # RI = recoverable interrupt
140 #define CYG_MSR_COMMON (MSR_FP | MSR_ME | MSR_RI)
142 #if (CYGHWR_HAL_POWERPC_VECTOR_BASE == 0xfff00000)
143 # define IP_BIT MSR_IP
148 #ifdef CYGHWR_HAL_POWERPC_ENABLE_MMU
149 # define IR_DR_BITS (MSR_IR | MSR_DR)
151 # define IR_DR_BITS 0
154 #define CYG_MSR (CYG_MSR_COMMON | IP_BIT | IR_DR_BITS)
156 # Include variant macros after MSR definition.
157 #include <cyg/hal/arch.inc>
158 #include <cyg/hal/ppc_offsets.inc>
161 #===========================================================================
162 # If the following option is enabled, we only save registers up to R12.
163 # The PowerPC ABI defines registers 13..31 as callee saved and thus we do
164 # not need to save them when calling C functions.
166 #ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
167 # define MAX_SAVE_REG 12
169 # define MAX_SAVE_REG 31
173 #if defined(CYGHWR_HAL_POWERPC_NEED_VECTORS)
175 #===========================================================================
176 # Start by defining the exceptions vectors that must be placed at
177 # locations 0xFFF00000 or 0x00000000. The following code will normally
178 # be located at 0xFFF00000 in the ROM. It may optionally be copied out
179 # to 0x00000000 if we want to use the RAM vectors. For this reason this code
180 # MUST BE POSITION INDEPENDENT.
182 .section ".vectors","ax"
184 #---------------------------------------------------------------------------
185 # Macros for generating an exception vector service routine
189 .macro reset_vector name
191 .globl __exception_\name
193 #ifdef CYGSEM_HAL_POWERPC_RESET_USES_JUMP
203 # Generic vector macro
205 .macro exception_vector name
207 .globl __exception_\name
209 mtspr SPRG1,r3 # stash some work registers away
213 li r5,__exception_\name-rom_vectors # load low half of vector addr
214 srwi r5,r5,6 # shift right by 6
215 lwi r3,hal_vsr_table # table base
216 lwzx r3,r3,r5 # address of vsr
217 mflr r5 # save link register
218 mtlr r3 # put vsr address into it
219 li r3,__exception_\name-rom_vectors # reload low half of vector addr
220 blr # go to common code
223 #---------------------------------------------------------------------------
224 # Define the exception vectors.
226 // Some platforms won't let us put the vector code just where we want
227 // This macro introduces some lattitude in vector placement
229 #ifdef CYG_HAL_FUDGE_VECTOR_ALIGNMENT
230 hal_fudge_vector_alignment
234 # These are the architecture defined vectors that
235 # are always present.
236 #ifdef CYG_HAL_RESERVED_VECTOR_00000
237 hal_reserved_vector_00000
239 exception_vector reserved_00000
242 exception_vector machine_check
243 exception_vector data_storage
244 exception_vector instruction_storage
245 exception_vector external
246 exception_vector alignment
247 exception_vector program
248 exception_vector floatingpoint_unavailable
249 exception_vector decrementer
250 exception_vector reserved_00a00
251 exception_vector reserved_00b00
252 exception_vector system_call
253 exception_vector trace
254 exception_vector floatingpoint_assist
255 exception_vector reserved_00f00
257 # Variants may define extra vectors.
262 #else // CYGHWR_HAL_POWERPC_NEED_VECTORS
264 # When vectors are not included this is the primary entry point.
265 .globl __exception_reset
271 #endif // CYGHWR_HAL_POWERPC_NEED_VECTORS
275 #===========================================================================
276 # Real startup code. We jump here from the various reset vectors to set up
282 # Initialize CPU to a post-reset state, ensuring the ground doesn''t
283 # shift under us while we try to set things up.
286 # Set up global offset table
287 lwi r2,_GLOBAL_OFFSET_TABLE_
289 # set up time base register to zero
295 # Call platform specific hardware initialization
296 # This may include memory controller initialization. It is not
297 # safe to access RAM until after this point.
298 bl hal_hardware_init # this is platform dependent
299 .globl _hal_hardware_init_done
300 _hal_hardware_init_done:
302 #if !defined(CYG_HAL_STARTUP_ROM) && defined(CYGSEM_HAL_POWERPC_COPY_VECTORS)
304 lwi r4,((CYGHWR_HAL_POWERPC_VECTOR_BASE)-4)
305 lwi r5,rom_vectors_end-4
313 lwi sp,__interrupt_stack
314 mtspr SPRG0,sp # save in sprg0 for later use
316 # Set up exception handlers and VSR table, taking care not to
317 # step on any ROM monitor''s toes.
320 #if defined(CYG_HAL_STARTUP_ROM)
322 # Copy data from ROM to ram
323 lwi r3,__rom_data_start # r3 = rom start
324 lwi r4,__ram_data_start # r4 = ram start
325 lwi r5,__ram_data_end # r5 = ram end
327 cmplw r4,r5 # skip if no data
331 lwz r0,0(r3) # get word from ROM
332 stw r0,0(r4) # store in RAM
333 addi r3,r3,4 # increment by 1 word
334 addi r4,r4,4 # increment by 1 word
335 cmplw r4,r5 # compare
336 blt 1b # loop if not yet done
341 lwi r3,__bss_start # r3 = start
342 lwi r4,__bss_end # r4 = end
344 cmplw r3,r4 # skip if no bss
347 1: stw r0,0(r3) # store zero
348 addi r3,r3,4 # increment by 1 word
349 cmplw r3,r4 # compare
350 blt 1b # loop if not yet done
354 lwi r3,__sbss_start # r3 = start
355 lwi r4,__sbss_end # r4 = end
356 cmplw r3,r4 # skip if no sbss
359 1: stw r0,0(r3) # store zero
360 addi r3,r3,4 # increment by 1 word
361 cmplw r3,r4 # compare
362 blt 1b # loop if not yet done
365 # It is now safe to call C functions which may rely on initialized
368 # Set up stack for calls to C code.
369 subi sp,sp,12 # make space on stack
371 stw r0,0(sp) # clear back chain
372 stw r0,8(sp) # zero return pc
373 stwu sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
375 # Variant HALs may need to do something special before we continue
378 # Platform initialization
381 # MMU and cache are controlled by the same option since caching
382 # on the PPC [typically] does not make sense without the MMU to mark
383 # regions which should not be cached.
384 #ifdef CYGHWR_HAL_POWERPC_ENABLE_MMU
388 # Enable MMU (if desired) so we can safely enable caches.
389 lwi r3,CYG_MSR # interrupts enabled later
396 #endif // CYGHWR_HAL_POWERPC_ENABLE_MMU
398 # set up platform specific interrupt environment
401 # call c++ constructors
402 bl cyg_hal_invoke_constructors
404 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
407 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
408 || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
409 .extern hal_ctrlc_isr_init
410 bl hal_ctrlc_isr_init
413 bl cyg_start # call cyg_start
415 b 9b # if we return, loop
417 #---------------------------------------------------------------------------
418 # This code handles the common part of all exception handlers.
419 # It saves the machine state onto the stack and then calls
420 # a "C" routine to do the rest of the work. This work may result
421 # in thread switches, and changes to the saved state. When we return
422 # here the saved state is restored and execution is continued.
426 .globl cyg_hal_default_exception_vsr
427 cyg_hal_default_exception_vsr:
429 # We come here with all register containing their
430 # pre-exception values except:
431 # R3 = ls 16 bits of vector address
439 # SRR1 = old MSR and the exception cause (the POW state is lost!)
441 subi sp,sp,CYGARC_PPC_EXCEPTION_DECREMENT
442 # leave space for registers and
444 #ifdef CYGPKG_HAL_POWERPC_PPC40x
445 // The caches on this processor are always enabled when the MMU is on
446 // (and disabled when off). Thus we need to be careful about cache
447 // polution and staleness when changing the MMU state.
448 // At this point, the MMU is off due to the exception. We need to
449 // flush the part of the cache which may be touched before the MMU
450 // is reenabled so that memory will be consistent when that happens.
451 // Of course, this is complicated by the fact that there are no "free"
452 // registers at this point in the code.
453 dcbf 0,sp // Flushes first line
454 stw r3,0(sp) // This is now safe
455 li r3,CYGARC_PPCREG_VECTOR // Flush lines which will be changed
457 li r3,CYGARC_PPCREG_CR
459 li r3,CYGARC_PPCREG_LR
461 lwz r3,0(sp) // Restore register
464 # First, save away some registers
465 stw r3,CYGARC_PPCREG_VECTOR(sp) # stash vector
466 stw r4,CYGARC_PPCREG_CR(sp) # stash CR
467 stw r5,CYGARC_PPCREG_LR(sp) # stash LR
469 #ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
470 # Mark this fram as an Exception frame
472 stw r3,CYGARC_PPCREG_WALL_HEAD(sp)
474 stw r3,CYGARC_PPCREG_WALL_TAIL(sp)
477 # Enable MMU & interrupt/FPU environment (as configured)
483 mfspr r3,SPRG1 # save original R3
484 stw r3,CYGARC_PPCREG_REGS+3*4(sp)
485 mfspr r4,SPRG2 # save original R4
486 stw r4,CYGARC_PPCREG_REGS+4*4(sp)
487 mfspr r5,SPRG3 # save original R5
488 stw r5,CYGARC_PPCREG_REGS+5*4(sp)
490 stw r0,CYGARC_PPCREG_REGS+0*4(sp) # save R0
491 stw r2,CYGARC_PPCREG_REGS+2*4(sp) # save R2
493 mr r3,sp # recreate original SP
494 addi r3,r3,CYGARC_PPC_EXCEPTION_DECREMENT
495 stw r3,CYGARC_PPCREG_REGS+1*4(sp) # and save it in state
497 # Save registers r6..r12/r31
499 .rept MAX_SAVE_REG+1-6
500 stw _reg,(CYGARC_PPCREG_REGS+_reg*4)(sp)
504 # Save registers used in vsr (r14+r15)
505 stw r14,(CYGARC_PPCREG_REGS+14*4)(sp)
506 stw r15,(CYGARC_PPCREG_REGS+15*4)(sp)
508 # get remaining family CPU registers
514 stw r3,CYGARC_PPCREG_XER(sp)
515 stw r4,CYGARC_PPCREG_CTR(sp)
516 stw r5,CYGARC_PPCREG_PC(sp)
517 stw r6,CYGARC_PPCREG_MSR(sp)
519 # Save variant registers
525 # The entire CPU state is now stashed on the stack,
526 # call into C to do something with it.
528 mr r3,sp # R3 = register dump
530 subi sp,sp,CYGARC_PPC_STACK_FRAME_SIZE # make a null frame
533 stw r0,0(sp) # backchain = 0
534 stw r0,8(sp) # return pc = 0
536 stwu sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
537 # where C code can save LR
539 lwi r5,restore_state # get return link
540 mtlr r5 # to link register
542 .extern cyg_hal_exception_handler
543 b cyg_hal_exception_handler # call C code, r3 = registers
545 # When the call returns it will go to restore_state below.
548 ##--------------------------------------------------------------------------
549 ## The following macros are defined depending on whether the Interrupt
550 ## system is using isr tables or chaining, and depending on the interrupt
551 ## controller in the system.
553 #ifndef CYGPKG_HAL_POWERPC_INTC_DEFINED
555 ## This is the simple version. No interrupt controller, CYGARC_PPCREG_VECTOR
556 ## is updated with the decoded interrupt vector. Isr tables/chaining
557 ## use same interrupt decoder.
558 ## Bit 21 biffers between decrementer (0) and external (1).
560 # decode the interrupt
561 .macro hal_intc_decode dreg,state
562 lwz \dreg,CYGARC_PPCREG_VECTOR(\state) # retrieve vector number,
563 rlwinm \dreg,\dreg,22,31,31 # isolate bit 21 and update
564 stw \dreg,CYGARC_PPCREG_VECTOR(\state) # vector in state frame.
565 slwi \dreg,\dreg,2 # convert to word offset.
568 #endif // CYGPKG_HAL_POWERPC_INTC_DEFINED
570 #---------------------------------------------------------------------------
571 # Common interrupt handling code.
573 .globl cyg_hal_default_interrupt_vsr
574 cyg_hal_default_interrupt_vsr:
576 # We come here with all register containing their
577 # pre-exception values except:
578 # R3 = ls 16 bits of vector address
589 subi sp,sp,CYGARC_PPC_EXCEPTION_DECREMENT
590 # leave space for registers and
592 #ifdef CYGPKG_HAL_POWERPC_PPC40x
593 // The caches on this processor are always enabled when the MMU is on
594 // (and disabled when off). Thus we need to be careful about cache
595 // polution and staleness when changing the MMU state.
596 // At this point, the MMU is off due to the exception. We need to
597 // flush the part of the cache which may be touched before the MMU
598 // is reenabled so that memory will be consistent when that happens.
599 // Of course, this is complicated by the fact that there are no "free"
600 // registers at this point in the code.
601 dcbf 0,sp // Flushes first line
602 stw r3,0(sp) // This is now safe
603 li r3,CYGARC_PPCREG_VECTOR // Flush lines which will be changed
605 li r3,CYGARC_PPCREG_CR
607 li r3,CYGARC_PPCREG_LR
609 lwz r3,0(sp) // Restore register
612 stw r3,CYGARC_PPCREG_VECTOR(sp) # stash vector
613 stw r4,CYGARC_PPCREG_CR(sp) # stash CR
614 stw r5,CYGARC_PPCREG_LR(sp) # stash LR
616 #ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
617 # Mark this fram as an 1nterrupt frame
619 stw r3,CYGARC_PPCREG_WALL_HEAD(sp)
621 stw r3,CYGARC_PPCREG_WALL_TAIL(sp)
624 # Enable MMU & interrupt/FPU environment as configured
630 mfspr r3,SPRG1 # save original R3
631 stw r3,CYGARC_PPCREG_REGS+3*4(sp)
632 mfspr r4,SPRG2 # save original R4
633 stw r4,CYGARC_PPCREG_REGS+4*4(sp)
634 mfspr r5,SPRG3 # save original R5
635 stw r5,CYGARC_PPCREG_REGS+5*4(sp)
637 stw r0,CYGARC_PPCREG_REGS+0*4(sp) # save R0
638 stw r2,CYGARC_PPCREG_REGS+2*4(sp) # save R2
640 mr r3,sp # recreate original SP
641 addi r3,r3,CYGARC_PPC_EXCEPTION_DECREMENT
642 stw r3,CYGARC_PPCREG_REGS+1*4(sp) # and save it in state
644 # Save registers r6..r12/r31
646 .rept MAX_SAVE_REG+1-6
647 stw _reg,(CYGARC_PPCREG_REGS+_reg*4)(sp)
651 # Save registers used in vsr (r14+r15)
652 stw r14,CYGARC_PPCREG_REGS+14*4(sp)
653 stw r15,CYGARC_PPCREG_REGS+15*4(sp)
655 # get remaining family CPU registers
662 stw r3,CYGARC_PPCREG_XER(sp)
663 stw r4,CYGARC_PPCREG_CTR(sp)
664 stw r5,CYGARC_PPCREG_PC(sp)
665 stw r6,CYGARC_PPCREG_MSR(sp)
667 # Save variant registers
673 # The entire CPU state is now stashed on the stack,
674 # increment the scheduler lock and call the ISR
677 #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
678 .extern cyg_scheduler_sched_lock
679 lwi r3,cyg_scheduler_sched_lock
685 mr r14,sp # r14 = register dump
687 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
688 lwi r3,__interrupt_stack # stack top
689 lwi r4,__interrupt_stack_base # stack base
690 sub. r5,sp,r4 # sp - base
691 blt 1f # if < 0 - not on istack
692 sub. r5,r3,sp # top - sp
693 bgt 2f # if > 0 - already on istack
695 1: mr sp,r3 # switch to istack
697 2: stwu r14,-4(sp) # save old SP on stack
701 subi sp,sp,CYGARC_PPC_STACK_FRAME_SIZE # make a null frame
704 stw r0,0(sp) # backchain = 0
705 stw r0,8(sp) # return pc = 0
707 stwu sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
708 # where C code can save LR
710 #if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
712 lwi r3,0x0301 # r3 = type = INTR,RAISE
713 lwz r4,CYGARC_PPCREG_VECTOR(r14) # arg1 = vector address
714 srwi r4,r4,8 # arg1 = vector number
715 xor r5,r5,r5 # arg2 = 0
716 bl cyg_instrument # call instrument function
720 hal_intc_decode r15,r14 # get table index
722 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
723 || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
724 # If we are supporting Ctrl-C interrupts from GDB, we must squirrel
725 # away a pointer to the save interrupt state here so that we can
726 # plant a breakpoint at some later time.
728 .extern hal_saved_interrupt_state
729 lwi r3,hal_saved_interrupt_state
734 #ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
736 #ifdef CYGPKG_HAL_POWERPC_MPC8xx
737 # The CPM controller allows nested interrupts. However,
738 # it sits on the back of the SIU controller which has no
739 # HW support for this. In effect, SW masking of lower
740 # priority IRQs in the SIU would be required for this to work.
745 lwz r3,CYGARC_PPCREG_VECTOR(r14) # retrieve decoded vector #
747 lwi r6,hal_interrupt_handlers # get interrupt handler table
748 lwzx r6,r6,r15 # load routine pointer
750 lwi r4,hal_interrupt_data # get interrupt data table
751 lwzx r4,r4,r15 # load data pointer
753 mr r5,r14 # R5 = saved registers
755 mtctr r6 # put isr address in ctr
757 bctrl # branch to ctr reg and link
759 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
761 # If we are returning from the last nested interrupt, move back
762 # to the thread stack. interrupt_end() must be called on the
763 # thread stack since it potentially causes a context switch.
764 # Since we have arranged for the top of stack location to
765 # contain the sp we need to go back to here, just pop it off
769 lwz sp,CYGARC_PPC_STACK_FRAME_SIZE*2(sp) # sp = *sp
771 subi sp,sp,CYGARC_PPC_STACK_FRAME_SIZE # make a null frame
774 stw r0,0(sp) # backchain = 0
775 stw r0,8(sp) # return pc = 0
777 stwu sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp) # create new stack frame
778 # where C code can save LR
781 # On return r3 bit 1 will indicate whether a DSR is
782 # to be posted. Pass this together with a pointer to
783 # the interrupt object we have just used to the
784 # interrupt tidy up routine.
786 # Note that r14 and r15 are defined to be preserved across
787 # calls by the calling convention, so they still contain
788 # the register dump and the vector number respectively.
790 lwi r4,hal_interrupt_objects # get interrupt object table
791 lwzx r4,r4,r15 # load object pointer
792 mr r5,r14 # arg3 = saved register dump
794 .extern interrupt_end
795 bl interrupt_end # call into C to finish off
798 # All done, restore CPU state and continue
800 # retrieve CPU state pointer
801 addi sp,sp,CYGARC_PPC_STACK_FRAME_SIZE*2
803 # Restore FPU registers
806 # Restore variant registers
809 # get sprs we want to restore
810 # stuff some of them into the CPU
811 lwz r3,CYGARC_PPCREG_XER(sp)
812 lwz r4,CYGARC_PPCREG_LR(sp)
813 lwz r5,CYGARC_PPCREG_CTR(sp)
818 # Restore registers used in vsr (r14+r15)
819 lwz r14,CYGARC_PPCREG_REGS+14*4(r1)
820 lwz r15,CYGARC_PPCREG_REGS+15*4(r1)
822 # restore registers r6..r12/r31
824 .rept MAX_SAVE_REG+1-6
825 lwz _reg,(CYGARC_PPCREG_REGS+_reg*4)(sp)
832 lwz r0,CYGARC_PPCREG_REGS+0*4(sp)
833 lwz r2,CYGARC_PPCREG_REGS+2*4(sp)
835 # Here all the registers are loaded except
836 # sp = HAL_SavedRegisters
841 # We have to disable interrupts while srr0 and
842 # srr1 are loaded, since another interrupt will
845 lwz r3,CYGARC_PPCREG_CR(sp)
846 lwz r4,CYGARC_PPCREG_PC(sp)
847 lwz r5,CYGARC_PPCREG_MSR(sp)
849 mtsrr0 r4 # load old pc
850 mtsrr1 r5 # load old msr
852 #ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
853 # Mark this frame as (almost) dead.
855 stw r3,CYGARC_PPCREG_WALL_HEAD(sp)
857 stw r3,CYGARC_PPCREG_WALL_TAIL(sp)
860 lwz r3,CYGARC_PPCREG_REGS+3*4(sp) # load r3 value
861 lwz r4,CYGARC_PPCREG_REGS+4*4(sp) # load r4 value
862 lwz r5,CYGARC_PPCREG_REGS+5*4(sp) # load r5 value
863 lwz sp,CYGARC_PPCREG_REGS+1*4(sp) # restore sp
865 sync # settle things down
871 ##-----------------------------------------------------------------------------
872 ## Execute pending DSRs on the interrupt stack with interrupts enabled.
873 ## Note: this can only be called from code running on a thread stack
875 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
876 .extern cyg_interrupt_call_pending_DSRs
878 FUNC_START(hal_interrupt_stack_call_pending_DSRs)
879 # Change to interrupt stack, save state and set up stack for
882 lwi r4,__interrupt_stack
883 subi r4,r4,24 # make space on stack
885 stw r3,12(sp) # save old sp
887 stw r3,16(sp) # save old MSR
889 stw r3,20(sp) # save old LR
892 stw r0,0(sp) # clear back chain
893 stw r0,8(sp) # zero return pc
897 # Call into kernel which will execute DSRs
898 stwu sp,-CYGARC_PPC_STACK_FRAME_SIZE(sp)
899 bl cyg_interrupt_call_pending_DSRs
900 addi sp,sp,CYGARC_PPC_STACK_FRAME_SIZE
902 lwz r3,20(sp) # restore LR
904 lwz r5,12(sp) # get SP from saved state
905 lwz r3,16(sp) # restore interrupt setting
908 mr sp,r5 # restore stack pointer
909 blr # and return to caller
912 #---------------------------------------------------------------------------
913 ## Temporary interrupt stack
918 .global cyg_interrupt_stack_base
919 cyg_interrupt_stack_base:
920 __interrupt_stack_base:
921 .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
925 .global cyg_interrupt_stack
929 .long 0,0,0,0,0,0,0,0
931 #---------------------------------------------------------------------------