summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/shared/exceptions/ppc_exc.S
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/powerpc/shared/exceptions/ppc_exc.S')
-rw-r--r--bsps/powerpc/shared/exceptions/ppc_exc.S185
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__ */