diff --git a/Makefile.target b/Makefile.target
index 1582904..0448fef 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -99,6 +99,9 @@ endif
 libobj-$(TARGET_SPARC) += int32_helper.o
 libobj-$(TARGET_SPARC64) += int64_helper.o
 libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
+ifeq ($(TARGET_BASE_ARCH), ppc)
+libobj-y += excp_helper.o
+endif
 
 libobj-y += disas.o
 libobj-$(CONFIG_TCI_DIS) += tci-dis.o
@@ -112,6 +115,9 @@ $(libobj-y): $(GENERATED_HEADERS)
 ifneq ($(TARGET_BASE_ARCH), sparc)
 op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 endif
+ifneq ($(TARGET_BASE_ARCH), ppc)
+excp_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+endif
 user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
 
 # Note: this is a workaround. The real fix is to avoid compiling
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
new file mode 100644
index 0000000..f03f738
--- /dev/null
+++ b/target-ppc/excp_helper.c
@@ -0,0 +1,218 @@
+/*
+ *  PowerPC exception emulation helpers for QEMU.
+ *
+ *  Copyright (c) 2003-2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "cpu.h"
+#include "dyngen-exec.h"
+#include "helper.h"
+
+#include "helper_regs.h"
+
+//#define DEBUG_OP
+//#define DEBUG_EXCEPTIONS
+
+/*****************************************************************************/
+/* Exceptions processing helpers */
+
+void helper_raise_exception_err(uint32_t exception, uint32_t error_code)
+{
+#if 0
+    printf("Raise exception %3x code : %d\n", exception, error_code);
+#endif
+    env->exception_index = exception;
+    env->error_code = error_code;
+    cpu_loop_exit(env);
+}
+
+void helper_raise_exception(uint32_t exception)
+{
+    helper_raise_exception_err(exception, 0);
+}
+
+#if !defined(CONFIG_USER_ONLY)
+void helper_store_msr(target_ulong val)
+{
+    val = hreg_store_msr(env, val, 0);
+    if (val != 0) {
+        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+        helper_raise_exception(val);
+    }
+}
+
+static inline void do_rfi(target_ulong nip, target_ulong msr,
+                          target_ulong msrm, int keep_msrh)
+{
+#if defined(TARGET_PPC64)
+    if (msr & (1ULL << MSR_SF)) {
+        nip = (uint64_t)nip;
+        msr &= (uint64_t)msrm;
+    } else {
+        nip = (uint32_t)nip;
+        msr = (uint32_t)(msr & msrm);
+        if (keep_msrh) {
+            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
+        }
+    }
+#else
+    nip = (uint32_t)nip;
+    msr &= (uint32_t)msrm;
+#endif
+    /* XXX: beware: this is false if VLE is supported */
+    env->nip = nip & ~((target_ulong)0x00000003);
+    hreg_store_msr(env, msr, 1);
+#if defined(DEBUG_OP)
+    cpu_dump_rfi(env->nip, env->msr);
+#endif
+    /* No need to raise an exception here,
+     * as rfi is always the last insn of a TB
+     */
+    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
+}
+
+void helper_rfi(void)
+{
+    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+           ~((target_ulong)0x783F0000), 1);
+}
+
+#if defined(TARGET_PPC64)
+void helper_rfid(void)
+{
+    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
+           ~((target_ulong)0x783F0000), 0);
+}
+
+void helper_hrfid(void)
+{
+    do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
+           ~((target_ulong)0x783F0000), 0);
+}
+#endif
+
+/*****************************************************************************/
+/* Embedded PowerPC specific helpers */
+void helper_40x_rfci(void)
+{
+    do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
+           ~((target_ulong)0xFFFF0000), 0);
+}
+
+void helper_rfci(void)
+{
+    do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
+           ~((target_ulong)0x3FFF0000), 0);
+}
+
+void helper_rfdi(void)
+{
+    do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
+           ~((target_ulong)0x3FFF0000), 0);
+}
+
+void helper_rfmci(void)
+{
+    do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
+           ~((target_ulong)0x3FFF0000), 0);
+}
+#endif
+
+void helper_tw(target_ulong arg1, target_ulong arg2, uint32_t flags)
+{
+    if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
+                  ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
+                  ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
+                  ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
+                  ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
+        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
+    }
+}
+
+#if defined(TARGET_PPC64)
+void helper_td(target_ulong arg1, target_ulong arg2, uint32_t flags)
+{
+    if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
+                  ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
+                  ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
+                  ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
+                  ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
+        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
+    }
+}
+#endif
+
+#if !defined(CONFIG_USER_ONLY)
+/*****************************************************************************/
+/* PowerPC 601 specific instructions (POWER bridge) */
+
+void helper_rfsvc(void)
+{
+    do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
+}
+
+/* Embedded.Processor Control */
+static int dbell2irq(target_ulong rb)
+{
+    int msg = rb & DBELL_TYPE_MASK;
+    int irq = -1;
+
+    switch (msg) {
+    case DBELL_TYPE_DBELL:
+        irq = PPC_INTERRUPT_DOORBELL;
+        break;
+    case DBELL_TYPE_DBELL_CRIT:
+        irq = PPC_INTERRUPT_CDOORBELL;
+        break;
+    case DBELL_TYPE_G_DBELL:
+    case DBELL_TYPE_G_DBELL_CRIT:
+    case DBELL_TYPE_G_DBELL_MC:
+        /* XXX implement */
+    default:
+        break;
+    }
+
+    return irq;
+}
+
+void helper_msgclr(target_ulong rb)
+{
+    int irq = dbell2irq(rb);
+
+    if (irq < 0) {
+        return;
+    }
+
+    env->pending_interrupts &= ~(1 << irq);
+}
+
+void helper_msgsnd(target_ulong rb)
+{
+    int irq = dbell2irq(rb);
+    int pir = rb & DBELL_PIRTAG_MASK;
+    CPUPPCState *cenv;
+
+    if (irq < 0) {
+        return;
+    }
+
+    for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
+        if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
+            cenv->pending_interrupts |= 1 << irq;
+            cpu_interrupt(cenv, CPU_INTERRUPT_HARD);
+        }
+    }
+}
+#endif
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index d9f7a8b..2e87860 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -29,7 +29,6 @@
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 //#define DEBUG_OP
-//#define DEBUG_EXCEPTIONS
 //#define DEBUG_SOFTWARE_TLB
 
 #ifdef DEBUG_SOFTWARE_TLB
