summaryrefslogblamecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_async_normal.S
blob: 59e621f64fb74279b470d7881dc612470ef9c319 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
  
                                                                      

                        
                 





                                                          
                                        






                               
                            











                                           
                                             














                                                                              















                                                                              



                                             





                                                    

                                        

                                                                   
                                             








                                                                             







                                                                







                                                             
             

      












                                                              



                                                                   

                                                              
                                                              
                                                                            
                                                                          
                                                                                                 
 
                                                                
 
                                        







                                                                               



                                                                     
 
                                                            
 
                                        









                                                                            
                                             
 




                                                                























                                                                                  


































































                                                             



                                                                        

                                                                                                 




                                          
                                        









                                                                       



                                             

                                                                   


                                                                                                 








                                                                              




                                                                   

                                                                   
                            

                                                                                                 
 









                                                              
                                                 


                                            
                                       
                            


                                


































































                                                             













                                                                   
                                                          
                                                              
                                                              




                                                        
                                                                          




                                                  
                                                            


                                                      
                                                                
                                  
                                                                
                                  
                                                                
                                  
                                                                
                                  
                                                                
                                  
                                                                
 




                                                                




                                                  


                                               
/*
 * Copyright (c) 2011-2015 embedded brains GmbH.  All rights reserved.
 *
 *  embedded brains GmbH
 *  Dornierstr. 4
 *  82178 Puchheim
 *  Germany
 *  <rtems@embedded-brains.de>
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rtems.org/license/LICENSE.
 */

#include <bspopts.h>
#include <rtems/score/percpu.h>
#include <bsp/vectors.h>

#define VECTOR_REGISTER r4
#define SELF_CPU_REGISTER r5
#define ISR_NEST_REGISTER r6
#define DISPATCH_LEVEL_REGISTER r7
#define HANDLER_REGISTER r8
#define SCRATCH_0_REGISTER r0
#define SCRATCH_1_REGISTER r3
#define SCRATCH_2_REGISTER r9
#define SCRATCH_3_REGISTER r10
#define SCRATCH_4_REGISTER r11
#define SCRATCH_5_REGISTER r12
#define FRAME_REGISTER r14

#define VECTOR_OFFSET(reg) GPR4_OFFSET(reg)
#define SELF_CPU_OFFSET(reg) GPR5_OFFSET(reg)
#define ISR_NEST_OFFSET(reg) GPR6_OFFSET(reg)
#define DISPATCH_LEVEL_OFFSET(reg) GPR7_OFFSET(reg)
#define HANDLER_OFFSET(reg) GPR8_OFFSET(reg)
#define SCRATCH_0_OFFSET(reg) GPR0_OFFSET(reg)
#define SCRATCH_1_OFFSET(reg) GPR3_OFFSET(reg)
#define SCRATCH_2_OFFSET(reg) GPR9_OFFSET(reg)
#define SCRATCH_3_OFFSET(reg) GPR10_OFFSET(reg)
#define SCRATCH_4_OFFSET(reg) GPR11_OFFSET(reg)
#define SCRATCH_5_OFFSET(reg) GPR12_OFFSET(reg)

/*
 * The register 2 slot is free, since this is the read-only small data anchor.
 */
#define FRAME_OFFSET(reg) GPR2_OFFSET(reg)

#ifdef RTEMS_PROFILING
/*
 * The PPC_EXC_MINIMAL_FRAME_SIZE is enough to store this additional register.
 */
#define ENTRY_INSTANT_REGISTER r15
#define ENTRY_INSTANT_OFFSET(reg) GPR13_OFFSET(reg)

.macro GET_TIME_BASE REG
#ifdef ppc8540
	mfspr	\REG, TBRL
#else /* ppc8540 */
	mftb	\REG
#endif /* ppc8540 */
.endm
#endif /* RTEMS_PROFILING */

#ifdef PPC_EXC_CONFIG_USE_FIXED_HANDLER
	.global	bsp_interrupt_dispatch
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */

	.global	ppc_exc_min_prolog_async_tmpl_normal
	.global ppc_exc_wrap_async_normal

ppc_exc_min_prolog_async_tmpl_normal:

	stwu	r1, -PPC_EXC_MINIMAL_FRAME_SIZE(r1)

