/*
* 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