@@ -38,25 +37,6 @@
 #  define LOG_SWTLB(...) do { } while (0)
 #endif
 
-
-/*****************************************************************************/
-/* Exceptions processing helpers */
-
-void helper_raise_exception_err(uint32_t exception, uint32_t error_code)
-{
-#if 0
-    printf("Raise exception %3x code : %d\n", exception, error_code);
-#endif
-    env->exception_index = exception;
-    env->error_code = error_code;
-    cpu_loop_exit(env);
-}
-
-void helper_raise_exception(uint32_t exception)
-{
-    helper_raise_exception_err(exception, 0);
-}
-
 /*****************************************************************************/
 /* SPR accesses */
 void helper_load_dump_spr(uint32_t sprn)
@@ -1658,91 +1638,6 @@ void helper_fcmpo(uint64_t arg1, uint64_t arg2, uint32_t crfD)
     }
 }
 
-#if !defined(CONFIG_USER_ONLY)
-void helper_store_msr(target_ulong val)
-{
-    val = hreg_store_msr(env, val, 0);
-    if (val != 0) {
-        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-        helper_raise_exception(val);
-    }
-}
-
-static inline void do_rfi(target_ulong nip, target_ulong msr,
-                          target_ulong msrm, int keep_msrh)
-{
-#if defined(TARGET_PPC64)
-    if (msr & (1ULL << MSR_SF)) {
-        nip = (uint64_t)nip;
-        msr &= (uint64_t)msrm;
-    } else {
-        nip = (uint32_t)nip;
-        msr = (uint32_t)(msr & msrm);
-        if (keep_msrh) {
-            msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
-        }
-    }
-#else
-    nip = (uint32_t)nip;
-    msr &= (uint32_t)msrm;
-#endif
-    /* XXX: beware: this is false if VLE is supported */
-    env->nip = nip & ~((target_ulong)0x00000003);
-    hreg_store_msr(env, msr, 1);
-#if defined(DEBUG_OP)
-    cpu_dump_rfi(env->nip, env->msr);
-#endif
-    /* No need to raise an exception here,
-     * as rfi is always the last insn of a TB
-     */
-    env->interrupt_request |= CPU_INTERRUPT_EXITTB;
-}
-
-void helper_rfi(void)
-{
-    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-           ~((target_ulong)0x783F0000), 1);
-}
-
-#if defined(TARGET_PPC64)
-void helper_rfid(void)
-{
-    do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-           ~((target_ulong)0x783F0000), 0);
-}
-
-void helper_hrfid(void)
-{
-    do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
-           ~((target_ulong)0x783F0000), 0);
-}
-#endif
-#endif
-
-void helper_tw(target_ulong arg1, target_ulong arg2, uint32_t flags)
-{
-    if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
-                  ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
-                  ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
-                  ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
-                  ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
-        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
-    }
-}
-
-#if defined(TARGET_PPC64)
-void helper_td(target_ulong arg1, target_ulong arg2, uint32_t flags)
-{
-    if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
-                  ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
-                  ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
-                  ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
-                  ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
-        helper_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
-    }
-}
-#endif
-
 /*****************************************************************************/
 /* PowerPC 601 specific instructions (POWER bridge) */
 