#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
	stw	VECTOR_REGISTER, PPC_EXC_VECTOR_PROLOGUE_OFFSET(r1)
	li	VECTOR_REGISTER, 0xffff8000
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */

	/*
	 * We store the absolute branch target address here.  It will be used
	 * to generate the branch operation in ppc_exc_make_prologue().
	 */
	.int	ppc_exc_wrap_async_normal

ppc_exc_wrap_async_normal:

#ifdef RTEMS_PROFILING
	/* Save non-volatile ENTRY_INSTANT_REGISTER */
	stw	ENTRY_INSTANT_REGISTER, ENTRY_INSTANT_OFFSET(r1)

	/* Get entry instant */
	GET_TIME_BASE	ENTRY_INSTANT_REGISTER
#endif /* RTEMS_PROFILING */

	/* Save non-volatile FRAME_REGISTER */
	stw	FRAME_REGISTER, FRAME_OFFSET(r1)

#ifdef __SPE__
	/* Enable SPE */
	mfmsr	FRAME_REGISTER
	oris	FRAME_REGISTER, FRAME_REGISTER, MSR_SPE >> 16
	mtmsr	FRAME_REGISTER
	isync
#endif

#if defined(PPC_MULTILIB_FPU) || defined(PPC_MULTILIB_ALTIVEC)
	/* Enable FPU and/or AltiVec */
	mfmsr	FRAME_REGISTER
#ifdef PPC_MULTILIB_FPU
	ori	FRAME_REGISTER, FRAME_REGISTER, MSR_FP
#endif
#ifdef PPC_MULTILIB_ALTIVEC
	oris	FRAME_REGISTER, FRAME_REGISTER, MSR_VE >> 16
#endif
	mtmsr	FRAME_REGISTER
	isync
#endif

	/* Move frame pointer to non-volatile FRAME_REGISTER */
	mr	FRAME_REGISTER, r1

	/* Load ISR nest level and thread dispatch disable level */
	PPC_GPR_STORE	SELF_CPU_REGISTER, SELF_CPU_OFFSET(r1)
	GET_SELF_CPU_CONTROL	SELF_CPU_REGISTER
	PPC_GPR_STORE	ISR_NEST_REGISTER, ISR_NEST_OFFSET(r1)
	lwz	ISR_NEST_REGISTER, PER_CPU_ISR_NEST_LEVEL(SELF_CPU_REGISTER)
	PPC_GPR_STORE	DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_OFFSET(r1)
	lwz	DISPATCH_LEVEL_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SELF_CPU_REGISTER)

	PPC_GPR_STORE	SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)

#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
#ifdef __SPE__
	/*
	 * Save high order part of VECTOR_REGISTER here.  The low order part
	 * was saved in the minimal prologue.
	 */
	evmergehi	SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, VECTOR_REGISTER
	stw	SCRATCH_0_REGISTER, VECTOR_OFFSET(r1)
#endif
#else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
	/* The vector register has no special purpose in this case */
	PPC_GPR_STORE	VECTOR_REGISTER, VECTOR_OFFSET(r1)
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */

	PPC_GPR_STORE	HANDLER_REGISTER, HANDLER_OFFSET(r1)

#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
	/*
	 * Load the handler address.  Get the handler table index from the
	 * vector number.  We have to discard the exception type.  Take only
	 * the least significant five bits (= LAST_VALID_EXC + 1) from the
	 * vector register.  Multiply by four (= size of function pointer).
	 */
	rlwinm	SCRATCH_0_REGISTER, VECTOR_REGISTER, 2, 25, 29
	lis	HANDLER_REGISTER, ppc_exc_handler_table@h
	ori	HANDLER_REGISTER, HANDLER_REGISTER, ppc_exc_handler_table@l
	lwzx	HANDLER_REGISTER, HANDLER_REGISTER, SCRATCH_0_REGISTER
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */

	PPC_GPR_STORE	SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1)
	PPC_GPR_STORE	SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1)
	PPC_GPR_STORE	SCRATCH_3_REGISTER, SCRATCH_3_OFFSET(r1)
	PPC_GPR_STORE	SCRATCH_4_REGISTER, SCRATCH_4_OFFSET(r1)
	PPC_GPR_STORE	SCRATCH_5_REGISTER, SCRATCH_5_OFFSET(r1)

	/* Save SRR0, SRR1, CR, CTR, XER, and LR */
	mfsrr0	SCRATCH_0_REGISTER
	mfsrr1	SCRATCH_1_REGISTER
	mfcr	SCRATCH_2_REGISTER
	mfctr	SCRATCH_3_REGISTER
	mfxer	SCRATCH_4_REGISTER
	mflr	SCRATCH_5_REGISTER
	stw	SCRATCH_0_REGISTER, SRR0_FRAME_OFFSET(r1)
	stw	SCRATCH_1_REGISTER, SRR1_FRAME_OFFSET(r1)
	stw	SCRATCH_2_REGISTER, EXC_CR_OFFSET(r1)
	stw	SCRATCH_3_REGISTER, EXC_CTR_OFFSET(r1)
	stw	SCRATCH_4_REGISTER, EXC_XER_OFFSET(r1)
	stw	SCRATCH_5_REGISTER, EXC_LR_OFFSET(r1)

