/* * (c) 1999, Eric Valette valette@crf.canon.fr * * Modified and partially rewritten by Till Straumann, 2007 * * Modified by Sebastian Huber , 2008. * * Low-level assembly code for PPC exceptions. * * This file was written with the goal to eliminate * ALL #ifdef conditionals -- please do not * reintroduce such statements. */ /* Load macro definitions */ #include #include #include /* * 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__ */