forked from Imagelibrary/rtems
186 lines
5.8 KiB
ArmAsm
186 lines
5.8 KiB
ArmAsm
/*
|
|
* (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__ */
|