diff options
Diffstat (limited to 'bsps/powerpc/shared/exceptions/ppc_exc.S')
-rw-r--r-- | bsps/powerpc/shared/exceptions/ppc_exc.S | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/bsps/powerpc/shared/exceptions/ppc_exc.S b/bsps/powerpc/shared/exceptions/ppc_exc.S new file mode 100644 index 0000000000..c606c0da30 --- /dev/null +++ b/bsps/powerpc/shared/exceptions/ppc_exc.S @@ -0,0 +1,185 @@ +/* + * (c) 1999, Eric Valette valette@crf.canon.fr + * + * Modified and partially rewritten by Till Straumann, 2007 + * + * Modified by Sebastian Huber <sebastian.huber@embedded-brains.de>, 2008. + * + * Low-level assembly code for PPC exceptions. + * + * This file was written with the goal to eliminate + * ALL #ifdef <cpu_flavor> conditionals -- please do not + * reintroduce such statements. + */ + +/* Load macro definitions */ +#include <rtems/asm.h> +#include <rtems/system.h> +#include <rtems/score/percpu.h> + +/* + * This code uses the small-data area which is not available in the 64-bit + * PowerPC ELFv2 ABI. + */ +#ifndef __powerpc64__ + +#include "ppc_exc_asm_macros.h" + +/******************************************************/ +/* PROLOGUES */ +/******************************************************/ + + /* + * Expand prologue snippets for classic, ppc405-critical, bookE-critical + * and E500 machine-check, synchronous and asynchronous exceptions + */ + PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_std _VEC=0 _PRI=std _FLVR=std + PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_p405_crit _VEC=0 _PRI=crit _FLVR=p405_crit + PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_bookE_crit _VEC=0 _PRI=crit _FLVR=bookE_crit + PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_e500_mchk _VEC=0 _PRI=mchk _FLVR=e500_mchk + + PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_std _VEC=0 _PRI=std _FLVR=std + PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_p405_crit _VEC=0 _PRI=crit _FLVR=p405_crit + PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_bookE_crit _VEC=0 _PRI=crit _FLVR=bookE_crit + PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_e500_mchk _VEC=0 _PRI=mchk _FLVR=e500_mchk + + .global ppc_exc_min_prolog_size +ppc_exc_min_prolog_size = 4 * 4 + +/* Special prologue for 603e-style CPUs. + * + * 603e shadows GPR0..GPR3 for certain exceptions. We must switch + * that off before we can use the stack pointer. Note that this is + * ONLY safe if the shadowing is actually active -- otherwise, r1 + * is destroyed. We deliberately use r1 so problems become obvious + * if this is misused! + */ + .global ppc_exc_tgpr_clr_prolog +ppc_exc_tgpr_clr_prolog: + mfmsr r1 + rlwinm r1,r1,0,15,13 + mtmsr r1 + isync + /* FALL THRU TO 'auto' PROLOG */ + +/* Determine vector dynamically/automatically + * + * BUT: - only standard exceptions (no critical ones) + * - vector offset must be on 256 Byte boundary. + */ + .global ppc_exc_min_prolog_auto +ppc_exc_min_prolog_auto: + stwu r1, -EXCEPTION_FRAME_END(r1) + stw VECTOR_REGISTER, VECTOR_OFFSET(r1) + mflr VECTOR_REGISTER + + /* + * We store the absolute branch target address here. It will be used + * to generate the branch operation in ppc_exc_make_prologue(). + * + * We add one to request the link in the generated branch instruction. + */ + .int ppc_exc_wrap_auto + 1 + + .global ppc_exc_tgpr_clr_prolog_size +ppc_exc_tgpr_clr_prolog_size = . - ppc_exc_tgpr_clr_prolog + +/* + * Automatic vector, asynchronous exception; however, + * automatic vector calculation is less efficient than + * using an explicit vector in a minimal prolog snippet. + * The latter method is preferable since there usually + * are few asynchronous exceptions. + * + * For generic exceptions (which are the bulk) using + * the 'auto' prologue is OK since performance is not + * really an issue. + */ + .global ppc_exc_min_prolog_auto_async +ppc_exc_min_prolog_auto_async: + stw r1, ppc_exc_lock_std@sdarel(r13) + stw VECTOR_REGISTER, ppc_exc_vector_register_std@sdarel(r13) + mflr VECTOR_REGISTER + + /* + * We store the absolute branch target address here. It will be used + * to generate the branch operation in ppc_exc_make_prologue(). + * + * We add one to request the link in the generated branch instruction. + */ + .int ppc_exc_wrap_auto_async + 1 + +/******************************************************/ +/* WRAPPERS */ +/******************************************************/ + + /* Tag start and end of the wrappers. + * If exceptions are installed farther removed + * from the text area than 32M then the wrappers + * must be moved to an area that is reachable + * from where the prologues reside. Branches into + * C-code are far. + */ + + .global __ppc_exc_wrappers_start +__ppc_exc_wrappers_start = . + + /* Expand wrappers for different exception flavors */ + + /* Standard/classic powerpc */ + WRAP _FLVR=std _PRI=std _SRR0=srr0 _SRR1=srr1 _RFI=rfi + + /* ppc405 has a critical exception using srr2/srr3 */ + WRAP _FLVR=p405_crit _PRI=crit _SRR0=srr2 _SRR1=srr3 _RFI=rfci + + /* bookE has critical exception using csrr0 cssr1 */ + WRAP _FLVR=bookE_crit _PRI=crit _SRR0=csrr0 _SRR1=csrr1 _RFI=rfci + + /* e500 has machine-check exception using mcsrr0 mcssr1 */ + WRAP _FLVR=e500_mchk _PRI=mchk _SRR0=mcsrr0 _SRR1=mcsrr1 _RFI=rfmci + + /* LR holds vector, VECTOR_REGISTER holds orig. LR */ + .global ppc_exc_wrap_auto +ppc_exc_wrap_auto: + stw FRAME_REGISTER, FRAME_OFFSET(r1) + + /* Find address where we jumped from */ + mflr FRAME_REGISTER + + /* Restore LR */ + mtlr VECTOR_REGISTER + + /* Compute vector into R3 */ + rlwinm VECTOR_REGISTER, FRAME_REGISTER, 24, 26, 31 + + /* + * We're now in almost the same state as if called by + * min_prolog_std but we must skip saving FRAME_REGISTER + * since that's done already + */ + b wrap_no_save_frame_register_std + + .global ppc_exc_wrap_auto_async +ppc_exc_wrap_auto_async: + stwu r1, -EXCEPTION_FRAME_END(r1) + stw FRAME_REGISTER, FRAME_OFFSET(r1) + /* find address where we jumped from */ + mflr FRAME_REGISTER + /* restore LR */ + mtlr VECTOR_REGISTER + /* set upper bits to indicate that non-volatile + * registers should not be saved/restored. + */ + li VECTOR_REGISTER, 0xffff8000 + /* compute vector into R3 */ + rlwimi VECTOR_REGISTER, FRAME_REGISTER, 24, 26, 31 + /* we're now in almost the same state as if called by + * min_prolog_std but we must skip saving FRAME_REGISTER + * since that's done already + */ + b wrap_no_save_frame_register_std + + .global __ppc_exc_wrappers_end +__ppc_exc_wrappers_end = . + +#endif /* !__powerpc64__ */ |