#ifdef __SPE__
	/* Save SPEFSCR and ACC */
	mfspr	SCRATCH_0_REGISTER, FSL_EIS_SPEFSCR
	evxor	SCRATCH_1_REGISTER, SCRATCH_1_REGISTER, SCRATCH_1_REGISTER
	evmwumiaa	SCRATCH_1_REGISTER, SCRATCH_1_REGISTER, SCRATCH_1_REGISTER
	stw	SCRATCH_0_REGISTER, PPC_EXC_SPEFSCR_OFFSET(r1)
	evstdd	SCRATCH_1_REGISTER, PPC_EXC_ACC_OFFSET(r1)
#endif

#ifdef PPC_MULTILIB_ALTIVEC
	/* Save volatile AltiVec context */
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(0)
	stvx	v0, r1, SCRATCH_0_REGISTER
	mfvscr	v0
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(1)
	stvx	v1, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(2)
	stvx	v2, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(3)
	stvx	v3, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(4)
	stvx	v4, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(5)
	stvx	v5, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(6)
	stvx	v6, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(7)
	stvx	v7, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(8)
	stvx	v8, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(9)
	stvx	v9, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(10)
	stvx	v10, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(11)
	stvx	v11, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(12)
	stvx	v12, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(13)
	stvx	v13, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(14)
	stvx	v14, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(15)
	stvx	v15, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(16)
	stvx	v16, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(17)
	stvx	v17, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(18)
	stvx	v18, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(19)
	stvx	v19, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VSCR_OFFSET
	stvewx	v0, r1, SCRATCH_0_REGISTER
#endif

#ifdef PPC_MULTILIB_FPU
	/* Save volatile FPU context */
	stfd	f0, PPC_EXC_MIN_FR_OFFSET(0)(r1)
	mffs	f0
	stfd	f1, PPC_EXC_MIN_FR_OFFSET(1)(r1)
	stfd	f2, PPC_EXC_MIN_FR_OFFSET(2)(r1)
	stfd	f3, PPC_EXC_MIN_FR_OFFSET(3)(r1)
	stfd	f4, PPC_EXC_MIN_FR_OFFSET(4)(r1)
	stfd	f5, PPC_EXC_MIN_FR_OFFSET(5)(r1)
	stfd	f6, PPC_EXC_MIN_FR_OFFSET(6)(r1)
	stfd	f7, PPC_EXC_MIN_FR_OFFSET(7)(r1)
	stfd	f8, PPC_EXC_MIN_FR_OFFSET(8)(r1)
	stfd	f9, PPC_EXC_MIN_FR_OFFSET(9)(r1)
	stfd	f10, PPC_EXC_MIN_FR_OFFSET(10)(r1)
	stfd	f11, PPC_EXC_MIN_FR_OFFSET(11)(r1)
	stfd	f12, PPC_EXC_MIN_FR_OFFSET(12)(r1)
	stfd	f13, PPC_EXC_MIN_FR_OFFSET(13)(r1)
	stfd	f0, PPC_EXC_MIN_FPSCR_OFFSET(r1)
#endif

	/* Increment ISR nest level and thread dispatch disable level */
	cmpwi	ISR_NEST_REGISTER, 0
	addi	ISR_NEST_REGISTER, ISR_NEST_REGISTER, 1
	addi	DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_REGISTER, 1
	stw	ISR_NEST_REGISTER, PER_CPU_ISR_NEST_LEVEL(SELF_CPU_REGISTER)
	stw	DISPATCH_LEVEL_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SELF_CPU_REGISTER)

	/* Switch stack if necessary */
	mfspr	SCRATCH_0_REGISTER, SPRG1
	iselgt	r1, r1, SCRATCH_0_REGISTER