@@ -1854,11 +1749,6 @@ target_ulong helper_rac(target_ulong addr)
     env->nb_BATs = nb_BATs;
     return ret;
 }
-
-void helper_rfsvc(void)
-{
-    do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
-}
 #endif
 
 /*****************************************************************************/
@@ -1918,32 +1808,6 @@ void helper_store_dcr(target_ulong dcrn, target_ulong val)
     }
 }
 
-#if !defined(CONFIG_USER_ONLY)
-void helper_40x_rfci(void)
-{
-    do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
-           ~((target_ulong)0xFFFF0000), 0);
-}
-
-void helper_rfci(void)
-{
-    do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
-           ~((target_ulong)0x3FFF0000), 0);
-}
-
-void helper_rfdi(void)
-{
-    do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
-           ~((target_ulong)0x3FFF0000), 0);
-}
-
-void helper_rfmci(void)
-{
-    do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
-           ~((target_ulong)0x3FFF0000), 0);
-}
-#endif
-
 /* 440 specific */
 target_ulong helper_dlmzb(target_ulong high, target_ulong low,
                           uint32_t update_Rc)
@@ -4716,58 +4580,4 @@ void helper_booke206_tlbflush(uint32_t type)
 
     booke206_flush_tlb(env, flags, 1);
 }
-
-/* Embedded.Processor Control */
-static int dbell2irq(target_ulong rb)
-{
-    int msg = rb & DBELL_TYPE_MASK;
-    int irq = -1;
-
-    switch (msg) {
-    case DBELL_TYPE_DBELL:
-        irq = PPC_INTERRUPT_DOORBELL;
-        break;
-    case DBELL_TYPE_DBELL_CRIT:
-        irq = PPC_INTERRUPT_CDOORBELL;
-        break;
-    case DBELL_TYPE_G_DBELL:
-    case DBELL_TYPE_G_DBELL_CRIT:
-    case DBELL_TYPE_G_DBELL_MC:
-        /* XXX implement */
-    default:
-        break;
-    }
-
-    return irq;
-}
-
-void helper_msgclr(target_ulong rb)
-{
-    int irq = dbell2irq(rb);
-
-    if (irq < 0) {
-        return;
-    }
-
-    env->pending_interrupts &= ~(1 << irq);
-}
-
-void helper_msgsnd(target_ulong rb)
-{
-    int irq = dbell2irq(rb);
-    int pir = rb & DBELL_PIRTAG_MASK;
-    CPUPPCState *cenv;
-
-    if (irq < 0) {
-        return;
-    }
-
-    for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
-        if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
-            cenv->pending_interrupts |= 1 << irq;
-            cpu_interrupt(cenv, CPU_INTERRUPT_HARD);
-        }
-    }
-}
-
 #endif /* !CONFIG_USER_ONLY */
