Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /*
0002  * (c) 1999, Eric Valette valette@crf.canon.fr
0003  *
0004  * Modified and partially rewritten by Till Straumann, 2007
0005  *
0006  * Modified by Sebastian Huber <sebastian.huber@embedded-brains.de>, 2008.
0007  *
0008  * Low-level assembly code for PPC exceptions.
0009  *
0010  * This file was written with the goal to eliminate
0011  * ALL #ifdef <cpu_flavor> conditionals -- please do not
0012  * reintroduce such statements.
0013  */
0014 
0015 /* Load macro definitions */
0016 #include <rtems/asm.h>
0017 #include <rtems/score/percpu.h>
0018 
0019 /*
0020  * This code uses the small-data area which is not available in the 64-bit
0021  * PowerPC ELFv2 ABI.
0022  */
0023 #ifndef __powerpc64__
0024 
0025 #include "ppc_exc_asm_macros.h"
0026 
0027 /******************************************************/
0028 /*  PROLOGUES                                         */
0029 /******************************************************/
0030 
0031     /*
0032      * Expand prologue snippets for classic, ppc405-critical, bookE-critical
0033      * and E500 machine-check, synchronous and asynchronous exceptions
0034      */
0035     PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_std        _VEC=0 _PRI=std  _FLVR=std
0036     PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_p405_crit  _VEC=0 _PRI=crit _FLVR=p405_crit
0037     PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_bookE_crit _VEC=0 _PRI=crit _FLVR=bookE_crit
0038     PPC_EXC_MIN_PROLOG_SYNC _NAME=tmpl_e500_mchk  _VEC=0 _PRI=mchk _FLVR=e500_mchk
0039 
0040     PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_std        _VEC=0 _PRI=std  _FLVR=std
0041     PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_p405_crit  _VEC=0 _PRI=crit _FLVR=p405_crit
0042     PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_bookE_crit _VEC=0 _PRI=crit _FLVR=bookE_crit
0043     PPC_EXC_MIN_PROLOG_ASYNC _NAME=tmpl_e500_mchk  _VEC=0 _PRI=mchk _FLVR=e500_mchk
0044 
0045     .global ppc_exc_min_prolog_size
0046 ppc_exc_min_prolog_size      = 4 * 4
0047 
0048 /* Special prologue for 603e-style CPUs.
0049  *
0050  * 603e shadows GPR0..GPR3 for certain exceptions. We must switch
0051  * that off before we can use the stack pointer. Note that this is
0052  * ONLY safe if the shadowing is actually active -- otherwise, r1
0053  * is destroyed. We deliberately use r1 so problems become obvious
0054  * if this is misused!
0055  */
0056     .global ppc_exc_tgpr_clr_prolog
0057 ppc_exc_tgpr_clr_prolog:
0058     mfmsr   r1
0059     rlwinm  r1,r1,0,15,13
0060     mtmsr   r1
0061     isync
0062     /* FALL THRU TO 'auto' PROLOG */
0063 
0064 /* Determine vector dynamically/automatically
0065  *
0066  * BUT: - only standard exceptions (no critical ones)
0067  *      - vector offset must be on 256 Byte boundary.
0068  */
0069     .global ppc_exc_min_prolog_auto
0070 ppc_exc_min_prolog_auto:
0071     stwu    r1, -EXCEPTION_FRAME_END(r1)
0072     stw VECTOR_REGISTER, VECTOR_OFFSET(r1)
0073     mflr    VECTOR_REGISTER
0074 
0075     /*
0076      * We store the absolute branch target address here.  It will be used
0077      * to generate the branch operation in ppc_exc_make_prologue().
0078      *
0079      * We add one to request the link in the generated branch instruction.
0080      */
0081     .int    ppc_exc_wrap_auto + 1
0082 
0083     .global ppc_exc_tgpr_clr_prolog_size
0084 ppc_exc_tgpr_clr_prolog_size = . - ppc_exc_tgpr_clr_prolog
0085 
0086 /*
0087  * Automatic vector, asynchronous exception; however,
0088  * automatic vector calculation is less efficient than
0089  * using an explicit vector in a minimal prolog snippet.
0090  * The latter method is preferable since there usually
0091  * are few asynchronous exceptions.
0092  *
0093  * For generic exceptions (which are the bulk) using
0094  * the 'auto' prologue is OK since performance is not
0095  * really an issue.
0096  */
0097     .global ppc_exc_min_prolog_auto_async
0098 ppc_exc_min_prolog_auto_async:
0099     stw r1, ppc_exc_lock_std@sdarel(r13)
0100     stw VECTOR_REGISTER, ppc_exc_vector_register_std@sdarel(r13)
0101     mflr    VECTOR_REGISTER
0102 
0103     /*
0104      * We store the absolute branch target address here.  It will be used
0105      * to generate the branch operation in ppc_exc_make_prologue().
0106      *
0107      * We add one to request the link in the generated branch instruction.
0108      */
0109     .int    ppc_exc_wrap_auto_async + 1
0110 
0111 /******************************************************/
0112 /*  WRAPPERS                                          */
0113 /******************************************************/
0114 
0115     /* Tag start and end of the wrappers.
0116      * If exceptions are installed farther removed
0117      * from the text area than 32M then the wrappers
0118      * must be moved to an area that is reachable
0119      * from where the prologues reside. Branches into
0120      * C-code are far.
0121      */
0122 
0123     .global __ppc_exc_wrappers_start
0124 __ppc_exc_wrappers_start = .
0125 
0126     /* Expand wrappers for different exception flavors */
0127 
0128     /* Standard/classic powerpc */
0129     WRAP    _FLVR=std _PRI=std _SRR0=srr0 _SRR1=srr1 _RFI=rfi
0130 
0131     /* ppc405 has a critical exception using srr2/srr3 */
0132     WRAP    _FLVR=p405_crit _PRI=crit _SRR0=srr2 _SRR1=srr3 _RFI=rfci
0133 
0134     /* bookE has critical exception using csrr0 cssr1 */
0135     WRAP    _FLVR=bookE_crit _PRI=crit _SRR0=csrr0 _SRR1=csrr1 _RFI=rfci
0136 
0137     /* e500 has machine-check exception using mcsrr0 mcssr1 */
0138     WRAP    _FLVR=e500_mchk _PRI=mchk _SRR0=mcsrr0 _SRR1=mcsrr1 _RFI=rfmci
0139 
0140     /* LR holds vector, VECTOR_REGISTER holds orig. LR */
0141         .global ppc_exc_wrap_auto
0142 ppc_exc_wrap_auto:
0143     stw FRAME_REGISTER, FRAME_OFFSET(r1)
0144 
0145     /* Find address where we jumped from */
0146     mflr    FRAME_REGISTER
0147 
0148     /* Restore LR */
0149     mtlr    VECTOR_REGISTER
0150 
0151     /* Compute vector into R3 */
0152     rlwinm  VECTOR_REGISTER, FRAME_REGISTER, 24, 26, 31
0153 
0154     /*
0155      * We're now in almost the same state as if called by
0156      * min_prolog_std but we must skip saving FRAME_REGISTER
0157      * since that's done already
0158      */
0159     b   wrap_no_save_frame_register_std
0160 
0161         .global ppc_exc_wrap_auto_async
0162 ppc_exc_wrap_auto_async:
0163     stwu    r1, -EXCEPTION_FRAME_END(r1)
0164     stw FRAME_REGISTER, FRAME_OFFSET(r1)
0165     /* find address where we jumped from */
0166     mflr    FRAME_REGISTER
0167     /* restore LR     */
0168     mtlr    VECTOR_REGISTER
0169     /* set upper bits to indicate that non-volatile
0170      * registers should not be saved/restored.
0171      */
0172     li  VECTOR_REGISTER, 0xffff8000
0173     /* compute vector into R3 */
0174     rlwimi  VECTOR_REGISTER, FRAME_REGISTER, 24, 26, 31
0175     /* we're now in almost the same state as if called by
0176      * min_prolog_std but we must skip saving FRAME_REGISTER
0177      * since that's done already
0178      */
0179     b   wrap_no_save_frame_register_std
0180 
0181     .global __ppc_exc_wrappers_end
0182 __ppc_exc_wrappers_end = .
0183 
0184 #endif /* !__powerpc64__ */