#ifndef PPC_EXC_CONFIG_USE_FIXED_HANDLER
	/*
	 * Call high level exception handler.
	 *
	 * First parameter = exception frame pointer + FRAME_LINK_SPACE
	 * Second parameter = vector number (r4 is the VECTOR_REGISTER)
	 */
	addi	r3, FRAME_REGISTER, FRAME_LINK_SPACE
	rlwinm	VECTOR_REGISTER, VECTOR_REGISTER, 0, 27, 31
	mtctr	HANDLER_REGISTER
	bctrl
#else /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
	/* Call fixed high level handler */
	bl	bsp_interrupt_dispatch
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */

	/* Load ISR nest level and thread dispatch disable level */
	GET_SELF_CPU_CONTROL	SELF_CPU_REGISTER
	lwz	ISR_NEST_REGISTER, PER_CPU_ISR_NEST_LEVEL(SELF_CPU_REGISTER)
	lwz	DISPATCH_LEVEL_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SELF_CPU_REGISTER)

	/*
	 * Switch back to original stack (FRAME_REGISTER == r1 if we are still
	 * on the IRQ stack) and restore FRAME_REGISTER.
	 */
	mr	r1, FRAME_REGISTER
	lwz	FRAME_REGISTER, FRAME_OFFSET(r1)

	/* Decrement ISR nest level and thread dispatch disable level */
#ifdef RTEMS_PROFILING
	subic.	ISR_NEST_REGISTER, ISR_NEST_REGISTER, 1
	subi	DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_REGISTER, 1
	cmpwi	cr2, DISPATCH_LEVEL_REGISTER, 0
#else /* RTEMS_PROFILING */
	subi	ISR_NEST_REGISTER, ISR_NEST_REGISTER, 1
	subic.	DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_REGISTER, 1
#endif /* RTEMS_PROFILING */
	stw	ISR_NEST_REGISTER, PER_CPU_ISR_NEST_LEVEL(SELF_CPU_REGISTER)
	stw	DISPATCH_LEVEL_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SELF_CPU_REGISTER)

#ifdef RTEMS_PROFILING
	/* Store profiling data if necessary */
	bne	profiling_done
	mr	r3, SELF_CPU_REGISTER
	mr	r4, ENTRY_INSTANT_REGISTER
	GET_TIME_BASE	r5
	bl	_Profiling_Outer_most_interrupt_entry_and_exit
profiling_done:
#endif /* RTEMS_PROFILING */

	/* Call thread dispatcher if necessary */
#ifdef RTEMS_PROFILING
	bne	cr2, thread_dispatching_done
#else /* RTEMS_PROFILING */
	bne	thread_dispatching_done
#endif /* RTEMS_PROFILING */
	bl	_Thread_Dispatch
thread_dispatching_done:

#ifdef PPC_MULTILIB_ALTIVEC
	/* Restore volatile AltiVec context */
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VSCR_OFFSET
	lvewx	v0, r1, SCRATCH_0_REGISTER
	mtvscr	v0
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(0)
	lvx	v0, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(1)
	lvx	v1, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(2)
	lvx	v2, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(3)
	lvx	v3, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(4)
	lvx	v4, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(5)
	lvx	v5, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(6)
	lvx	v6, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(7)
	lvx	v7, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(8)
	lvx	v8, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(9)
	lvx	v9, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(10)
	lvx	v10, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(11)
	lvx	v11, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(12)
	lvx	v12, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(13)
	lvx	v13, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(14)
	lvx	v14, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(15)
	lvx	v15, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(16)
	lvx	v16, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(17)
	lvx	v17, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(18)
	lvx	v18, r1, SCRATCH_0_REGISTER
	li	SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(19)
	lvx	v19, r1, SCRATCH_0_REGISTER
#endif

