summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2009-10-23 09:51:03 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2009-10-23 09:51:03 +0000
commit856cce506825d1257efafdb89ce632530c182d8b (patch)
tree591d090786d561a2237c929a23b315985232d34c
parentFix broken formating. (diff)
downloadrtems-856cce506825d1257efafdb89ce632530c182d8b.tar.bz2
add new files for exception handler
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/include/irq-config.h47
-rw-r--r--c/src/lib/libbsp/powerpc/mpc8260ads/include/irq-config.h47
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc-code-copy.c39
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_address.c77
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_categories.c297
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_global_handler.c215
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_initialize.c194
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_naked.S189
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_prologue.c127
9 files changed, 1232 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/include/irq-config.h b/c/src/lib/libbsp/powerpc/mbx8xx/include/irq-config.h
new file mode 100644
index 0000000000..da5bbbec5d
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/include/irq-config.h
@@ -0,0 +1,47 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief BSP interrupt support configuration.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H
+#define LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H
+
+#include <stdint.h>
+
+#include <bsp/irq.h>
+
+/**
+ * @addtogroup bsp_interrupt
+ *
+ * @{
+ */
+
+/**
+ * @brief Minimum vector number.
+ */
+#define BSP_INTERRUPT_VECTOR_MIN BSP_LOWEST_OFFSET
+
+/**
+ * @brief Maximum vector number.
+ */
+#define BSP_INTERRUPT_VECTOR_MAX BSP_MAX_OFFSET
+
+/** @} */
+
+#endif /* LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H */
diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/include/irq-config.h b/c/src/lib/libbsp/powerpc/mpc8260ads/include/irq-config.h
new file mode 100644
index 0000000000..da5bbbec5d
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mpc8260ads/include/irq-config.h
@@ -0,0 +1,47 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief BSP interrupt support configuration.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#ifndef LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H
+#define LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H
+
+#include <stdint.h>
+
+#include <bsp/irq.h>
+
+/**
+ * @addtogroup bsp_interrupt
+ *
+ * @{
+ */
+
+/**
+ * @brief Minimum vector number.
+ */
+#define BSP_INTERRUPT_VECTOR_MIN BSP_LOWEST_OFFSET
+
+/**
+ * @brief Maximum vector number.
+ */
+#define BSP_INTERRUPT_VECTOR_MAX BSP_MAX_OFFSET
+
+/** @} */
+
+#endif /* LIBBSP_POWERPC_MBX8XX_IRQ_CONFIG_H */
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc-code-copy.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc-code-copy.c
new file mode 100644
index 0000000000..9e327e5141
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc-code-copy.c
@@ -0,0 +1,39 @@
+/**
+ * @file
+ *
+ * @ingroup powerpc_shared
+ *
+ * @brief Code copy implementation.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <string.h>
+
+#include <rtems.h>
+
+#include <libcpu/powerpc-utility.h>
+
+void ppc_code_copy(void *dest, const void *src, size_t n)
+{
+ if (memcmp(dest, src, n) != 0) {
+ memcpy(dest, src, n);
+
+ rtems_cache_flush_multiple_data_lines(dest, n);
+ ppc_synchronize_data();
+
+ rtems_cache_invalidate_multiple_instruction_lines(dest, n);
+ ppc_synchronize_instructions();
+ }
+}
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_address.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_address.c
new file mode 100644
index 0000000000..1121afc9f4
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_address.c
@@ -0,0 +1,77 @@
+/**
+ * @file
+ *
+ * @ingroup ppc_exc
+ *
+ * @brief PowerPC Exceptions implementation.
+ */
+
+/*
+ * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * Copyright (C) 2009 embedded brains GmbH.
+ *
+ * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
+ * to support 603, 603e, 604, 604e exceptions
+ *
+ * Moved to "libcpu/powerpc/new-exceptions" and consolidated
+ * by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
+ * to be common for all PPCs with new exceptions.
+ *
+ * Derived from file "libcpu/powerpc/new-exceptions/raw_exception.c".
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+
+#include <bsp/vectors.h>
+
+bool bsp_exceptions_in_RAM = true;
+
+uint32_t ppc_exc_vector_base = 0;
+
+void *ppc_exc_vector_address(unsigned vector)
+{
+ uintptr_t vector_base = 0xfff00000;
+ uintptr_t vector_offset = vector << 8;
+
+ if (ppc_cpu_has_altivec()) {
+ if (vector == ASM_60X_VEC_VECTOR) {
+ vector_offset = ASM_60X_VEC_VECTOR_OFFSET;
+ }
+ }
+
+ if (ppc_cpu_is(PPC_405)) {
+ switch (vector) {
+ case ASM_BOOKE_FIT_VECTOR:
+ vector_offset = ASM_PPC405_FIT_VECTOR_OFFSET;
+ break;
+ case ASM_BOOKE_WDOG_VECTOR:
+ vector_offset = ASM_PPC405_WDOG_VECTOR_OFFSET;
+ break;
+ case ASM_TRACE_VECTOR:
+ vector_offset = ASM_PPC405_TRACE_VECTOR_OFFSET;
+ break;
+ case ASM_PPC405_APU_UNAVAIL_VECTOR:
+ vector_offset = ASM_60X_VEC_VECTOR_OFFSET;
+ default:
+ break;
+ }
+ }
+
+ if (ppc_cpu_has_ivpr_and_ivor()) {
+ vector_offset >>= 4;
+ }
+
+ if (bsp_exceptions_in_RAM) {
+ vector_base = ppc_exc_vector_base;
+ }
+
+ return (void *) (vector_base + vector_offset);
+}
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_categories.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_categories.c
new file mode 100644
index 0000000000..2856957639
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_categories.c
@@ -0,0 +1,297 @@
+/**
+ * @file
+ *
+ * @ingroup ppc_exc
+ *
+ * @brief PowerPC Exceptions implementation.
+ */
+
+/*
+ * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * Copyright (C) 2009 embedded brains GmbH.
+ *
+ * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
+ * to support 603, 603e, 604, 604e exceptions
+ *
+ * Moved to "libcpu/powerpc/new-exceptions" and consolidated
+ * by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
+ * to be common for all PPCs with new exceptions.
+ *
+ * Derived from file "libcpu/powerpc/new-exceptions/raw_exception.c".
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bsp/vectors.h>
+
+#define PPC_BASIC_VECS \
+ [ASM_RESET_VECTOR] = PPC_EXC_CLASSIC, \
+ [ASM_MACH_VECTOR] = PPC_EXC_CLASSIC, \
+ [ASM_PROT_VECTOR] = PPC_EXC_CLASSIC, \
+ [ASM_ISI_VECTOR] = PPC_EXC_CLASSIC, \
+ [ASM_EXT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, \
+ [ASM_ALIGN_VECTOR] = PPC_EXC_CLASSIC, \
+ [ASM_PROG_VECTOR] = PPC_EXC_CLASSIC, \
+ [ASM_FLOAT_VECTOR] = PPC_EXC_CLASSIC, \
+ [ASM_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, \
+ [ASM_SYS_VECTOR] = PPC_EXC_CLASSIC, \
+ [ASM_TRACE_VECTOR] = PPC_EXC_CLASSIC
+
+static const ppc_exc_categories ppc_405_category_table = {
+ [ASM_BOOKE_CRIT_VECTOR] = PPC_EXC_405_CRITICAL | PPC_EXC_ASYNC,
+ [ASM_MACH_VECTOR] = PPC_EXC_405_CRITICAL,
+ [ASM_PROT_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_ISI_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_EXT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_ALIGN_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_PROG_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_FLOAT_VECTOR] = PPC_EXC_CLASSIC,
+
+ [ASM_PPC405_APU_UNAVAIL_VECTOR] = PPC_EXC_CLASSIC,
+
+ [ASM_SYS_VECTOR] = PPC_EXC_CLASSIC,
+
+ [ASM_BOOKE_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_BOOKE_FIT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_BOOKE_WDOG_VECTOR] = PPC_EXC_405_CRITICAL | PPC_EXC_ASYNC,
+ [ASM_BOOKE_DTLBMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_BOOKE_ITLBMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_TRACE_VECTOR] = PPC_EXC_405_CRITICAL,
+};
+
+static const ppc_exc_categories mpc_5xx_category_table = {
+ [ASM_RESET_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_MACH_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_EXT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_ALIGN_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_PROG_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_FLOAT_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_SYS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_TRACE_VECTOR] = PPC_EXC_CLASSIC,
+
+ [ASM_5XX_FLOATASSIST_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_5XX_SOFTEMUL_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_5XX_IPROT_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_5XX_DPROT_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_5XX_DBREAK_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_5XX_IBREAK_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_5XX_MEBREAK_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_5XX_NMEBREAK_VECTOR] = PPC_EXC_CLASSIC,
+};
+
+static const ppc_exc_categories mpc_603_category_table = {
+ PPC_BASIC_VECS,
+
+ [ASM_60X_SYSMGMT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_60X_IMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_DLMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_DSMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_ADDR_VECTOR] = PPC_EXC_CLASSIC,
+};
+
+static const ppc_exc_categories mpc_604_category_table = {
+ PPC_BASIC_VECS,
+
+ [ASM_60X_PERFMON_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_SYSMGMT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_60X_ADDR_VECTOR] = PPC_EXC_CLASSIC,
+};
+
+static const ppc_exc_categories mpc_604_altivec_category_table = {
+ PPC_BASIC_VECS,
+
+ [ASM_60X_PERFMON_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_SYSMGMT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_60X_ADDR_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_VEC_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_VEC_ASSIST_VECTOR] = PPC_EXC_CLASSIC,
+};
+
+static const ppc_exc_categories mpc_750_category_table = {
+ PPC_BASIC_VECS,
+
+ [ASM_60X_SYSMGMT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_60X_ADDR_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_ITM_VECTOR] = PPC_EXC_CLASSIC,
+};
+
+static const ppc_exc_categories mpc_750_altivec_category_table = {
+ PPC_BASIC_VECS,
+
+ [ASM_60X_SYSMGMT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_60X_ADDR_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_ITM_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_VEC_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_VEC_ASSIST_VECTOR] = PPC_EXC_CLASSIC,
+};
+
+static const ppc_exc_categories mpc_860_category_table = {
+ PPC_BASIC_VECS,
+
+ [ASM_8XX_FLOATASSIST_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_8XX_SOFTEMUL_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_8XX_ITLBMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_8XX_DTLBMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_8XX_ITLBERROR_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_8XX_DTLBERROR_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_8XX_DBREAK_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_8XX_IBREAK_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_8XX_PERIFBREAK_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_8XX_DEVPORT_VECTOR] = PPC_EXC_CLASSIC,
+};
+
+static const ppc_exc_categories e200_category_table = {
+ [ASM_MACH_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC,
+ [ASM_PROT_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_ISI_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_EXT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_ALIGN_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_PROG_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_FLOAT_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_SYS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_BOOKE_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_BOOKE_FIT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_BOOKE_WDOG_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC,
+ [ASM_BOOKE_ITLBMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_BOOKE_DTLBMISS_VECTOR] = PPC_EXC_CLASSIC,
+
+ /* FIXME: Depending on HDI0 [DAPUEN] this is a critical or debug exception */
+ [ASM_TRACE_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_BOOKE_CRITICAL,
+
+ [ASM_E200_SPE_UNAVAILABLE_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_E200_SPE_DATA_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_E200_SPE_ROUND_VECTOR] = PPC_EXC_CLASSIC,
+};
+
+static const ppc_exc_categories e300_category_table = {
+ [ASM_RESET_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_MACH_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_PROT_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_ISI_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_EXT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_ALIGN_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_PROG_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_FLOAT_VECTOR] = PPC_EXC_NAKED,
+ [ASM_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_SYS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_TRACE_VECTOR] = PPC_EXC_CLASSIC,
+
+ [ASM_E300_CRIT_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC,
+ [ASM_E300_PERFMON_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_E300_IMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_E300_DLMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_E300_DSMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_E300_ADDR_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_E300_SYSMGMT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+};
+
+static const ppc_exc_categories e500_category_table = {
+ [ASM_MACH_VECTOR] = PPC_EXC_E500_MACHCHK,
+
+ [ASM_BOOKE_CRIT_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC,
+ [ASM_BOOKE_WDOG_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC,
+ [ASM_TRACE_VECTOR] = PPC_EXC_BOOKE_CRITICAL,
+
+ [ASM_EXT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_BOOKE_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_BOOKE_FIT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+
+ [ASM_PROT_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_ISI_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_ALIGN_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_PROG_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_FLOAT_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_SYS_VECTOR] = PPC_EXC_CLASSIC,
+ [ /* APU unavailable */ 0x0b] = PPC_EXC_CLASSIC,
+
+ [ASM_60X_DLMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_DSMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_VEC_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_PERFMON_VECTOR] = PPC_EXC_CLASSIC,
+
+ [ /* emb FP data */ 0x15] = PPC_EXC_CLASSIC,
+ [ /* emb FP round */ 0x16] = PPC_EXC_CLASSIC,
+};
+
+static const ppc_exc_categories psim_category_table = {
+ PPC_BASIC_VECS,
+
+ [ASM_60X_SYSMGMT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
+ [ASM_60X_IMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_DLMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_DSMISS_VECTOR] = PPC_EXC_CLASSIC,
+ [ASM_60X_ADDR_VECTOR] = PPC_EXC_CLASSIC,
+};
+
+const ppc_exc_categories *ppc_exc_categories_for_cpu(ppc_cpu_id_t cpu)
+{
+ if (ppc_cpu_has_altivec()) {
+ switch (cpu) {
+ case PPC_7400:
+ return &mpc_750_altivec_category_table;
+ case PPC_7455:
+ case PPC_7457:
+ return &mpc_604_altivec_category_table;
+ default:
+ break;
+ }
+ }
+
+ switch (cpu) {
+ case PPC_7400:
+ case PPC_750:
+ return &mpc_750_category_table;
+ case PPC_7455:
+ case PPC_7457:
+ case PPC_604:
+ case PPC_604e:
+ case PPC_604r:
+ return &mpc_604_category_table;
+ case PPC_603:
+ case PPC_603e:
+ case PPC_603le:
+ case PPC_603ev:
+ /* case PPC_8240: same value as 8260 */
+ case PPC_8260:
+ case PPC_8245:
+ return &mpc_603_category_table;
+ case PPC_e300c1:
+ case PPC_e300c2:
+ case PPC_e300c3:
+ return &e300_category_table;
+ case PPC_PSIM:
+ return &psim_category_table;
+ case PPC_8540:
+ return &e500_category_table;
+ case PPC_e200z6:
+ return &e200_category_table;
+ case PPC_5XX:
+ return &mpc_5xx_category_table;
+ case PPC_860:
+ return &mpc_860_category_table;
+ case PPC_405:
+ case PPC_405GP:
+ case PPC_405EX:
+ return &ppc_405_category_table;
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+ppc_exc_category ppc_exc_category_for_vector(const ppc_exc_categories *categories, unsigned vector)
+{
+ if (vector <= LAST_VALID_EXC) {
+ return (*categories) [vector];
+ } else {
+ return PPC_EXC_INVALID;
+ }
+}
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_global_handler.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_global_handler.c
new file mode 100644
index 0000000000..116199332c
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_global_handler.c
@@ -0,0 +1,215 @@
+/**
+ * @file
+ *
+ * @ingroup ppc_exc
+ *
+ * @brief PowerPC Exceptions implementation.
+ */
+
+/*
+ * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * Derived from file "libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c".
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bsp/vectors.h>
+
+exception_handler_t globalExceptHdl = C_exception_handler;
+
+/* T. Straumann: provide a stack trace
+ * <strauman@slac.stanford.edu>, 6/26/2001
+ */
+typedef struct LRFrameRec_ {
+ struct LRFrameRec_ *frameLink;
+ unsigned long *lr;
+} LRFrameRec, *LRFrame;
+
+#define STACK_CLAMP 50 /* in case we have a corrupted bottom */
+
+static uint32_t ppc_exc_get_DAR_dflt(void)
+{
+ if (ppc_cpu_is_60x())
+ return PPC_SPECIAL_PURPOSE_REGISTER(DAR);
+ else
+ switch (ppc_cpu_is_bookE()) {
+ default:
+ break;
+ case PPC_BOOKE_STD:
+ case PPC_BOOKE_E500:
+ return PPC_SPECIAL_PURPOSE_REGISTER(DEAR_BOOKE);
+ case PPC_BOOKE_405:
+ return PPC_SPECIAL_PURPOSE_REGISTER(DEAR_405);
+ }
+ return 0xdeadbeef;
+}
+
+uint32_t (*ppc_exc_get_DAR)(void) = ppc_exc_get_DAR_dflt;
+
+void BSP_printStackTrace(BSP_Exception_frame *excPtr)
+{
+ LRFrame f;
+ int i;
+ LRFrame sp;
+ void *lr;
+
+ printk("Stack Trace: \n ");
+ if (excPtr) {
+ printk("IP: 0x%08x, ", excPtr->EXC_SRR0);
+ sp = (LRFrame) excPtr->GPR1;
+ lr = (void *) excPtr->EXC_LR;
+ } else {
+ /* there's no macro for this */
+ __asm__ __volatile__("mr %0, 1":"=r"(sp));
+ lr = (LRFrame) ppc_link_register();
+ }
+ printk("LR: 0x%08x\n", lr);
+ for (f = (LRFrame) sp, i = 0; f->frameLink && i < STACK_CLAMP; f = f->frameLink) {
+ printk("--^ 0x%08x", (long) (f->frameLink->lr));
+ if (!(++i % 5))
+ printk("\n");
+ }
+ if (i >= STACK_CLAMP) {
+ printk("Too many stack frames (stack possibly corrupted), giving up...\n");
+ } else {
+ if (i % 5)
+ printk("\n");
+ }
+}
+
+void C_exception_handler(BSP_Exception_frame *excPtr)
+{
+ static int nest = 0;
+
+ int recoverable = 0;
+ rtems_id id = 0;
+ int synch;
+ unsigned n;
+ rtems_status_code sc;
+
+ /* Catch recursion */
+ nest++;
+
+ if (nest > 2) {
+ /* maybe printk() or dereferencing excPtr caused an exception;
+ * die silently...
+ */
+ while (1);
+ }
+
+ synch = (int) excPtr->_EXC_number >= 0;
+ n = excPtr->_EXC_number & 0x7fff;
+
+ printk("Exception handler called for exception %d (0x%x)\n", n, n);
+ printk("\t Next PC or Address of fault = %08x\n", excPtr->EXC_SRR0);
+ printk("\t Saved MSR = %08x\n", excPtr->EXC_SRR1);
+
+ if (nest > 1) {
+ printk("Recursion in the exception handler detected; I'll spin now...\n");
+ while (1);
+ }
+
+ /* Try to find out more about the context where this happened */
+ printk("\t Context: ");
+ if (rtems_interrupt_is_in_progress()) {
+ printk("ISR");
+ } else if (!_Thread_Executing) {
+ printk("Initialization (_Thread_Executing not available yet)");
+ } else {
+ if (RTEMS_SUCCESSFUL != (sc = rtems_task_ident(RTEMS_SELF, RTEMS_LOCAL, &id))) {
+ printk("Unable to determine faulting task; rtems_task_ident() returned %u", sc);
+ id = 0;
+ } else {
+ printk("Task ID 0x%08x", id);
+ }
+ }
+ printk("\n");
+
+ /* Dump registers */
+
+ printk("\t R0 = %08x", excPtr->GPR0);
+ if (synch) {
+ printk(" R1 = %08x", excPtr->GPR1);
+ printk(" R2 = %08x", excPtr->GPR2);
+ } else {
+ printk(" ");
+ printk(" ");
+ }
+ printk(" R3 = %08x\n", excPtr->GPR3);
+ printk("\t R4 = %08x", excPtr->GPR4);
+ printk(" R5 = %08x", excPtr->GPR5);
+ printk(" R6 = %08x", excPtr->GPR6);
+ printk(" R7 = %08x\n", excPtr->GPR7);
+ printk("\t R8 = %08x", excPtr->GPR8);
+ printk(" R9 = %08x", excPtr->GPR9);
+ printk(" R10 = %08x", excPtr->GPR10);
+ printk(" R11 = %08x\n", excPtr->GPR11);
+ printk("\t R12 = %08x", excPtr->GPR12);
+ if (synch) {
+ printk(" R13 = %08x", excPtr->GPR13);
+ printk(" R14 = %08x", excPtr->GPR14);
+ printk(" R15 = %08x\n", excPtr->GPR15);
+ printk("\t R16 = %08x", excPtr->GPR16);
+ printk(" R17 = %08x", excPtr->GPR17);
+ printk(" R18 = %08x", excPtr->GPR18);
+ printk(" R19 = %08x\n", excPtr->GPR19);
+ printk("\t R20 = %08x", excPtr->GPR20);
+ printk(" R21 = %08x", excPtr->GPR21);
+ printk(" R22 = %08x", excPtr->GPR22);
+ printk(" R23 = %08x\n", excPtr->GPR23);
+ printk("\t R24 = %08x", excPtr->GPR24);
+ printk(" R25 = %08x", excPtr->GPR25);
+ printk(" R26 = %08x", excPtr->GPR26);
+ printk(" R27 = %08x\n", excPtr->GPR27);
+ printk("\t R28 = %08x", excPtr->GPR28);
+ printk(" R29 = %08x", excPtr->GPR29);
+ printk(" R30 = %08x", excPtr->GPR30);
+ printk(" R31 = %08x\n", excPtr->GPR31);
+ } else {
+ printk("\n");
+ }
+ printk("\t CR = %08x\n", excPtr->EXC_CR);
+ printk("\t CTR = %08x\n", excPtr->EXC_CTR);
+ printk("\t XER = %08x\n", excPtr->EXC_XER);
+ printk("\t LR = %08x\n", excPtr->EXC_LR);
+
+ /* Would be great to print DAR but unfortunately,
+ * that is not portable across different CPUs.
+ * AFAIK on classic PPC DAR is SPR 19, on the
+ * 405 we have DEAR = SPR 0x3d5 and booE says
+ * DEAR = SPR 61 :-(
+ */
+ if (ppc_exc_get_DAR) {
+ printk("\t DAR = %08x\n", ppc_exc_get_DAR());
+ }
+
+ BSP_printStackTrace(excPtr);
+
+ if (excPtr->_EXC_number == ASM_DEC_VECTOR)
+ recoverable = 1;
+ if (excPtr->_EXC_number == ASM_SYS_VECTOR)
+#ifdef TEST_RAW_EXCEPTION_CODE
+ recoverable = 1;
+#else
+ recoverable = 0;
+#endif
+ if (!recoverable) {
+ if (id) {
+ printk("Suspending faulting task (0x%08x)\n", id);
+ /* Unnest here because rtems_task_suspend() never returns */
+ nest--;
+ rtems_task_suspend(id);
+ } else {
+ printk("unrecoverable exception!!! Push reset button\n");
+ while (1);
+ }
+ } else {
+ nest--;
+ }
+}
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_initialize.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_initialize.c
new file mode 100644
index 0000000000..5d2de9dc3e
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_initialize.c
@@ -0,0 +1,194 @@
+/**
+ * @file
+ *
+ * @ingroup ppc_exc
+ *
+ * @brief PowerPC Exceptions implementation.
+ */
+
+/*
+ * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * Copyright (C) 2007 Till Straumann <strauman@slac.stanford.edu>
+ *
+ * Copyright (C) 2009 embedded brains GmbH.
+ *
+ * Derived from file "libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c".
+ * Derived from file "libcpu/powerpc/new-exceptions/e500_raw_exc_init.c".
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+
+#include <bsp/vectors.h>
+
+uint32_t ppc_exc_cache_wb_check = 1;
+
+#define MTIVPR(prefix) asm volatile ("mtivpr %0" : : "r" (prefix))
+#define MTIVOR(x, vec) asm volatile ("mtivor"#x" %0" : : "r" (vec))
+
+static void ppc_exc_initialize_e500(void)
+{
+ /* Interupt vector prefix register */
+ MTIVPR(ppc_exc_vector_base);
+
+ /* Interupt vector offset register */
+ MTIVOR(0, ppc_exc_vector_address(ASM_BOOKE_CRIT_VECTOR)); /* Critical input not (yet) supported; use reset vector */
+ MTIVOR(1, ppc_exc_vector_address(ASM_MACH_VECTOR));
+ MTIVOR(2, ppc_exc_vector_address(ASM_PROT_VECTOR));
+ MTIVOR(3, ppc_exc_vector_address(ASM_ISI_VECTOR));
+ MTIVOR(4, ppc_exc_vector_address(ASM_EXT_VECTOR));
+ MTIVOR(5, ppc_exc_vector_address(ASM_ALIGN_VECTOR));
+ MTIVOR(6, ppc_exc_vector_address(ASM_PROG_VECTOR));
+ MTIVOR(7, ppc_exc_vector_address(ASM_FLOAT_VECTOR));
+ MTIVOR(8, ppc_exc_vector_address(ASM_SYS_VECTOR));
+ MTIVOR(9, ppc_exc_vector_address(0x0b));
+ MTIVOR(10, ppc_exc_vector_address(ASM_BOOKE_DEC_VECTOR));
+ MTIVOR(11, ppc_exc_vector_address(ASM_BOOKE_FIT_VECTOR));
+ MTIVOR(12, ppc_exc_vector_address(ASM_BOOKE_WDOG_VECTOR));
+ MTIVOR(13, ppc_exc_vector_address(ASM_60X_DSMISS_VECTOR));
+ MTIVOR(14, ppc_exc_vector_address(ASM_60X_DLMISS_VECTOR));
+ MTIVOR(15, ppc_exc_vector_address(ASM_TRACE_VECTOR));
+ MTIVOR(32, ppc_exc_vector_address(ASM_60X_VEC_VECTOR));
+ MTIVOR(33, ppc_exc_vector_address(0x16));
+ MTIVOR(34, ppc_exc_vector_address(0x15));
+ MTIVOR(35, ppc_exc_vector_address(ASM_60X_PERFMON_VECTOR));
+}
+
+static void ppc_exc_initialize_e200(void)
+{
+ /* Interupt vector prefix register */
+ MTIVPR(ppc_exc_vector_base);
+
+ /* Interupt vector offset register */
+ MTIVOR(0, 0); /* Critical input */
+ MTIVOR(1, ppc_exc_vector_address( ASM_MACH_VECTOR));
+ MTIVOR(2, ppc_exc_vector_address( ASM_PROT_VECTOR));
+ MTIVOR(3, ppc_exc_vector_address( ASM_ISI_VECTOR));
+ MTIVOR(4, ppc_exc_vector_address( ASM_EXT_VECTOR));
+ MTIVOR(5, ppc_exc_vector_address( ASM_ALIGN_VECTOR));
+ MTIVOR(6, ppc_exc_vector_address( ASM_PROG_VECTOR));
+ MTIVOR(7, ppc_exc_vector_address( ASM_FLOAT_VECTOR));
+ MTIVOR(8, ppc_exc_vector_address( ASM_SYS_VECTOR));
+ MTIVOR(9, 0); /* APU unavailable */
+ MTIVOR(10, ppc_exc_vector_address( ASM_BOOKE_DEC_VECTOR));
+ MTIVOR(11, ppc_exc_vector_address( ASM_BOOKE_FIT_VECTOR));
+ MTIVOR(12, ppc_exc_vector_address( ASM_BOOKE_WDOG_VECTOR));
+ MTIVOR(13, ppc_exc_vector_address( ASM_BOOKE_ITLBMISS_VECTOR));
+ MTIVOR(14, ppc_exc_vector_address( ASM_BOOKE_DTLBMISS_VECTOR));
+ MTIVOR(15, ppc_exc_vector_address( ASM_TRACE_VECTOR));
+ MTIVOR(32, ppc_exc_vector_address( ASM_E200_SPE_UNAVAILABLE_VECTOR));
+ MTIVOR(33, ppc_exc_vector_address( ASM_E200_SPE_DATA_VECTOR));
+ MTIVOR(34, ppc_exc_vector_address( ASM_E200_SPE_ROUND_VECTOR));
+}
+
+rtems_status_code ppc_exc_initialize(
+ uint32_t interrupt_disable_mask,
+ uintptr_t interrupt_stack_begin,
+ uintptr_t interrupt_stack_size
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ const ppc_exc_categories *const categories = ppc_exc_current_categories();
+ uintptr_t const interrupt_stack_end = interrupt_stack_begin + interrupt_stack_size;
+ uintptr_t interrupt_stack_pointer = interrupt_stack_end - PPC_MINIMUM_STACK_FRAME_SIZE;
+ unsigned vector = 0;
+ uint32_t sda_base = 0;
+ uint32_t r13 = 0;
+
+ if (categories == NULL) {
+ return RTEMS_NOT_IMPLEMENTED;
+ }
+
+ /* Assembly code needs SDA_BASE in r13 (SVR4 or EABI). Make sure
+ * early init code put it there.
+ */
+ asm volatile (
+ "lis %0, _SDA_BASE_@h\n"
+ "ori %0, %0, _SDA_BASE_@l\n"
+ "mr %1, 13\n"
+ : "=r" (sda_base), "=r"(r13)
+ );
+
+ if (sda_base != r13) {
+ return RTEMS_NOT_CONFIGURED;
+ }
+
+ /* Ensure proper interrupt stack alignment */
+ interrupt_stack_pointer &= ~((uint32_t) CPU_STACK_ALIGNMENT - 1);
+
+ /* Tag interrupt stack bottom */
+ *(uint32_t *) interrupt_stack_pointer = 0;
+
+ /* Move interrupt stack values to special purpose registers */
+ PPC_SET_SPECIAL_PURPOSE_REGISTER(SPRG1, interrupt_stack_pointer);
+ PPC_SET_SPECIAL_PURPOSE_REGISTER(SPRG2, interrupt_stack_begin);
+
+ ppc_interrupt_set_disable_mask(interrupt_disable_mask);
+
+ /* Use current MMU / RI settings when running C exception handlers */
+ ppc_exc_msr_bits = ppc_machine_state_register() & (MSR_DR | MSR_IR | MSR_RI);
+
+ if (ppc_cpu_is(PPC_e200z6)) {
+ ppc_exc_initialize_e200();
+ } else if (ppc_cpu_is_bookE() == PPC_BOOKE_STD || ppc_cpu_is_bookE() == PPC_BOOKE_E500) {
+ ppc_exc_initialize_e500();
+ }
+
+ for (vector = 0; vector <= LAST_VALID_EXC; ++vector) {
+ ppc_exc_category category = ppc_exc_category_for_vector(categories, vector);
+
+ if (category != PPC_EXC_INVALID) {
+ void *const vector_address = ppc_exc_vector_address(vector);
+ uint32_t prologue [16];
+ size_t prologue_size = sizeof(prologue);
+
+ sc = ppc_exc_make_prologue(vector, category, prologue, &prologue_size);
+ if (sc != RTEMS_SUCCESSFUL) {
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ ppc_code_copy(vector_address, prologue, prologue_size);
+ }
+ }
+
+ /* If we are on a classic PPC with MSR_DR enabled then
+ * assert that the mapping for at least this task's
+ * stack is write-back-caching enabled (see README/CAVEATS)
+ * Do this only if the cache is physically enabled.
+ * Since it is not easy to figure that out in a
+ * generic way we need help from the BSP: BSPs
+ * which run entirely w/o the cache may set
+ * ppc_exc_cache_wb_check to zero prior to calling
+ * this routine.
+ *
+ * We run this check only after exception handling is
+ * initialized so that we have some chance to get
+ * information printed if it fails.
+ *
+ * Note that it is unsafe to ignore this issue; if
+ * the check fails, do NOT disable it unless caches
+ * are always physically disabled.
+ */
+ if (ppc_exc_cache_wb_check && (MSR_DR & ppc_exc_msr_bits)) {
+ /* The size of 63 assumes cache lines are at most 32 bytes */
+ uint8_t dummy[63];
+ uintptr_t p = (uintptr_t) dummy;
+ /* If the dcbz instruction raises an alignment exception
+ * then the stack is mapped as write-thru or caching-disabled.
+ * The low-level code is not capable of dealing with this
+ * ATM.
+ */
+ p = (p + 31U) & ~31U;
+ asm volatile ("dcbz 0, %0"::"b" (p));
+ /* If we make it thru here then things seem to be OK */
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_naked.S b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_naked.S
new file mode 100644
index 0000000000..1c4a3b8462
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_naked.S
@@ -0,0 +1,189 @@
+/**
+ * @file
+ *
+ * @ingroup ppc_exc
+ *
+ * @brief PowerPC Exceptions implementation.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include "ppc_exc_asm_macros.h"
+
+ .global ppc_exc_min_prolog_tmpl_naked
+
+ppc_exc_min_prolog_tmpl_naked:
+
+ stwu r1, -EXCEPTION_FRAME_END(r1)
+ stw VECTOR_REGISTER, VECTOR_OFFSET(r1)
+ li VECTOR_REGISTER, 0
+ ba wrap_naked
+
+wrap_naked:
+
+ /* Save scratch registers */
+ stw SCRATCH_REGISTER_0, SCRATCH_REGISTER_0_OFFSET(r1)
+ stw SCRATCH_REGISTER_1, SCRATCH_REGISTER_1_OFFSET(r1)
+ stw SCRATCH_REGISTER_2, SCRATCH_REGISTER_2_OFFSET(r1)
+
+ /* Save volatile registers */
+ stw r0, GPR0_OFFSET(r1)
+ stw r3, GPR3_OFFSET(r1)
+ stw r8, GPR8_OFFSET(r1)
+ stw r9, GPR9_OFFSET(r1)
+ stw r10, GPR10_OFFSET(r1)
+ stw r11, GPR11_OFFSET(r1)
+ stw r12, GPR12_OFFSET(r1)
+
+ /* Save CR */
+ mfcr SCRATCH_REGISTER_0
+ stw SCRATCH_REGISTER_0, EXC_CR_OFFSET(r1)
+
+ /* Save SRR0 */
+ mfspr SCRATCH_REGISTER_0, srr0
+ stw SCRATCH_REGISTER_0, SRR0_FRAME_OFFSET(r1)
+
+ /* Save SRR1 */
+ mfspr SCRATCH_REGISTER_0, srr1
+ stw SCRATCH_REGISTER_0, SRR1_FRAME_OFFSET(r1)
+
+ /* Save CTR */
+ mfctr SCRATCH_REGISTER_0
+ stw SCRATCH_REGISTER_0, EXC_CTR_OFFSET(r1)
+
+ /* Save XER */
+ mfxer SCRATCH_REGISTER_0
+ stw SCRATCH_REGISTER_0, EXC_XER_OFFSET(r1)
+
+ /* Save LR */
+ mflr SCRATCH_REGISTER_0
+ stw SCRATCH_REGISTER_0, EXC_LR_OFFSET(r1)
+
+ /* Load MSR bit mask */
+ lwz SCRATCH_REGISTER_0, ppc_exc_msr_bits@sdarel(r13)
+
+ /*
+ * Change the MSR if necessary (MMU, RI), remember decision in
+ * non-volatile CR_MSR.
+ */
+ cmpwi CR_MSR, SCRATCH_REGISTER_0, 0
+ bne CR_MSR, wrap_change_msr_naked
+
+wrap_change_msr_done_naked:
+
+ /*
+ * Call high level exception handler
+ */
+
+ /*
+ * Get the handler table index from the vector number. We have to
+ * discard the exception type. Take only the least significant five
+ * bits (= LAST_VALID_EXC + 1) from the vector register. Multiply by
+ * four (= size of function pointer).
+ */
+ rlwinm SCRATCH_REGISTER_1, VECTOR_REGISTER, 2, 25, 29
+
+ /* Load handler table address */
+ LA SCRATCH_REGISTER_0, ppc_exc_handler_table
+
+ /* Load handler address */
+ lwzx SCRATCH_REGISTER_0, SCRATCH_REGISTER_0, SCRATCH_REGISTER_1
+
+ /*
+ * First parameter = exception frame pointer + FRAME_LINK_SPACE
+ *
+ * We add FRAME_LINK_SPACE to the frame pointer because the high level
+ * handler expects a BSP_Exception_frame structure.
+ */
+ addi r3, r1, FRAME_LINK_SPACE
+
+ /*
+ * Second parameter = vector number (r4 is the VECTOR_REGISTER)
+ *
+ * Discard the exception type and store the vector number
+ * in the vector register. Take only the least significant
+ * five bits (= LAST_VALID_EXC + 1).
+ */
+ rlwinm VECTOR_REGISTER, VECTOR_REGISTER, 0, 27, 31
+
+ /* Call handler */
+ mtctr SCRATCH_REGISTER_0
+ bctrl
+
+ /* Restore MSR? */
+ bne CR_MSR, wrap_restore_msr_naked
+
+wrap_restore_msr_done_naked:
+
+ /* Restore XER and CTR */
+ lwz SCRATCH_REGISTER_0, EXC_XER_OFFSET(r1)
+ lwz SCRATCH_REGISTER_1, EXC_CTR_OFFSET(r1)
+ mtxer SCRATCH_REGISTER_0
+ mtctr SCRATCH_REGISTER_1
+
+ /* Restore CR and LR */
+ lwz SCRATCH_REGISTER_0, EXC_CR_OFFSET(r1)
+ lwz SCRATCH_REGISTER_1, EXC_LR_OFFSET(r1)
+ mtcr SCRATCH_REGISTER_0
+ mtlr SCRATCH_REGISTER_1
+
+ /* Restore volatile registers */
+ lwz r0, GPR0_OFFSET(r1)
+ lwz r3, GPR3_OFFSET(r1)
+ lwz r8, GPR8_OFFSET(r1)
+ lwz r9, GPR9_OFFSET(r1)
+ lwz r10, GPR10_OFFSET(r1)
+ lwz r11, GPR11_OFFSET(r1)
+ lwz r12, GPR12_OFFSET(r1)
+
+ /* Restore vector register */
+ lwz VECTOR_REGISTER, VECTOR_OFFSET(r1)
+
+ /* Restore scratch registers and SRRs */
+ lwz SCRATCH_REGISTER_0, SRR0_FRAME_OFFSET(r1)
+ lwz SCRATCH_REGISTER_1, SRR1_FRAME_OFFSET(r1)
+ lwz SCRATCH_REGISTER_2, SCRATCH_REGISTER_2_OFFSET(r1)
+ mtspr srr0, SCRATCH_REGISTER_0
+ lwz SCRATCH_REGISTER_0, SCRATCH_REGISTER_0_OFFSET(r1)
+ mtspr srr1, SCRATCH_REGISTER_1
+ lwz SCRATCH_REGISTER_1, SCRATCH_REGISTER_1_OFFSET(r1)
+
+ /*
+ * We restore r1 from the frame rather than just popping (adding to
+ * current r1) since the exception handler might have done strange
+ * things (e.g. a debugger moving and relocating the stack).
+ */
+ lwz r1, 0(r1)
+
+ /* Return */
+ rfi
+
+wrap_change_msr_naked:
+
+ mfmsr SCRATCH_REGISTER_1
+ or SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, SCRATCH_REGISTER_0
+ mtmsr SCRATCH_REGISTER_1
+ sync
+ isync
+ b wrap_change_msr_done_naked
+
+wrap_restore_msr_naked:
+
+ lwz SCRATCH_REGISTER_0, ppc_exc_msr_bits@sdarel(r13)
+ mfmsr SCRATCH_REGISTER_1
+ andc SCRATCH_REGISTER_1, SCRATCH_REGISTER_1, SCRATCH_REGISTER_0
+ mtmsr SCRATCH_REGISTER_1
+ sync
+ isync
+ b wrap_restore_msr_done_naked
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_prologue.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_prologue.c
new file mode 100644
index 0000000000..b259589aa6
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_prologue.c
@@ -0,0 +1,127 @@
+/**
+ * @file
+ *
+ * @ingroup ppc_exc
+ *
+ * @brief PowerPC Exceptions implementation.
+ */
+
+/*
+ * Copyright (C) 2007 Till Straumann <strauman@slac.stanford.edu>
+ *
+ * Copyright (C) 2009 embedded brains GmbH.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <string.h>
+
+#include <bsp/vectors.h>
+
+/* Offset into minimal prolog where vector number is hardcoded */
+#define PPC_EXC_PROLOG_VEC_OFFSET 2
+
+/* Symbols are defined by the linker */
+extern const char ppc_exc_min_prolog_size [];
+extern const char ppc_exc_tgpr_clr_prolog_size [];
+
+/* Special prologue for handling register shadowing on 603-style CPUs */
+extern const uint32_t ppc_exc_tgpr_clr_prolog [];
+
+/*
+ * Classic prologue which determines the vector dynamically from the offset
+ * address. This must only be used for classic, synchronous exceptions with a
+ * vector offset aligned on a 256-byte boundary.
+ */
+extern const uint32_t ppc_exc_min_prolog_auto [];
+
+extern const uint32_t ppc_exc_min_prolog_auto_packed [];
+
+/* Minimal prologue templates */
+extern const uint32_t ppc_exc_min_prolog_async_tmpl_std [];
+extern const uint32_t ppc_exc_min_prolog_sync_tmpl_std [];
+extern const uint32_t ppc_exc_min_prolog_async_tmpl_p405_crit [];
+extern const uint32_t ppc_exc_min_prolog_sync_tmpl_p405_crit [];
+extern const uint32_t ppc_exc_min_prolog_async_tmpl_bookE_crit [];
+extern const uint32_t ppc_exc_min_prolog_sync_tmpl_bookE_crit [];
+extern const uint32_t ppc_exc_min_prolog_sync_tmpl_e500_mchk [];
+extern const uint32_t ppc_exc_min_prolog_async_tmpl_e500_mchk [];
+extern const uint32_t ppc_exc_min_prolog_tmpl_naked [];
+
+static const uint32_t *const ppc_exc_prologue_templates [] = {
+ [PPC_EXC_CLASSIC] = ppc_exc_min_prolog_sync_tmpl_std,
+ [PPC_EXC_CLASSIC_ASYNC] = ppc_exc_min_prolog_async_tmpl_std,
+ [PPC_EXC_405_CRITICAL] = ppc_exc_min_prolog_sync_tmpl_p405_crit,
+ [PPC_EXC_405_CRITICAL_ASYNC] = ppc_exc_min_prolog_async_tmpl_p405_crit,
+ [PPC_EXC_BOOKE_CRITICAL] = ppc_exc_min_prolog_sync_tmpl_bookE_crit,
+ [PPC_EXC_BOOKE_CRITICAL_ASYNC] = ppc_exc_min_prolog_async_tmpl_bookE_crit,
+ [PPC_EXC_E500_MACHCHK] = ppc_exc_min_prolog_sync_tmpl_e500_mchk,
+ [PPC_EXC_E500_MACHCHK_ASYNC] = ppc_exc_min_prolog_async_tmpl_e500_mchk,
+ [PPC_EXC_NAKED] = ppc_exc_min_prolog_tmpl_naked
+};
+
+rtems_status_code ppc_exc_make_prologue(
+ unsigned vector,
+ ppc_exc_category category,
+ uint32_t *prologue,
+ size_t *prologue_size
+)
+{
+ const uint32_t *prologue_template = NULL;
+ size_t prologue_template_size = 0;
+ uintptr_t vector_address = (uintptr_t) ppc_exc_vector_address(vector);
+ bool fixup_vector = false;
+
+ if (!ppc_exc_is_valid_category(category)) {
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ if (
+ ppc_cpu_has_shadowed_gprs()
+ && (vector == ASM_60X_IMISS_VECTOR
+ || vector == ASM_60X_DLMISS_VECTOR
+ || vector == ASM_60X_DSMISS_VECTOR)
+ ) {
+ prologue_template = ppc_exc_tgpr_clr_prolog;
+ prologue_template_size = (size_t) ppc_exc_tgpr_clr_prolog_size;
+ } else if (
+ category == PPC_EXC_CLASSIC
+ && ((vector_address & 0xffU) == 0
+ || (ppc_cpu_has_ivpr_and_ivor() && (vector_address & 0xfU) == 0))
+ ) {
+ if (ppc_cpu_has_ivpr_and_ivor()) {
+ prologue_template = ppc_exc_min_prolog_auto_packed;
+ } else {
+ prologue_template = ppc_exc_min_prolog_auto;
+ }
+ prologue_template_size = (size_t) ppc_exc_min_prolog_size;
+ } else {
+ prologue_template = ppc_exc_prologue_templates [category];
+ prologue_template_size = (size_t) ppc_exc_min_prolog_size;
+ fixup_vector = true;
+ }
+
+ if (prologue_template_size <= *prologue_size) {
+ *prologue_size = prologue_template_size;
+
+ memcpy(prologue, prologue_template, prologue_template_size);
+
+ if (fixup_vector) {
+ if (vector <= 0x7fffU) {
+ prologue [PPC_EXC_PROLOG_VEC_OFFSET] =
+ (prologue [PPC_EXC_PROLOG_VEC_OFFSET] & 0xffff8000U)
+ | (vector & 0x7fffU);
+ } else {
+ return RTEMS_INVALID_ID;
+ }
+ }
+ } else {
+ return RTEMS_INVALID_SIZE;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}