#ifdef PPC_MULTILIB_FPU
	/* Restore volatile FPU context */
	lfd	f0, PPC_EXC_MIN_FPSCR_OFFSET(r1)
	mtfsf	0xff, f0
	lfd	f0, PPC_EXC_MIN_FR_OFFSET(0)(r1)
	lfd	f1, PPC_EXC_MIN_FR_OFFSET(1)(r1)
	lfd	f2, PPC_EXC_MIN_FR_OFFSET(2)(r1)
	lfd	f3, PPC_EXC_MIN_FR_OFFSET(3)(r1)
	lfd	f4, PPC_EXC_MIN_FR_OFFSET(4)(r1)
	lfd	f5, PPC_EXC_MIN_FR_OFFSET(5)(r1)
	lfd	f6, PPC_EXC_MIN_FR_OFFSET(6)(r1)
	lfd	f7, PPC_EXC_MIN_FR_OFFSET(7)(r1)
	lfd	f8, PPC_EXC_MIN_FR_OFFSET(8)(r1)
	lfd	f9, PPC_EXC_MIN_FR_OFFSET(9)(r1)
	lfd	f10, PPC_EXC_MIN_FR_OFFSET(10)(r1)
	lfd	f11, PPC_EXC_MIN_FR_OFFSET(11)(r1)
	lfd	f12, PPC_EXC_MIN_FR_OFFSET(12)(r1)
	lfd	f13, PPC_EXC_MIN_FR_OFFSET(13)(r1)
#endif

#ifdef __SPE__
	/* Load SPEFSCR and ACC */
	lwz	DISPATCH_LEVEL_REGISTER, PPC_EXC_SPEFSCR_OFFSET(r1)
	evldd	HANDLER_REGISTER, PPC_EXC_ACC_OFFSET(r1)
#endif

	/* Load SRR0, SRR1, CR, CTR, XER, and LR */
	lwz	SCRATCH_0_REGISTER, SRR0_FRAME_OFFSET(r1)
	lwz	SCRATCH_1_REGISTER, SRR1_FRAME_OFFSET(r1)
	lwz	SCRATCH_2_REGISTER, EXC_CR_OFFSET(r1)
	lwz	SCRATCH_3_REGISTER, EXC_CTR_OFFSET(r1)
	lwz	SCRATCH_4_REGISTER, EXC_XER_OFFSET(r1)
	lwz	SCRATCH_5_REGISTER, EXC_LR_OFFSET(r1)

	PPC_GPR_LOAD	VECTOR_REGISTER, VECTOR_OFFSET(r1)
	PPC_GPR_LOAD	SELF_CPU_REGISTER, SELF_CPU_OFFSET(r1)
	PPC_GPR_LOAD	ISR_NEST_REGISTER, ISR_NEST_OFFSET(r1)

#ifdef __SPE__
	/* Restore SPEFSCR */
	mtspr	FSL_EIS_SPEFSCR, DISPATCH_LEVEL_REGISTER
#endif
	PPC_GPR_LOAD	DISPATCH_LEVEL_REGISTER, DISPATCH_LEVEL_OFFSET(r1)

#ifdef __SPE__
	/* Restore ACC */
	evmra	HANDLER_REGISTER, HANDLER_REGISTER
#endif
	PPC_GPR_LOAD	HANDLER_REGISTER, HANDLER_OFFSET(r1)

	/* Restore SRR0, SRR1, CR, CTR, XER, and LR */
	mtsrr0	SCRATCH_0_REGISTER
	PPC_GPR_LOAD	SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)
	mtsrr1	SCRATCH_1_REGISTER
	PPC_GPR_LOAD	SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1)
	mtcr	SCRATCH_2_REGISTER
	PPC_GPR_LOAD	SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1)
	mtctr	SCRATCH_3_REGISTER
	PPC_GPR_LOAD	SCRATCH_3_REGISTER, SCRATCH_3_OFFSET(r1)
	mtxer	SCRATCH_4_REGISTER
	PPC_GPR_LOAD	SCRATCH_4_REGISTER, SCRATCH_4_OFFSET(r1)
	mtlr	SCRATCH_5_REGISTER
	PPC_GPR_LOAD	SCRATCH_5_REGISTER, SCRATCH_5_OFFSET(r1)

#ifdef RTEMS_PROFILING
	/* Restore ENTRY_INSTANT_REGISTER */
	lwz	ENTRY_INSTANT_REGISTER, ENTRY_INSTANT_OFFSET(r1)
#endif /* RTEMS_PROFILING */

	/* Pop stack */
	addi	r1, r1, PPC_EXC_MINIMAL_FRAME_SIZE

	/* Return */
	rfi

/* Symbol provided for debugging and tracing */
ppc_exc_wrap_async_normal_end: