]> git.proxmox.com Git - qemu.git/commitdiff
Rework PowerPC exceptions model to make it more versatile:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 29 Sep 2007 13:06:16 +0000 (13:06 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Sat, 29 Sep 2007 13:06:16 +0000 (13:06 +0000)
* don't use exception vectors as the exception number.
  Use vectors numbers as defined in the PowerPC embedded specification instead
  and extend this model to cover all emulated PowerPC variants exceptions.
* add some missing exceptions definitions, from PowerPC 2.04 specification
  and actual PowerPC implementations.
* add code provision for hypervisor exceptions handling.
* define exception vectors and prefix in CPUPPCState to emulate BookE exception
  vectors without any hacks.
* define per CPU model valid exception vectors.
* handle all known exceptions in user-mode only emulations.
* fix hardware interrupts priorities in most cases.
* change RET_EXCP macros name into GEN_EXCP as they don't return.
* do not stop translation on most instructions that are not defined as
  context-synchronizing in PowerPC specification.
* fix PowerPC 64 jump targets and link register update when in 32 bits mode.
* Fix PowerPC 464 and 464F definitions.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3261 c046a42c-6fe2-441c-8c8c-71466251a162

darwin-user/main.c
linux-user/main.c
target-ppc/cpu.h
target-ppc/helper.c
target-ppc/op_helper.c
target-ppc/op_mem.h
target-ppc/translate.c
target-ppc/translate_init.c

index fd62fc1b86e6bddb19f3521e6777341d108f1cf0..affd8745430f8fb7c6c42f1018f07be2fe40dd78 100644 (file)
@@ -139,17 +139,6 @@ void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
     cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
 }
 
-uint32_t cpu_ppc_load_decr (CPUState *env)
-{
-    /* TO FIX */
-    return -1;
-}
-
-void cpu_ppc_store_decr (CPUState *env, uint32_t value)
-{
-    /* TO FIX */
-}
-
 void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
 {
     cpu_ppc_store_tbu( env, value );
@@ -165,6 +154,27 @@ uint32_t cpu_ppc601_load_rtcl (CPUState *env)
     return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
 }
 
+/* XXX: to be fixed */
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
+{
+    return -1;
+}
+
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
+{
+    return -1;
+}
+
+#define EXCP_DUMP(env, fmt, args...)                                         \
+do {                                                                          \
+    fprintf(stderr, fmt , ##args);                                            \
+    cpu_dump_state(env, stderr, fprintf, 0);                                  \
+    if (loglevel != 0) {                                                      \
+        fprintf(logfile, fmt , ##args);                                       \
+        cpu_dump_state(env, logfile, fprintf, 0);                             \
+    }                                                                         \
+} while (0)
+
 void cpu_loop(CPUPPCState *env)
 {
     int trapnr;
@@ -173,271 +183,365 @@ void cpu_loop(CPUPPCState *env)
 
     for(;;) {
         trapnr = cpu_ppc_exec(env);
-        if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
-            trapnr != EXCP_TRACE) {
-            if (loglevel > 0) {
-                cpu_dump_state(env, logfile, fprintf, 0);
-            }
-        }
         switch(trapnr) {
-        case EXCP_NONE:
+        case POWERPC_EXCP_NONE:
+            /* Just go on */
             break;
-        case EXCP_SYSCALL_USER:
-            /* system call */
-            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
-                ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
-                                      env->gpr[5], env->gpr[6], env->gpr[7],
-                                      env->gpr[8], env->gpr[9], env->gpr[10]*/);
-            else if(((int)env->gpr[0])<0)
-                ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
-                                      env->gpr[5], env->gpr[6], env->gpr[7],
-                                      env->gpr[8], env->gpr[9], env->gpr[10]);
-            else
-                ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
-                                        env->gpr[5], env->gpr[6], env->gpr[7],
-                                        env->gpr[8], env->gpr[9], env->gpr[10]);
-
-            /* Unix syscall error signaling */
-            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
-            {
-                if( (int)ret < 0 )
-                    env->nip += 0;
-                else
-                    env->nip += 4;
-            }
-
-            /* Return value */
-            env->gpr[3] = ret;
+        case POWERPC_EXCP_CRITICAL: /* Critical input                        */
+            cpu_abort(env, "Critical interrupt while in user mode. "
+                      "Aborting\n");
             break;
-        case EXCP_RESET:
-            /* Should not happen ! */
-            fprintf(stderr, "RESET asked... Stop emulation\n");
-            if (loglevel)
-                fprintf(logfile, "RESET asked... Stop emulation\n");
-                abort();
-        case EXCP_MACHINE_CHECK:
-            fprintf(stderr, "Machine check exeption...  Stop emulation\n");
-            if (loglevel)
-                fprintf(logfile, "RESET asked... Stop emulation\n");
-                info.si_signo = SIGBUS;
-            info.si_errno = 0;
-            info.si_code = BUS_OBJERR;
-            info.si_addr = (void*)(env->nip - 4);
-            queue_signal(info.si_signo, &info);
-        case EXCP_DSI:
+        case POWERPC_EXCP_MCHECK:   /* Machine check exception               */
+            cpu_abort(env, "Machine check exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DSI:      /* Data storage exception                */
 #ifndef DAR
 /* To deal with multiple qemu header version as host for the darwin-user code */
 # define DAR SPR_DAR
 #endif
-            fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
-            if (loglevel) {
-                fprintf(logfile, "Invalid data memory access: 0x%08x\n",
-                        env->spr[DAR]);
-            }
+            EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
+                      env->spr[SPR_DAR]);
             /* Handle this via the gdb */
             gdb_handlesig (env, SIGSEGV);
 
             info.si_addr = (void*)env->nip;
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_ISI:
-            fprintf(stderr, "Invalid instruction fetch\n");
-            if (loglevel)
-                fprintf(logfile, "Invalid instruction fetch\n");
+        case POWERPC_EXCP_ISI:      /* Instruction storage exception         */
+            EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
+                      env->spr[SPR_DAR]);
             /* Handle this via the gdb */
             gdb_handlesig (env, SIGSEGV);
 
             info.si_addr = (void*)(env->nip - 4);
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_EXTERNAL:
-            /* Should not happen ! */
-            fprintf(stderr, "External interruption... Stop emulation\n");
-            if (loglevel)
-                fprintf(logfile, "External interruption... Stop emulation\n");
-                abort();
-        case EXCP_ALIGN:
-            fprintf(stderr, "Invalid unaligned memory access\n");
-            if (loglevel)
-                fprintf(logfile, "Invalid unaligned memory access\n");
-                info.si_signo = SIGBUS;
+        case POWERPC_EXCP_EXTERNAL: /* External input                        */
+            cpu_abort(env, "External interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ALIGN:    /* Alignment exception                   */
+            EXCP_DUMP(env, "Unaligned memory access\n");
             info.si_errno = 0;
             info.si_code = BUS_ADRALN;
             info.si_addr = (void*)(env->nip - 4);
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_PROGRAM:
+        case POWERPC_EXCP_PROGRAM:  /* Program exception                     */
+            /* XXX: check this */
             switch (env->error_code & ~0xF) {
-                case EXCP_FP:
-                    fprintf(stderr, "Program exception\n");
-                    if (loglevel)
-                        fprintf(logfile, "Program exception\n");
-                        /* Set FX */
-                        env->fpscr[7] |= 0x8;
-                    /* Finally, update FEX */
-                    if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
-                        ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
-                        env->fpscr[7] |= 0x4;
-                        info.si_signo = SIGFPE;
-                    info.si_errno = 0;
-                    switch (env->error_code & 0xF) {
-                        case EXCP_FP_OX:
-                            info.si_code = FPE_FLTOVF;
-                            break;
-                        case EXCP_FP_UX:
-                            info.si_code = FPE_FLTUND;
-                            break;
-                        case EXCP_FP_ZX:
-                        case EXCP_FP_VXZDZ:
-                            info.si_code = FPE_FLTDIV;
-                            break;
-                        case EXCP_FP_XX:
-                            info.si_code = FPE_FLTRES;
-                            break;
-                        case EXCP_FP_VXSOFT:
-                            info.si_code = FPE_FLTINV;
-                            break;
-                        case EXCP_FP_VXNAN:
-                        case EXCP_FP_VXISI:
-                        case EXCP_FP_VXIDI:
-                        case EXCP_FP_VXIMZ:
-                        case EXCP_FP_VXVC:
-                        case EXCP_FP_VXSQRT:
-                        case EXCP_FP_VXCVI:
-                            info.si_code = FPE_FLTSUB;
-                            break;
-                        default:
-                            fprintf(stderr, "Unknown floating point exception "
-                                    "(%02x)\n", env->error_code);
-                            if (loglevel) {
-                                fprintf(logfile, "Unknown floating point exception "
-                                        "(%02x)\n", env->error_code & 0xF);
-                            }
-                    }
-                        break;
-                case EXCP_INVAL:
-                    fprintf(stderr, "Invalid instruction\n");
-                    if (loglevel)
-                        fprintf(logfile, "Invalid instruction\n");
-                        info.si_signo = SIGILL;
-                    info.si_errno = 0;
-                    switch (env->error_code & 0xF) {
-                        case EXCP_INVAL_INVAL:
-                            info.si_code = ILL_ILLOPC;
-                            break;
-                        case EXCP_INVAL_LSWX:
-                            info.si_code = ILL_ILLOPN;
-                            break;
-                        case EXCP_INVAL_SPR:
-                            info.si_code = ILL_PRVREG;
-                            break;
-                        case EXCP_INVAL_FP:
-                            info.si_code = ILL_COPROC;
-                            break;
-                        default:
-                            fprintf(stderr, "Unknown invalid operation (%02x)\n",
-                                    env->error_code & 0xF);
-                            if (loglevel) {
-                                fprintf(logfile, "Unknown invalid operation (%02x)\n",
-                                        env->error_code & 0xF);
-                            }
-                                info.si_code = ILL_ILLADR;
-                            break;
-                    }
-                        /* Handle this via the gdb */
-                        gdb_handlesig (env, SIGSEGV);
+            case POWERPC_EXCP_FP:
+                EXCP_DUMP(env, "Floating point program exception\n");
+                /* Set FX */
+                env->fpscr[7] |= 0x8;
+                /* Finally, update FEX */
+                if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
+                    ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
+                    env->fpscr[7] |= 0x4;
+                info.si_signo = SIGFPE;
+                info.si_errno = 0;
+                switch (env->error_code & 0xF) {
+                case POWERPC_EXCP_FP_OX:
+                    info.si_code = FPE_FLTOVF;
+                    break;
+                case POWERPC_EXCP_FP_UX:
+                    info.si_code = FPE_FLTUND;
+                    break;
+                case POWERPC_EXCP_FP_ZX:
+                case POWERPC_EXCP_FP_VXZDZ:
+                    info.si_code = FPE_FLTDIV;
+                    break;
+                case POWERPC_EXCP_FP_XX:
+                    info.si_code = FPE_FLTRES;
+                    break;
+                case POWERPC_EXCP_FP_VXSOFT:
+                    info.si_code = FPE_FLTINV;
+                    break;
+                case POWERPC_EXCP_FP_VXNAN:
+                case POWERPC_EXCP_FP_VXISI:
+                case POWERPC_EXCP_FP_VXIDI:
+                case POWERPC_EXCP_FP_VXIMZ:
+                case POWERPC_EXCP_FP_VXVC:
+                case POWERPC_EXCP_FP_VXSQRT:
+                case POWERPC_EXCP_FP_VXCVI:
+                    info.si_code = FPE_FLTSUB;
+                    break;
+                default:
+                    EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
+                              env->error_code);
+                    break;
+                }
+                break;
+            case POWERPC_EXCP_INVAL:
+                EXCP_DUMP(env, "Invalid instruction\n");
+                info.si_signo = SIGILL;
+                info.si_errno = 0;
+                switch (env->error_code & 0xF) {
+                case POWERPC_EXCP_INVAL_INVAL:
+                    info.si_code = ILL_ILLOPC;
+                    break;
+                case POWERPC_EXCP_INVAL_LSWX:
+                    info.si_code = ILL_ILLOPN;
+                    break;
+                case POWERPC_EXCP_INVAL_SPR:
+                    info.si_code = ILL_PRVREG;
+                    break;
+                case POWERPC_EXCP_INVAL_FP:
+                    info.si_code = ILL_COPROC;
+                    break;
+                default:
+                    EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
+                              env->error_code & 0xF);
+                    info.si_code = ILL_ILLADR;
+                    break;
+                }
+                /* Handle this via the gdb */
+                gdb_handlesig (env, SIGSEGV);
+                break;
+            case POWERPC_EXCP_PRIV:
+                EXCP_DUMP(env, "Privilege violation\n");
+                info.si_signo = SIGILL;
+                info.si_errno = 0;
+                switch (env->error_code & 0xF) {
+                case POWERPC_EXCP_PRIV_OPC:
+                    info.si_code = ILL_PRVOPC;
+                    break;
+                case POWERPC_EXCP_PRIV_REG:
+                    info.si_code = ILL_PRVREG;
                     break;
-                case EXCP_PRIV:
-                    fprintf(stderr, "Privilege violation\n");
-                    if (loglevel)
-                        fprintf(logfile, "Privilege violation\n");
-                        info.si_signo = SIGILL;
-                    info.si_errno = 0;
-                    switch (env->error_code & 0xF) {
-                        case EXCP_PRIV_OPC:
-                            info.si_code = ILL_PRVOPC;
-                            break;
-                        case EXCP_PRIV_REG:
-                            info.si_code = ILL_PRVREG;
-                            break;
-                        default:
-                            fprintf(stderr, "Unknown privilege violation (%02x)\n",
-                                    env->error_code & 0xF);
-                            info.si_code = ILL_PRVOPC;
-                            break;
-                    }
-                        break;
-                case EXCP_TRAP:
-                    fprintf(stderr, "Tried to call a TRAP\n");
-                    if (loglevel)
-                        fprintf(logfile, "Tried to call a TRAP\n");
-                        abort();
                 default:
-                    /* Should not happen ! */
-                    fprintf(stderr, "Unknown program exception (%02x)\n",
-                            env->error_code);
-                    if (loglevel) {
-                        fprintf(logfile, "Unknwon program exception (%02x)\n",
-                                env->error_code);
-                    }
-                        abort();
+                    EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
+                              env->error_code & 0xF);
+                    info.si_code = ILL_PRVOPC;
+                    break;
+                }
+                break;
+            case POWERPC_EXCP_TRAP:
+                cpu_abort(env, "Tried to call a TRAP\n");
+                break;
+            default:
+                /* Should not happen ! */
+                cpu_abort(env, "Unknown program exception (%02x)\n",
+                          env->error_code);
+                break;
             }
             info.si_addr = (void*)(env->nip - 4);
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_NO_FP:
-            fprintf(stderr, "No floating point allowed\n");
-            if (loglevel)
-                fprintf(logfile, "No floating point allowed\n");
-                info.si_signo = SIGILL;
+        case POWERPC_EXCP_FPU:      /* Floating-point unavailable exception  */
+            EXCP_DUMP(env, "No floating point allowed\n");
+            info.si_signo = SIGILL;
             info.si_errno = 0;
             info.si_code = ILL_COPROC;
             info.si_addr = (void*)(env->nip - 4);
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_DECR:
-            /* Should not happen ! */
-            fprintf(stderr, "Decrementer exception\n");
-            if (loglevel)
-                fprintf(logfile, "Decrementer exception\n");
-            abort();
-        case EXCP_TRACE:
-            /* Pass to gdb: we use this to trace execution */
-            gdb_handlesig (env, SIGTRAP);
+        case POWERPC_EXCP_SYSCALL:  /* System call exception                 */
+            cpu_abort(env, "Syscall exception while in user mode. "
+                      "Aborting\n");
             break;
-        case EXCP_FP_ASSIST:
-            /* Should not happen ! */
-            fprintf(stderr, "Floating point assist exception\n");
-            if (loglevel)
-                fprintf(logfile, "Floating point assist exception\n");
-            abort();
-        case EXCP_MTMSR:
-            /* We reloaded the msr, just go on */
-            if (msr_pr == 0) {
-                fprintf(stderr, "Tried to go into supervisor mode !\n");
-                if (loglevel)
-                    fprintf(logfile, "Tried to go into supervisor mode !\n");
-                abort();
-            }
+        case POWERPC_EXCP_APU:      /* Auxiliary processor unavailable       */
+            EXCP_DUMP(env, "No APU instruction allowed\n");
+            info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = ILL_COPROC;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
             break;
-        case EXCP_BRANCH:
-            /* We stopped because of a jump... */
+        case POWERPC_EXCP_DECR:     /* Decrementer exception                 */
+            cpu_abort(env, "Decrementer interrupt while in user mode. "
+                      "Aborting\n");
             break;
-        case EXCP_INTERRUPT:
-            /* Don't know why this should ever happen... */
-            fprintf(stderr, "EXCP_INTERRUPT\n");
+        case POWERPC_EXCP_FIT:      /* Fixed-interval timer interrupt        */
+            cpu_abort(env, "Fix interval timer interrupt while in user mode. "
+                      "Aborting\n");
             break;
-        case EXCP_DEBUG:
+        case POWERPC_EXCP_WDT:      /* Watchdog timer interrupt              */
+            cpu_abort(env, "Watchdog timer interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DTLB:     /* Data TLB error                        */
+            cpu_abort(env, "Data TLB exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ITLB:     /* Instruction TLB error                 */
+            cpu_abort(env, "Instruction TLB exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DEBUG:    /* Debug interrupt                       */
             gdb_handlesig (env, SIGTRAP);
             break;
-        default:
-            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
-                    trapnr);
-            if (loglevel) {
-                fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
-                        "0x%02x - aborting\n", trapnr, env->error_code);
+#if defined(TARGET_PPCEMB)
+        case POWERPC_EXCP_SPEU:     /* SPE/embedded floating-point unavail.  */
+            EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
+            info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = ILL_COPROC;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case POWERPC_EXCP_EFPDI:    /* Embedded floating-point data IRQ      */
+            cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
+            break;
+        case POWERPC_EXCP_EFPRI:    /* Embedded floating-point round IRQ     */
+            cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
+            break;
+        case POWERPC_EXCP_EPERFM:   /* Embedded performance monitor IRQ      */
+            cpu_abort(env, "Performance monitor exception not handled\n");
+            break;
+        case POWERPC_EXCP_DOORI:    /* Embedded doorbell interrupt           */
+            cpu_abort(env, "Doorbell interrupt while in user mode. "
+                       "Aborting\n");
+            break;
+        case POWERPC_EXCP_DOORCI:   /* Embedded doorbell critical interrupt  */
+            cpu_abort(env, "Doorbell critical interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+#endif /* defined(TARGET_PPCEMB) */
+        case POWERPC_EXCP_RESET:    /* System reset exception                */
+            cpu_abort(env, "Reset interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+#if defined(TARGET_PPC64) /* PowerPC 64 */
+        case POWERPC_EXCP_DSEG:     /* Data segment exception                */
+            cpu_abort(env, "Data segment exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ISEG:     /* Instruction segment exception         */
+            cpu_abort(env, "Instruction segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64) */
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+        case POWERPC_EXCP_HDECR:    /* Hypervisor decrementer exception      */
+            cpu_abort(env, "Hypervisor decrementer interrupt "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64H) */
+        case POWERPC_EXCP_TRACE:    /* Trace exception                       */
+            /* Nothing to do:
+             * we use this exception to emulate step-by-step execution mode.
+             */
+            break;
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+        case POWERPC_EXCP_HDSI:     /* Hypervisor data storage exception     */
+            cpu_abort(env, "Hypervisor data storage exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HISI:     /* Hypervisor instruction storage excp   */
+            cpu_abort(env, "Hypervisor instruction storage exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HDSEG:    /* Hypervisor data segment exception     */
+            cpu_abort(env, "Hypervisor data segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HISEG:    /* Hypervisor instruction segment excp   */
+            cpu_abort(env, "Hypervisor instruction segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64H) */
+        case POWERPC_EXCP_VPU:      /* Vector unavailable exception          */
+            EXCP_DUMP(env, "No Altivec instructions allowed\n");
+            info.si_signo = SIGILL;
+            info.si_errno = 0;
+            info.si_code = ILL_COPROC;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */
+            cpu_abort(env, "Programable interval timer interrupt "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_IO:       /* IO error exception                    */
+            cpu_abort(env, "IO error exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_RUNM:     /* Run mode exception                    */
+            cpu_abort(env, "Run mode exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_EMUL:     /* Emulation trap exception              */
+            cpu_abort(env, "Emulation trap exception not handled\n");
+            break;
+        case POWERPC_EXCP_IFTLB:    /* Instruction fetch TLB error           */
+            cpu_abort(env, "Instruction fetch TLB exception "
+                      "while in user-mode. Aborting");
+            break;
+        case POWERPC_EXCP_DLTLB:    /* Data load TLB miss                    */
+            cpu_abort(env, "Data load TLB exception while in user-mode. "
+                      "Aborting");
+            break;
+        case POWERPC_EXCP_DSTLB:    /* Data store TLB miss                   */
+            cpu_abort(env, "Data store TLB exception while in user-mode. "
+                      "Aborting");
+            break;
+        case POWERPC_EXCP_FPA:      /* Floating-point assist exception       */
+            cpu_abort(env, "Floating-point assist exception not handled\n");
+            break;
+        case POWERPC_EXCP_IABR:     /* Instruction address breakpoint        */
+            cpu_abort(env, "Instruction address breakpoint exception "
+                      "not handled\n");
+            break;
+        case POWERPC_EXCP_SMI:      /* System management interrupt           */
+            cpu_abort(env, "System management interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_THERM:    /* Thermal interrupt                     */
+            cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_PERFM:    /* Embedded performance monitor IRQ      */
+            cpu_abort(env, "Performance monitor exception not handled\n");
+            break;
+        case POWERPC_EXCP_VPUA:     /* Vector assist exception               */
+            cpu_abort(env, "Vector assist exception not handled\n");
+            break;
+        case POWERPC_EXCP_SOFTP:    /* Soft patch exception                  */
+            cpu_abort(env, "Soft patch exception not handled\n");
+            break;
+        case POWERPC_EXCP_MAINT:    /* Maintenance exception                 */
+            cpu_abort(env, "Maintenance exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_STOP:     /* stop translation                      */
+            /* We did invalidate the instruction cache. Go on */
+            break;
+        case POWERPC_EXCP_BRANCH:   /* branch instruction:                   */
+            /* We just stopped because of a branch. Go on */
+            break;
+        case POWERPC_EXCP_SYSCALL_USER:
+            /* system call in user-mode emulation */
+            /* system call */
+            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
+                ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
+                                      env->gpr[5], env->gpr[6], env->gpr[7],
+                                      env->gpr[8], env->gpr[9], env->gpr[10]*/);
+            else if(((int)env->gpr[0])<0)
+                ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+                                      env->gpr[5], env->gpr[6], env->gpr[7],
+                                      env->gpr[8], env->gpr[9], env->gpr[10]);
+            else
+                ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+                                        env->gpr[5], env->gpr[6], env->gpr[7],
+                                        env->gpr[8], env->gpr[9], env->gpr[10]);
+
+            /* Unix syscall error signaling */
+            if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
+            {
+                if( (int)ret < 0 )
+                    env->nip += 0;
+                else
+                    env->nip += 4;
             }
-                abort();
+
+            /* Return value */
+            env->gpr[3] = ret;
+            break;
+        default:
+            cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
+            break;
         }
         process_pending_signals(env);
     }
index b70c070c3f50fdd734a4863072996e15ce51d649..fb424ad8873faac625ed274c7e3d22e26eea6f16 100644 (file)
@@ -723,6 +723,16 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
     return -1;
 }
 
+#define EXCP_DUMP(env, fmt, args...)                                         \
+do {                                                                          \
+    fprintf(stderr, fmt , ##args);                                            \
+    cpu_dump_state(env, stderr, fprintf, 0);                                  \
+    if (loglevel != 0) {                                                      \
+        fprintf(logfile, fmt , ##args);                                       \
+        cpu_dump_state(env, logfile, fprintf, 0);                             \
+    }                                                                         \
+} while (0)
+
 void cpu_loop(CPUPPCState *env)
 {
     target_siginfo_t info;
@@ -731,60 +741,22 @@ void cpu_loop(CPUPPCState *env)
 
     for(;;) {
         trapnr = cpu_ppc_exec(env);
-        if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
-            trapnr != EXCP_TRACE) {
-            if (loglevel > 0) {
-                cpu_dump_state(env, logfile, fprintf, 0);
-            }
-        }
         switch(trapnr) {
-        case EXCP_NONE:
+        case POWERPC_EXCP_NONE:
+            /* Just go on */
             break;
-        case EXCP_SYSCALL_USER:
-            /* system call */
-            /* WARNING:
-             * PPC ABI uses overflow flag in cr0 to signal an error
-             * in syscalls.
-             */
-#if 0
-            printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
-                   env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
-#endif
-            env->crf[0] &= ~0x1;
-            ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
-                             env->gpr[5], env->gpr[6], env->gpr[7],
-                             env->gpr[8]);
-            if (ret > (uint32_t)(-515)) {
-                env->crf[0] |= 0x1;
-                ret = -ret;
-            }
-            env->gpr[3] = ret;
-#if 0
-            printf("syscall returned 0x%08x (%d)\n", ret, ret);
-#endif
+        case POWERPC_EXCP_CRITICAL: /* Critical input                        */
+            cpu_abort(env, "Critical interrupt while in user mode. "
+                      "Aborting\n");
             break;
-        case EXCP_RESET:
-            /* Should not happen ! */
-            fprintf(stderr, "RESET asked... Stop emulation\n");
-            if (loglevel)
-                fprintf(logfile, "RESET asked... Stop emulation\n");
-            abort();
-        case EXCP_MACHINE_CHECK:
-            fprintf(stderr, "Machine check exeption...  Stop emulation\n");
-            if (loglevel)
-                fprintf(logfile, "Machine check exception. Stop emulation\n");
-            info.si_signo = TARGET_SIGBUS;
-            info.si_errno = 0;
-            info.si_code = TARGET_BUS_OBJERR;
-            info._sifields._sigfault._addr = env->nip - 4;
-            queue_signal(info.si_signo, &info);
-        case EXCP_DSI:
-            fprintf(stderr, "Invalid data memory access: 0x" ADDRX "\n",
-                    env->spr[SPR_DAR]);
-            if (loglevel) {
-                fprintf(logfile, "Invalid data memory access: 0x" ADDRX "\n",
-                        env->spr[SPR_DAR]);
-            }
+        case POWERPC_EXCP_MCHECK:   /* Machine check exception               */
+            cpu_abort(env, "Machine check exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DSI:      /* Data storage exception                */
+            EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
+                      env->spr[SPR_DAR]);
+            /* XXX: check this. Seems bugged */
             switch (env->error_code & 0xFF000000) {
             case 0x40000000:
                 info.si_signo = TARGET_SIGSEGV;
@@ -803,12 +775,8 @@ void cpu_loop(CPUPPCState *env)
                 break;
             default:
                 /* Let's send a regular segfault... */
-                fprintf(stderr, "Invalid segfault errno (%02x)\n",
-                        env->error_code);
-                if (loglevel) {
-                    fprintf(logfile, "Invalid segfault errno (%02x)\n",
-                            env->error_code);
-                }
+                EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
+                          env->error_code);
                 info.si_signo = TARGET_SIGSEGV;
                 info.si_errno = 0;
                 info.si_code = TARGET_SEGV_MAPERR;
@@ -817,10 +785,10 @@ void cpu_loop(CPUPPCState *env)
             info._sifields._sigfault._addr = env->nip;
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_ISI:
-            fprintf(stderr, "Invalid instruction fetch\n");
-            if (loglevel)
-                fprintf(logfile, "Invalid instruction fetch\n");
+        case POWERPC_EXCP_ISI:      /* Instruction storage exception         */
+            EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
+                      env->spr[SPR_DAR]);
+            /* XXX: check this */
             switch (env->error_code & 0xFF000000) {
             case 0x40000000:
                 info.si_signo = TARGET_SIGSEGV;
@@ -835,12 +803,8 @@ void cpu_loop(CPUPPCState *env)
                 break;
             default:
                 /* Let's send a regular segfault... */
-                fprintf(stderr, "Invalid segfault errno (%02x)\n",
-                        env->error_code);
-                if (loglevel) {
-                    fprintf(logfile, "Invalid segfault errno (%02x)\n",
-                            env->error_code);
-                }
+                EXCP_DUMP(env, "Invalid segfault errno (%02x)\n",
+                          env->error_code);
                 info.si_signo = TARGET_SIGSEGV;
                 info.si_errno = 0;
                 info.si_code = TARGET_SEGV_MAPERR;
@@ -849,28 +813,24 @@ void cpu_loop(CPUPPCState *env)
             info._sifields._sigfault._addr = env->nip - 4;
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_EXTERNAL:
-            /* Should not happen ! */
-            fprintf(stderr, "External interruption... Stop emulation\n");
-            if (loglevel)
-                fprintf(logfile, "External interruption... Stop emulation\n");
-            abort();
-        case EXCP_ALIGN:
-            fprintf(stderr, "Invalid unaligned memory access\n");
-            if (loglevel)
-                fprintf(logfile, "Invalid unaligned memory access\n");
+        case POWERPC_EXCP_EXTERNAL: /* External input                        */
+            cpu_abort(env, "External interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ALIGN:    /* Alignment exception                   */
+            EXCP_DUMP(env, "Unaligned memory access\n");
+            /* XXX: check this */
             info.si_signo = TARGET_SIGBUS;
             info.si_errno = 0;
             info.si_code = TARGET_BUS_ADRALN;
             info._sifields._sigfault._addr = env->nip - 4;
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_PROGRAM:
+        case POWERPC_EXCP_PROGRAM:  /* Program exception                     */
+            /* XXX: check this */
             switch (env->error_code & ~0xF) {
-            case EXCP_FP:
-            fprintf(stderr, "Program exception\n");
-                if (loglevel)
-                    fprintf(logfile, "Program exception\n");
+            case POWERPC_EXCP_FP:
+                EXCP_DUMP(env, "Floating point program exception\n");
                 /* Set FX */
                 env->fpscr[7] |= 0x8;
                 /* Finally, update FEX */
@@ -880,155 +840,138 @@ void cpu_loop(CPUPPCState *env)
                 info.si_signo = TARGET_SIGFPE;
                 info.si_errno = 0;
                 switch (env->error_code & 0xF) {
-                case EXCP_FP_OX:
+                case POWERPC_EXCP_FP_OX:
                     info.si_code = TARGET_FPE_FLTOVF;
                     break;
-                case EXCP_FP_UX:
+                case POWERPC_EXCP_FP_UX:
                     info.si_code = TARGET_FPE_FLTUND;
                     break;
-                case EXCP_FP_ZX:
-                case EXCP_FP_VXZDZ:
+                case POWERPC_EXCP_FP_ZX:
+                case POWERPC_EXCP_FP_VXZDZ:
                     info.si_code = TARGET_FPE_FLTDIV;
                     break;
-                case EXCP_FP_XX:
+                case POWERPC_EXCP_FP_XX:
                     info.si_code = TARGET_FPE_FLTRES;
                     break;
-                case EXCP_FP_VXSOFT:
+                case POWERPC_EXCP_FP_VXSOFT:
                     info.si_code = TARGET_FPE_FLTINV;
                     break;
-                case EXCP_FP_VXNAN:
-                case EXCP_FP_VXISI:
-                case EXCP_FP_VXIDI:
-                case EXCP_FP_VXIMZ:
-                case EXCP_FP_VXVC:
-                case EXCP_FP_VXSQRT:
-                case EXCP_FP_VXCVI:
+                case POWERPC_EXCP_FP_VXNAN:
+                case POWERPC_EXCP_FP_VXISI:
+                case POWERPC_EXCP_FP_VXIDI:
+                case POWERPC_EXCP_FP_VXIMZ:
+                case POWERPC_EXCP_FP_VXVC:
+                case POWERPC_EXCP_FP_VXSQRT:
+                case POWERPC_EXCP_FP_VXCVI:
                     info.si_code = TARGET_FPE_FLTSUB;
                     break;
                 default:
-                    fprintf(stderr, "Unknown floating point exception "
-                            "(%02x)\n", env->error_code);
-                    if (loglevel) {
-                        fprintf(logfile, "Unknown floating point exception "
-                                "(%02x)\n", env->error_code & 0xF);
-                    }
+                    EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
+                              env->error_code);
+                    break;
                 }
-            break;
-        case EXCP_INVAL:
-                fprintf(stderr, "Invalid instruction\n");
-                if (loglevel)
-                    fprintf(logfile, "Invalid instruction\n");
+                break;
+            case POWERPC_EXCP_INVAL:
+                EXCP_DUMP(env, "Invalid instruction\n");
                 info.si_signo = TARGET_SIGILL;
                 info.si_errno = 0;
                 switch (env->error_code & 0xF) {
-                case EXCP_INVAL_INVAL:
+                case POWERPC_EXCP_INVAL_INVAL:
                     info.si_code = TARGET_ILL_ILLOPC;
                     break;
-                case EXCP_INVAL_LSWX:
+                case POWERPC_EXCP_INVAL_LSWX:
                     info.si_code = TARGET_ILL_ILLOPN;
                     break;
-                case EXCP_INVAL_SPR:
+                case POWERPC_EXCP_INVAL_SPR:
                     info.si_code = TARGET_ILL_PRVREG;
                     break;
-                case EXCP_INVAL_FP:
+                case POWERPC_EXCP_INVAL_FP:
                     info.si_code = TARGET_ILL_COPROC;
                     break;
                 default:
-                    fprintf(stderr, "Unknown invalid operation (%02x)\n",
-                            env->error_code & 0xF);
-                    if (loglevel) {
-                        fprintf(logfile, "Unknown invalid operation (%02x)\n",
-                                env->error_code & 0xF);
-                    }
+                    EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
+                              env->error_code & 0xF);
                     info.si_code = TARGET_ILL_ILLADR;
                     break;
                 }
                 break;
-            case EXCP_PRIV:
-                fprintf(stderr, "Privilege violation\n");
-                if (loglevel)
-                    fprintf(logfile, "Privilege violation\n");
+            case POWERPC_EXCP_PRIV:
+                EXCP_DUMP(env, "Privilege violation\n");
                 info.si_signo = TARGET_SIGILL;
                 info.si_errno = 0;
                 switch (env->error_code & 0xF) {
-                case EXCP_PRIV_OPC:
+                case POWERPC_EXCP_PRIV_OPC:
                     info.si_code = TARGET_ILL_PRVOPC;
                     break;
-                case EXCP_PRIV_REG:
+                case POWERPC_EXCP_PRIV_REG:
                     info.si_code = TARGET_ILL_PRVREG;
-                break;
+                    break;
                 default:
-                    fprintf(stderr, "Unknown privilege violation (%02x)\n",
-                            env->error_code & 0xF);
+                    EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
+                              env->error_code & 0xF);
                     info.si_code = TARGET_ILL_PRVOPC;
                     break;
                 }
                 break;
-            case EXCP_TRAP:
-                fprintf(stderr, "Tried to call a TRAP\n");
-                if (loglevel)
-                    fprintf(logfile, "Tried to call a TRAP\n");
-                abort();
+            case POWERPC_EXCP_TRAP:
+                cpu_abort(env, "Tried to call a TRAP\n");
+                break;
             default:
                 /* Should not happen ! */
-                fprintf(stderr, "Unknown program exception (%02x)\n",
-                        env->error_code);
-                if (loglevel) {
-                    fprintf(logfile, "Unknwon program exception (%02x)\n",
-                            env->error_code);
-                }
-                abort();
+                cpu_abort(env, "Unknown program exception (%02x)\n",
+                          env->error_code);
+                break;
             }
             info._sifields._sigfault._addr = env->nip - 4;
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_NO_FP:
-            fprintf(stderr, "No floating point allowed\n");
-            if (loglevel)
-                fprintf(logfile, "No floating point allowed\n");
+        case POWERPC_EXCP_FPU:      /* Floating-point unavailable exception  */
+            EXCP_DUMP(env, "No floating point allowed\n");
             info.si_signo = TARGET_SIGILL;
             info.si_errno = 0;
             info.si_code = TARGET_ILL_COPROC;
             info._sifields._sigfault._addr = env->nip - 4;
             queue_signal(info.si_signo, &info);
             break;
-        case EXCP_DECR:
-            /* Should not happen ! */
-            fprintf(stderr, "Decrementer exception\n");
-            if (loglevel)
-                fprintf(logfile, "Decrementer exception\n");
-            abort();
-        case EXCP_TRACE:
-            /* Do nothing: we use this to trace execution */
-            break;
-        case EXCP_FP_ASSIST:
-            /* Should not happen ! */
-            fprintf(stderr, "Floating point assist exception\n");
-            if (loglevel)
-                fprintf(logfile, "Floating point assist exception\n");
-            abort();
-        case EXCP_MTMSR:
-            /* We reloaded the msr, just go on */
-            if (msr_pr == 0) {
-                fprintf(stderr, "Tried to go into supervisor mode !\n");
-                if (loglevel)
-                    fprintf(logfile, "Tried to go into supervisor mode !\n");
-                abort();
-            }
+        case POWERPC_EXCP_SYSCALL:  /* System call exception                 */
+            cpu_abort(env, "Syscall exception while in user mode. "
+                      "Aborting\n");
             break;
-        case EXCP_BRANCH:
-            /* We stopped because of a jump... */
+        case POWERPC_EXCP_APU:      /* Auxiliary processor unavailable       */
+            EXCP_DUMP(env, "No APU instruction allowed\n");
+            info.si_signo = TARGET_SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_COPROC;
+            info._sifields._sigfault._addr = env->nip - 4;
+            queue_signal(info.si_signo, &info);
             break;
-        case EXCP_INTERRUPT:
-            /* Don't know why this should ever happen... */
+        case POWERPC_EXCP_DECR:     /* Decrementer exception                 */
+            cpu_abort(env, "Decrementer interrupt while in user mode. "
+                      "Aborting\n");
             break;
-        case EXCP_DEBUG:
+        case POWERPC_EXCP_FIT:      /* Fixed-interval timer interrupt        */
+            cpu_abort(env, "Fix interval timer interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_WDT:      /* Watchdog timer interrupt              */
+            cpu_abort(env, "Watchdog timer interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DTLB:     /* Data TLB error                        */
+            cpu_abort(env, "Data TLB exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ITLB:     /* Instruction TLB error                 */
+            cpu_abort(env, "Instruction TLB exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_DEBUG:    /* Debug interrupt                       */
+            /* XXX: check this */
             {
                 int sig;
 
-                sig = gdb_handlesig (env, TARGET_SIGTRAP);
-                if (sig)
-                  {
+                sig = gdb_handlesig(env, TARGET_SIGTRAP);
+                if (sig) {
                     info.si_signo = sig;
                     info.si_errno = 0;
                     info.si_code = TARGET_TRAP_BRKPT;
@@ -1036,14 +979,171 @@ void cpu_loop(CPUPPCState *env)
                   }
             }
             break;
-        default:
-            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
-                    trapnr);
-            if (loglevel) {
-                fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
-                        "0x%02x - aborting\n", trapnr, env->error_code);
+#if defined(TARGET_PPCEMB)
+        case POWERPC_EXCP_SPEU:     /* SPE/embedded floating-point unavail.  */
+            EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
+            info.si_signo = TARGET_SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_COPROC;
+            info._sifields._sigfault._addr = env->nip - 4;
+            queue_signal(info.si_signo, &info);
+            break;
+        case POWERPC_EXCP_EFPDI:    /* Embedded floating-point data IRQ      */
+            cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
+            break;
+        case POWERPC_EXCP_EFPRI:    /* Embedded floating-point round IRQ     */
+            cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
+            break;
+        case POWERPC_EXCP_EPERFM:   /* Embedded performance monitor IRQ      */
+            cpu_abort(env, "Performance monitor exception not handled\n");
+            break;
+        case POWERPC_EXCP_DOORI:    /* Embedded doorbell interrupt           */
+            cpu_abort(env, "Doorbell interrupt while in user mode. "
+                       "Aborting\n");
+            break;
+        case POWERPC_EXCP_DOORCI:   /* Embedded doorbell critical interrupt  */
+            cpu_abort(env, "Doorbell critical interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_RESET:    /* System reset exception                */
+            cpu_abort(env, "Reset interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+#endif /* defined(TARGET_PPCEMB) */
+#if defined(TARGET_PPC64) /* PowerPC 64 */
+        case POWERPC_EXCP_DSEG:     /* Data segment exception                */
+            cpu_abort(env, "Data segment exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_ISEG:     /* Instruction segment exception         */
+            cpu_abort(env, "Instruction segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64) */
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+        case POWERPC_EXCP_HDECR:    /* Hypervisor decrementer exception      */
+            cpu_abort(env, "Hypervisor decrementer interrupt "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64H) */
+        case POWERPC_EXCP_TRACE:    /* Trace exception                       */
+            /* Nothing to do:
+             * we use this exception to emulate step-by-step execution mode.
+             */
+            break;
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+        case POWERPC_EXCP_HDSI:     /* Hypervisor data storage exception     */
+            cpu_abort(env, "Hypervisor data storage exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HISI:     /* Hypervisor instruction storage excp   */
+            cpu_abort(env, "Hypervisor instruction storage exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HDSEG:    /* Hypervisor data segment exception     */
+            cpu_abort(env, "Hypervisor data segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_HISEG:    /* Hypervisor instruction segment excp   */
+            cpu_abort(env, "Hypervisor instruction segment exception "
+                      "while in user mode. Aborting\n");
+            break;
+#endif /* defined(TARGET_PPC64H) */
+        case POWERPC_EXCP_VPU:      /* Vector unavailable exception          */
+            EXCP_DUMP(env, "No Altivec instructions allowed\n");
+            info.si_signo = TARGET_SIGILL;
+            info.si_errno = 0;
+            info.si_code = TARGET_ILL_COPROC;
+            info._sifields._sigfault._addr = env->nip - 4;
+            queue_signal(info.si_signo, &info);
+            break;
+        case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */
+            cpu_abort(env, "Programable interval timer interrupt "
+                      "while in user mode. Aborting\n");
+            break;
+        case POWERPC_EXCP_IO:       /* IO error exception                    */
+            cpu_abort(env, "IO error exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_RUNM:     /* Run mode exception                    */
+            cpu_abort(env, "Run mode exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_EMUL:     /* Emulation trap exception              */
+            cpu_abort(env, "Emulation trap exception not handled\n");
+            break;
+        case POWERPC_EXCP_IFTLB:    /* Instruction fetch TLB error           */
+            cpu_abort(env, "Instruction fetch TLB exception "
+                      "while in user-mode. Aborting");
+            break;
+        case POWERPC_EXCP_DLTLB:    /* Data load TLB miss                    */
+            cpu_abort(env, "Data load TLB exception while in user-mode. "
+                      "Aborting");
+            break;
+        case POWERPC_EXCP_DSTLB:    /* Data store TLB miss                   */
+            cpu_abort(env, "Data store TLB exception while in user-mode. "
+                      "Aborting");
+            break;
+        case POWERPC_EXCP_FPA:      /* Floating-point assist exception       */
+            cpu_abort(env, "Floating-point assist exception not handled\n");
+            break;
+        case POWERPC_EXCP_IABR:     /* Instruction address breakpoint        */
+            cpu_abort(env, "Instruction address breakpoint exception "
+                      "not handled\n");
+            break;
+        case POWERPC_EXCP_SMI:      /* System management interrupt           */
+            cpu_abort(env, "System management interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_THERM:    /* Thermal interrupt                     */
+            cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_PERFM:   /* Embedded performance monitor IRQ      */
+            cpu_abort(env, "Performance monitor exception not handled\n");
+            break;
+        case POWERPC_EXCP_VPUA:     /* Vector assist exception               */
+            cpu_abort(env, "Vector assist exception not handled\n");
+            break;
+        case POWERPC_EXCP_SOFTP:    /* Soft patch exception                  */
+            cpu_abort(env, "Soft patch exception not handled\n");
+            break;
+        case POWERPC_EXCP_MAINT:    /* Maintenance exception                 */
+            cpu_abort(env, "Maintenance exception while in user mode. "
+                      "Aborting\n");
+            break;
+        case POWERPC_EXCP_STOP:     /* stop translation                      */
+            /* We did invalidate the instruction cache. Go on */
+            break;
+        case POWERPC_EXCP_BRANCH:   /* branch instruction:                   */
+            /* We just stopped because of a branch. Go on */
+            break;
+        case POWERPC_EXCP_SYSCALL_USER:
+            /* system call in user-mode emulation */
+            /* WARNING:
+             * PPC ABI uses overflow flag in cr0 to signal an error
+             * in syscalls.
+             */
+#if 0
+            printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
+                   env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
+#endif
+            env->crf[0] &= ~0x1;
+            ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+                             env->gpr[5], env->gpr[6], env->gpr[7],
+                             env->gpr[8]);
+            if (ret > (uint32_t)(-515)) {
+                env->crf[0] |= 0x1;
+                ret = -ret;
             }
-            abort();
+            env->gpr[3] = ret;
+#if 0
+            printf("syscall returned 0x%08x (%d)\n", ret, ret);
+#endif
+            break;
+        default:
+            cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
+            break;
         }
         process_pending_signals(env);
     }
index 79712b0c650d38e0915aeed2885da100f213d7d5..57e8f358c27b706b9e3e4c88a1e3bfc775dbac72 100644 (file)
@@ -148,6 +148,127 @@ enum {
     POWERPC_EXCP_BOOKE,
 };
 
+/*****************************************************************************/
+/* Exception vectors definitions                                             */
+enum {
+    POWERPC_EXCP_NONE    = -1,
+    /* The 64 first entries are used by the PowerPC embedded specification   */
+    POWERPC_EXCP_CRITICAL = 0,  /* Critical input                            */
+    POWERPC_EXCP_MCHECK   = 1,  /* Machine check exception                   */
+    POWERPC_EXCP_DSI      = 2,  /* Data storage exception                    */
+    POWERPC_EXCP_ISI      = 3,  /* Instruction storage exception             */
+    POWERPC_EXCP_EXTERNAL = 4,  /* External input                            */
+    POWERPC_EXCP_ALIGN    = 5,  /* Alignment exception                       */
+    POWERPC_EXCP_PROGRAM  = 6,  /* Program exception                         */
+    POWERPC_EXCP_FPU      = 7,  /* Floating-point unavailable exception      */
+    POWERPC_EXCP_SYSCALL  = 8,  /* System call exception                     */
+    POWERPC_EXCP_APU      = 9,  /* Auxiliary processor unavailable           */
+    POWERPC_EXCP_DECR     = 10, /* Decrementer exception                     */
+    POWERPC_EXCP_FIT      = 11, /* Fixed-interval timer interrupt            */
+    POWERPC_EXCP_WDT      = 12, /* Watchdog timer interrupt                  */
+    POWERPC_EXCP_DTLB     = 13, /* Data TLB error                            */
+    POWERPC_EXCP_ITLB     = 14, /* Instruction TLB error                     */
+    POWERPC_EXCP_DEBUG    = 15, /* Debug interrupt                           */
+    /* Vectors 16 to 31 are reserved                                         */
+#if defined(TARGET_PPCEMB)
+    POWERPC_EXCP_SPEU     = 32, /* SPE/embedded floating-point unavailable   */
+    POWERPC_EXCP_EFPDI    = 33, /* Embedded floating-point data interrupt    */
+    POWERPC_EXCP_EFPRI    = 34, /* Embedded floating-point round interrupt   */
+    POWERPC_EXCP_EPERFM   = 35, /* Embedded performance monitor interrupt    */
+    POWERPC_EXCP_DOORI    = 36, /* Embedded doorbell interrupt               */
+    POWERPC_EXCP_DOORCI   = 37, /* Embedded doorbell critical interrupt      */
+#endif /* defined(TARGET_PPCEMB) */
+    /* Vectors 38 to 63 are reserved                                         */
+    /* Exceptions defined in the PowerPC server specification                */
+    POWERPC_EXCP_RESET    = 64, /* System reset exception                    */
+#if defined(TARGET_PPC64) /* PowerPC 64 */
+    POWERPC_EXCP_DSEG     = 65, /* Data segment exception                    */
+    POWERPC_EXCP_ISEG     = 66, /* Instruction segment exception             */
+#endif /* defined(TARGET_PPC64) */
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+    POWERPC_EXCP_HDECR    = 67, /* Hypervisor decrementer exception          */
+#endif /* defined(TARGET_PPC64H) */
+    POWERPC_EXCP_TRACE    = 68, /* Trace exception                           */
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+    POWERPC_EXCP_HDSI     = 69, /* Hypervisor data storage exception         */
+    POWERPC_EXCP_HISI     = 70, /* Hypervisor instruction storage exception  */
+    POWERPC_EXCP_HDSEG    = 71, /* Hypervisor data segment exception         */
+    POWERPC_EXCP_HISEG    = 72, /* Hypervisor instruction segment exception  */
+#endif /* defined(TARGET_PPC64H) */
+    POWERPC_EXCP_VPU      = 73, /* Vector unavailable exception              */
+    /* 40x specific exceptions                                               */
+    POWERPC_EXCP_PIT      = 74, /* Programmable interval timer interrupt     */
+    /* 601 specific exceptions                                               */
+    POWERPC_EXCP_IO       = 75, /* IO error exception                        */
+    POWERPC_EXCP_RUNM     = 76, /* Run mode exception                        */
+    /* 602 specific exceptions                                               */
+    POWERPC_EXCP_EMUL     = 77, /* Emulation trap exception                  */
+    /* 602/603 specific exceptions                                           */
+    POWERPC_EXCP_IFTLB    = 78, /* Instruction fetch TLB error               */
+    POWERPC_EXCP_DLTLB    = 79, /* Data load TLB miss                        */
+    POWERPC_EXCP_DSTLB    = 80, /* Data store TLB miss                       */
+    /* Exceptions available on most PowerPC                                  */
+    POWERPC_EXCP_FPA      = 81, /* Floating-point assist exception           */
+    POWERPC_EXCP_IABR     = 82, /* Instruction address breakpoint            */
+    POWERPC_EXCP_SMI      = 83, /* System management interrupt               */
+    POWERPC_EXCP_PERFM    = 84, /* Embedded performance monitor interrupt    */
+    /* 7xx/74xx specific exceptions                                          */
+    POWERPC_EXCP_THERM    = 85, /* Thermal interrupt                         */
+    /* 74xx specific exceptions                                              */
+    POWERPC_EXCP_VPUA     = 86, /* Vector assist exception                   */
+    /* 970FX specific exceptions                                             */
+    POWERPC_EXCP_SOFTP    = 87, /* Soft patch exception                      */
+    POWERPC_EXCP_MAINT    = 88, /* Maintenance exception                     */
+    /* EOL                                                                   */
+    POWERPC_EXCP_NB       = 96,
+    /* Qemu exceptions: used internally during code translation              */
+    POWERPC_EXCP_STOP         = 0x200, /* stop translation                   */
+    POWERPC_EXCP_BRANCH       = 0x201, /* branch instruction                 */
+    /* Qemu exceptions: special cases we want to stop translation            */
+    POWERPC_EXCP_SYNC         = 0x202, /* context synchronizing instruction  */
+    POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only      */
+};
+
+
+/* Exceptions error codes                                                    */
+enum {
+    /* Exception subtypes for POWERPC_EXCP_ALIGN                             */
+    POWERPC_EXCP_ALIGN_FP      = 0x01,  /* FP alignment exception            */
+    POWERPC_EXCP_ALIGN_LST     = 0x02,  /* Unaligned mult/extern load/store  */
+    POWERPC_EXCP_ALIGN_LE      = 0x03,  /* Multiple little-endian access     */
+    POWERPC_EXCP_ALIGN_PROT    = 0x04,  /* Access cross protection boundary  */
+    POWERPC_EXCP_ALIGN_BAT     = 0x05,  /* Access cross a BAT/seg boundary   */
+    POWERPC_EXCP_ALIGN_CACHE   = 0x06,  /* Impossible dcbz access            */
+    /* Exception subtypes for POWERPC_EXCP_PROGRAM                           */
+    /* FP exceptions                                                         */
+    POWERPC_EXCP_FP            = 0x10,
+    POWERPC_EXCP_FP_OX         = 0x01,  /* FP overflow                       */
+    POWERPC_EXCP_FP_UX         = 0x02,  /* FP underflow                      */
+    POWERPC_EXCP_FP_ZX         = 0x03,  /* FP divide by zero                 */
+    POWERPC_EXCP_FP_XX         = 0x04,  /* FP inexact                        */
+    POWERPC_EXCP_FP_VXNAN      = 0x05,  /* FP invalid SNaN op                */
+    POWERPC_EXCP_FP_VXISI      = 0x06,  /* FP invalid infinite subtraction   */
+    POWERPC_EXCP_FP_VXIDI      = 0x07,  /* FP invalid infinite divide        */
+    POWERPC_EXCP_FP_VXZDZ      = 0x08,  /* FP invalid zero divide            */
+    POWERPC_EXCP_FP_VXIMZ      = 0x09,  /* FP invalid infinite * zero        */
+    POWERPC_EXCP_FP_VXVC       = 0x0A,  /* FP invalid compare                */
+    POWERPC_EXCP_FP_VXSOFT     = 0x0B,  /* FP invalid operation              */
+    POWERPC_EXCP_FP_VXSQRT     = 0x0C,  /* FP invalid square root            */
+    POWERPC_EXCP_FP_VXCVI      = 0x0D,  /* FP invalid integer conversion     */
+    /* Invalid instruction                                                   */
+    POWERPC_EXCP_INVAL         = 0x20,
+    POWERPC_EXCP_INVAL_INVAL   = 0x01,  /* Invalid instruction               */
+    POWERPC_EXCP_INVAL_LSWX    = 0x02,  /* Invalid lswx instruction          */
+    POWERPC_EXCP_INVAL_SPR     = 0x03,  /* Invalid SPR access                */
+    POWERPC_EXCP_INVAL_FP      = 0x04,  /* Unimplemented mandatory fp instr  */
+    /* Privileged instruction                                                */
+    POWERPC_EXCP_PRIV          = 0x30,
+    POWERPC_EXCP_PRIV_OPC      = 0x01,  /* Privileged operation exception    */
+    POWERPC_EXCP_PRIV_REG      = 0x02,  /* Privileged register exception     */
+    /* Trap                                                                  */
+    POWERPC_EXCP_TRAP          = 0x40,
+};
+
 /*****************************************************************************/
 /* Input pins model                                                          */
 enum {
@@ -411,6 +532,11 @@ struct CPUPPCState {
      */
     uint32_t irq_input_state;
     void **irq_inputs;
+    /* Exception vectors */
+    target_ulong excp_vectors[POWERPC_EXCP_NB];
+    target_ulong excp_prefix;
+    target_ulong ivor_mask;
+    target_ulong ivpr_mask;
 #endif
 
     /* Those resources are used only during code translation */
@@ -634,9 +760,9 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
 #define SPR_BOOKE_IAC1   (0x138)
 #define SPR_HRMOR        (0x139)
 #define SPR_BOOKE_IAC2   (0x139)
-#define SPR_HSSR0        (0x13A)
+#define SPR_HSRR0        (0x13A)
 #define SPR_BOOKE_IAC3   (0x13A)
-#define SPR_HSSR1        (0x13B)
+#define SPR_HSRR1        (0x13B)
 #define SPR_BOOKE_IAC4   (0x13B)
 #define SPR_LPCR         (0x13C)
 #define SPR_BOOKE_DAC1   (0x13C)
@@ -948,117 +1074,6 @@ enum {
     ACCESS_CACHE = 0x60, /* Cache manipulation               */
 };
 
-/*****************************************************************************/
-/* Exceptions */
-#define EXCP_NONE          -1
-/* PowerPC hardware exceptions : exception vectors defined in PowerPC book 3 */
-#define EXCP_RESET         0x0100 /* System reset                            */
-#define EXCP_MACHINE_CHECK 0x0200 /* Machine check exception                 */
-#define EXCP_DSI           0x0300 /* Data storage exception                  */
-#define EXCP_DSEG          0x0380 /* Data segment exception                  */
-#define EXCP_ISI           0x0400 /* Instruction storage exception           */
-#define EXCP_ISEG          0x0480 /* Instruction segment exception           */
-#define EXCP_EXTERNAL      0x0500 /* External interruption                   */
-#define EXCP_ALIGN         0x0600 /* Alignment exception                     */
-#define EXCP_PROGRAM       0x0700 /* Program exception                       */
-#define EXCP_NO_FP         0x0800 /* Floating point unavailable exception    */
-#define EXCP_DECR          0x0900 /* Decrementer exception                   */
-#define EXCP_HDECR         0x0980 /* Hypervisor decrementer exception        */
-#define EXCP_SYSCALL       0x0C00 /* System call                             */
-#define EXCP_TRACE         0x0D00 /* Trace exception                         */
-#define EXCP_PERF          0x0F00 /* Performance monitor exception           */
-/* Exceptions defined in PowerPC 32 bits programming environment manual      */
-#define EXCP_FP_ASSIST     0x0E00 /* Floating-point assist                   */
-/* Implementation specific exceptions                                        */
-/* 40x exceptions                                                            */
-#define EXCP_40x_PIT       0x1000 /* Programmable interval timer interrupt   */
-#define EXCP_40x_FIT       0x1010 /* Fixed interval timer interrupt          */
-#define EXCP_40x_WATCHDOG  0x1020 /* Watchdog timer exception                */
-#define EXCP_40x_DTLBMISS  0x1100 /* Data TLB miss exception                 */
-#define EXCP_40x_ITLBMISS  0x1200 /* Instruction TLB miss exception          */
-#define EXCP_40x_DEBUG     0x2000 /* Debug exception                         */
-/* 405 specific exceptions                                                   */
-#define EXCP_405_APU       0x0F20 /* APU unavailable exception               */
-/* 440 specific exceptions                                                   */
-#define EXCP_440_CRIT      0x0100 /* Critical interrupt                      */
-#define EXCP_440_SPEU      0x1600 /* SPE unavailable exception               */
-#define EXCP_440_SPED      0x1700 /* SPE floating-point data exception       */
-#define EXCP_440_SPER      0x1800 /* SPE floating-point round exception      */
-/* TLB assist exceptions (602/603)                                           */
-#define EXCP_I_TLBMISS     0x1000 /* Instruction TLB miss                    */
-#define EXCP_DL_TLBMISS    0x1100 /* Data load TLB miss                      */
-#define EXCP_DS_TLBMISS    0x1200 /* Data store TLB miss                     */
-/* Breakpoint exceptions (602/603/604/620/740/745/750/755...)                */
-#define EXCP_IABR          0x1300 /* Instruction address breakpoint          */
-#define EXCP_SMI           0x1400 /* System management interrupt             */
-/* Altivec related exceptions                                                */
-#define EXCP_VPU           0x0F20 /* VPU unavailable exception               */
-/* 601 specific exceptions                                                   */
-#define EXCP_601_IO        0x0A00 /* IO error exception                      */
-#define EXCP_601_RUNM      0x2000 /* Run mode exception                      */
-/* 602 specific exceptions                                                   */
-#define EXCP_602_WATCHDOG  0x1500 /* Watchdog exception                      */
-#define EXCP_602_EMUL      0x1600 /* Emulation trap exception                */
-/* G2 specific exceptions                                                    */
-#define EXCP_G2_CRIT       0x0A00 /* Critical interrupt                      */
-/* MPC740/745/750 & IBM 750 specific exceptions                              */
-#define EXCP_THRM          0x1700 /* Thermal management interrupt            */
-/* 74xx specific exceptions                                                  */
-#define EXCP_74xx_VPUA     0x1600 /* VPU assist exception                    */
-/* 970FX specific exceptions                                                 */
-#define EXCP_970_SOFTP     0x1500 /* Soft patch exception                    */
-#define EXCP_970_MAINT     0x1600 /* Maintenance exception                   */
-#define EXCP_970_THRM      0x1800 /* Thermal exception                       */
-#define EXCP_970_VPUA      0x1700 /* VPU assist exception                    */
-/* SPE related exceptions                                                    */
-#define EXCP_NO_SPE        0x0F20 /* SPE unavailable exception               */
-/* End of exception vectors area                                             */
-#define EXCP_PPC_MAX       0x4000
-/* Qemu exceptions: special cases we want to stop translation                */
-#define EXCP_MTMSR         0x11000 /* mtmsr instruction:                     */
-                                   /* may change privilege level             */
-#define EXCP_BRANCH        0x11001 /* branch instruction                     */
-#define EXCP_SYSCALL_USER  0x12000 /* System call in user mode only          */
-
-/* Error codes */
-enum {
-    /* Exception subtypes for EXCP_ALIGN                            */
-    EXCP_ALIGN_FP      = 0x01,  /* FP alignment exception           */
-    EXCP_ALIGN_LST     = 0x02,  /* Unaligned mult/extern load/store */
-    EXCP_ALIGN_LE      = 0x03,  /* Multiple little-endian access    */
-    EXCP_ALIGN_PROT    = 0x04,  /* Access cross protection boundary */
-    EXCP_ALIGN_BAT     = 0x05,  /* Access cross a BAT/seg boundary  */
-    EXCP_ALIGN_CACHE   = 0x06,  /* Impossible dcbz access           */
-    /* Exception subtypes for EXCP_PROGRAM                          */
-    /* FP exceptions */
-    EXCP_FP            = 0x10,
-    EXCP_FP_OX         = 0x01,  /* FP overflow                      */
-    EXCP_FP_UX         = 0x02,  /* FP underflow                     */
-    EXCP_FP_ZX         = 0x03,  /* FP divide by zero                */
-    EXCP_FP_XX         = 0x04,  /* FP inexact                       */
-    EXCP_FP_VXNAN      = 0x05,  /* FP invalid SNaN op               */
-    EXCP_FP_VXISI      = 0x06,  /* FP invalid infinite subtraction */
-    EXCP_FP_VXIDI      = 0x07,  /* FP invalid infinite divide       */
-    EXCP_FP_VXZDZ      = 0x08,  /* FP invalid zero divide           */
-    EXCP_FP_VXIMZ      = 0x09,  /* FP invalid infinite * zero       */
-    EXCP_FP_VXVC       = 0x0A,  /* FP invalid compare               */
-    EXCP_FP_VXSOFT     = 0x0B,  /* FP invalid operation             */
-    EXCP_FP_VXSQRT     = 0x0C,  /* FP invalid square root           */
-    EXCP_FP_VXCVI      = 0x0D,  /* FP invalid integer conversion    */
-    /* Invalid instruction */
-    EXCP_INVAL         = 0x20,
-    EXCP_INVAL_INVAL   = 0x01,  /* Invalid instruction              */
-    EXCP_INVAL_LSWX    = 0x02,  /* Invalid lswx instruction         */
-    EXCP_INVAL_SPR     = 0x03,  /* Invalid SPR access               */
-    EXCP_INVAL_FP      = 0x04,  /* Unimplemented mandatory fp instr */
-    /* Privileged instruction */
-    EXCP_PRIV          = 0x30,
-    EXCP_PRIV_OPC      = 0x01,  /* Privileged operation exception   */
-    EXCP_PRIV_REG      = 0x02,  /* Privileged register exception    */
-    /* Trap */
-    EXCP_TRAP          = 0x40,
-};
-
 /* Hardware interruption sources:
  * all those exception can be raised simulteaneously
  */
@@ -1130,19 +1145,22 @@ enum {
 /* Hardware exceptions definitions */
 enum {
     /* External hardware exception sources */
-    PPC_INTERRUPT_RESET  = 0,  /* Reset exception                      */
-    PPC_INTERRUPT_MCK    = 1,  /* Machine check exception              */
-    PPC_INTERRUPT_EXT    = 2,  /* External interrupt                   */
-    PPC_INTERRUPT_SMI    = 3,  /* System management interrupt          */
-    PPC_INTERRUPT_CEXT   = 4,  /* Critical external interrupt          */
-    PPC_INTERRUPT_DEBUG  = 5,  /* External debug exception             */
-    PPC_INTERRUPT_THERM  = 6,  /* Thermal exception                    */
+    PPC_INTERRUPT_RESET     = 0,  /* Reset exception                      */
+    PPC_INTERRUPT_MCK       = 1,  /* Machine check exception              */
+    PPC_INTERRUPT_EXT       = 2,  /* External interrupt                   */
+    PPC_INTERRUPT_SMI       = 3,  /* System management interrupt          */
+    PPC_INTERRUPT_CEXT      = 4,  /* Critical external interrupt          */
+    PPC_INTERRUPT_DEBUG     = 5,  /* External debug exception             */
+    PPC_INTERRUPT_THERM     = 6,  /* Thermal exception                    */
     /* Internal hardware exception sources */
-    PPC_INTERRUPT_DECR   = 7,  /* Decrementer exception                */
-    PPC_INTERRUPT_HDECR  = 8,  /* Hypervisor decrementer exception     */
-    PPC_INTERRUPT_PIT    = 9,  /* Programmable inteval timer interrupt */
-    PPC_INTERRUPT_FIT    = 10, /* Fixed interval timer interrupt       */
-    PPC_INTERRUPT_WDT    = 11, /* Watchdog timer interrupt             */
+    PPC_INTERRUPT_DECR      = 7,  /* Decrementer exception                */
+    PPC_INTERRUPT_HDECR     = 8,  /* Hypervisor decrementer exception     */
+    PPC_INTERRUPT_PIT       = 9,  /* Programmable inteval timer interrupt */
+    PPC_INTERRUPT_FIT       = 10, /* Fixed interval timer interrupt       */
+    PPC_INTERRUPT_WDT       = 11, /* Watchdog timer interrupt             */
+    PPC_INTERRUPT_CDOORBELL = 12, /* Critical doorbell interrupt          */
+    PPC_INTERRUPT_DOORBELL  = 13, /* Doorbell interrupt                   */
+    PPC_INTERRUPT_PERFM     = 14, /* Performance monitor interrupt        */
 };
 
 /*****************************************************************************/
index f27a7f50a50581ea7c8bc6aee2b1366897c3c475..8b6bed1e5197a87def79e395fd5ea6f5d117e8d3 100644 (file)
@@ -44,10 +44,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
     int exception, error_code;
 
     if (rw == 2) {
-        exception = EXCP_ISI;
+        exception = POWERPC_EXCP_ISI;
         error_code = 0;
     } else {
-        exception = EXCP_DSI;
+        exception = POWERPC_EXCP_DSI;
         error_code = 0;
         if (rw)
             error_code |= 0x02000000;
@@ -1128,6 +1128,7 @@ static int check_physical (CPUState *env, mmu_ctx_t *ctx,
                 ctx->prot |= PAGE_WRITE;
             }
         }
+        break;
     case POWERPC_MMU_BOOKE:
         ctx->prot |= PAGE_WRITE;
         break;
@@ -1250,20 +1251,20 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
             cpu_dump_state(env, logfile, fprintf, 0);
 #endif
         if (access_type == ACCESS_CODE) {
-            exception = EXCP_ISI;
+            exception = POWERPC_EXCP_ISI;
             switch (ret) {
             case -1:
                 /* No matches in page tables or TLB */
                 switch (env->mmu_model) {
                 case POWERPC_MMU_SOFT_6xx:
-                    exception = EXCP_I_TLBMISS;
+                    exception = POWERPC_EXCP_IFTLB;
                     env->spr[SPR_IMISS] = address;
                     env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
                     error_code = 1 << 18;
                     goto tlb_miss;
                 case POWERPC_MMU_SOFT_4xx:
                 case POWERPC_MMU_SOFT_4xx_Z:
-                    exception = EXCP_40x_ITLBMISS;
+                    exception = POWERPC_EXCP_ITLB;
                     error_code = 0;
                     env->spr[SPR_40x_DEAR] = address;
                     env->spr[SPR_40x_ESR] = 0x00000000;
@@ -1315,24 +1316,26 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                 /* No code fetch is allowed in direct-store areas */
                 error_code = 0x10000000;
                 break;
+#if defined(TARGET_PPC64)
             case -5:
                 /* No match in segment table */
-                exception = EXCP_ISEG;
+                exception = POWERPC_EXCP_ISEG;
                 error_code = 0;
                 break;
+#endif
             }
         } else {
-            exception = EXCP_DSI;
+            exception = POWERPC_EXCP_DSI;
             switch (ret) {
             case -1:
                 /* No matches in page tables or TLB */
                 switch (env->mmu_model) {
                 case POWERPC_MMU_SOFT_6xx:
                     if (rw == 1) {
-                        exception = EXCP_DS_TLBMISS;
+                        exception = POWERPC_EXCP_DSTLB;
                         error_code = 1 << 16;
                     } else {
-                        exception = EXCP_DL_TLBMISS;
+                        exception = POWERPC_EXCP_DLTLB;
                         error_code = 0;
                     }
                     env->spr[SPR_DMISS] = address;
@@ -1345,7 +1348,7 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                     goto out;
                 case POWERPC_MMU_SOFT_4xx:
                 case POWERPC_MMU_SOFT_4xx_Z:
-                    exception = EXCP_40x_DTLBMISS;
+                    exception = POWERPC_EXCP_DTLB;
                     error_code = 0;
                     env->spr[SPR_40x_DEAR] = address;
                     if (rw)
@@ -1396,8 +1399,8 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                 switch (access_type) {
                 case ACCESS_FLOAT:
                     /* Floating point load/store */
-                    exception = EXCP_ALIGN;
-                    error_code = EXCP_ALIGN_FP;
+                    exception = POWERPC_EXCP_ALIGN;
+                    error_code = POWERPC_EXCP_ALIGN_FP;
                     break;
                 case ACCESS_RES:
                     /* lwarx, ldarx or srwcx. */
@@ -1409,18 +1412,20 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                     break;
                 default:
                     printf("DSI: invalid exception (%d)\n", ret);
-                    exception = EXCP_PROGRAM;
-                    error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
+                    exception = POWERPC_EXCP_PROGRAM;
+                    error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
                     break;
                 }
                 break;
+#if defined(TARGET_PPC64)
             case -5:
                 /* No match in segment table */
-                exception = EXCP_DSEG;
+                exception = POWERPC_EXCP_DSEG;
                 error_code = 0;
                 break;
+#endif
             }
-            if (exception == EXCP_DSI && rw == 1)
+            if (exception == POWERPC_EXCP_DSI && rw == 1)
                 error_code |= 0x02000000;
             /* Store fault address */
             env->spr[SPR_DAR] = address;
@@ -1830,12 +1835,14 @@ void do_compute_hflags (CPUPPCState *env)
 #if defined (CONFIG_USER_ONLY)
 void do_interrupt (CPUState *env)
 {
-    env->exception_index = -1;
+    env->exception_index = POWERPC_EXCP_NONE;
+    env->error_code = 0;
 }
 
 void ppc_hw_interrupt (CPUState *env)
 {
-    env->exception_index = -1;
+    env->exception_index = POWERPC_EXCP_NONE;
+    env->error_code = 0;
 }
 #else /* defined (CONFIG_USER_ONLY) */
 static void dump_syscall (CPUState *env)
@@ -1846,126 +1853,122 @@ static void dump_syscall (CPUState *env)
             env->gpr[5], env->gpr[6], env->nip);
 }
 
-void do_interrupt (CPUState *env)
+/* Note that this function should be greatly optimized
+ * when called with a constant excp, from ppc_hw_interrupt
+ */
+static always_inline void powerpc_excp (CPUState *env,
+                                        int excp_model, int excp)
 {
-    target_ulong msr, *srr_0, *srr_1, *asrr_0, *asrr_1;
-    int excp, idx;
+    target_ulong msr, vector;
+    int srr0, srr1, asrr0, asrr1;
 
-    excp = env->exception_index;
-    msr = do_load_msr(env);
-    /* The default is to use SRR0 & SRR1 to save the exception context */
-    srr_0 = &env->spr[SPR_SRR0];
-    srr_1 = &env->spr[SPR_SRR1];
-    asrr_0 = NULL;
-    asrr_1 = NULL;
-#if defined (DEBUG_EXCEPTIONS)
-    if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) {
-        if (loglevel != 0) {
-            fprintf(logfile,
-                    "Raise exception at 0x" ADDRX " => 0x%08x (%02x)\n",
-                    env->nip, excp, env->error_code);
-            cpu_dump_state(env, logfile, fprintf, 0);
-        }
-    }
-#endif
     if (loglevel & CPU_LOG_INT) {
         fprintf(logfile, "Raise exception at 0x" ADDRX " => 0x%08x (%02x)\n",
                 env->nip, excp, env->error_code);
     }
-    msr_pow = 0;
-    idx = -1;
-    /* Generate informations in save/restore registers */
+    msr = do_load_msr(env);
+    srr0 = SPR_SRR0;
+    srr1 = SPR_SRR1;
+    asrr0 = -1;
+    asrr1 = -1;
+    msr &= ~((target_ulong)0x783F0000);
     switch (excp) {
-    /* Generic PowerPC exceptions */
-    case EXCP_RESET: /* 0x0100 */
-        switch (env->excp_model) {
+    case POWERPC_EXCP_NONE:
+        /* Should never happen */
+        return;
+    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
+        msr_ri = 0; /* XXX: check this */
+        switch (excp_model) {
         case POWERPC_EXCP_40x:
-            srr_0 = &env->spr[SPR_40x_SRR2];
-            srr_1 = &env->spr[SPR_40x_SRR3];
+            srr0 = SPR_40x_SRR2;
+            srr1 = SPR_40x_SRR3;
             break;
         case POWERPC_EXCP_BOOKE:
-            idx = 0;
-            srr_0 = &env->spr[SPR_BOOKE_CSRR0];
-            srr_1 = &env->spr[SPR_BOOKE_CSRR1];
+            srr0 = SPR_BOOKE_CSRR0;
+            srr1 = SPR_BOOKE_CSRR1;
             break;
-        default:
-            if (msr_ip)
-                excp += 0xFFC00;
-            excp |= 0xFFC00000;
+        case POWERPC_EXCP_G2:
             break;
+        default:
+            goto excp_invalid;
         }
         goto store_next;
-    case EXCP_MACHINE_CHECK: /* 0x0200 */
-        switch (env->excp_model) {
+    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
+        if (msr_me == 0) {
+            /* Machine check exception is not enabled */
+            /* XXX: we may just stop the processor here, to allow debugging */
+            excp = POWERPC_EXCP_RESET;
+            goto excp_reset;
+        }
+        msr_ri = 0;
+        msr_me = 0;
+#if defined(TARGET_PPC64H)
+        msr_hv = 1;
+#endif
+        /* XXX: should also have something loaded in DAR / DSISR */
+        switch (excp_model) {
         case POWERPC_EXCP_40x:
-            srr_0 = &env->spr[SPR_40x_SRR2];
-            srr_1 = &env->spr[SPR_40x_SRR3];
+            srr0 = SPR_40x_SRR2;
+            srr1 = SPR_40x_SRR3;
             break;
         case POWERPC_EXCP_BOOKE:
-            idx = 1;
-            srr_0 = &env->spr[SPR_BOOKE_MCSRR0];
-            srr_1 = &env->spr[SPR_BOOKE_MCSRR1];
-            asrr_0 = &env->spr[SPR_BOOKE_CSRR0];
-            asrr_1 = &env->spr[SPR_BOOKE_CSRR1];
-            msr_ce = 0;
+            srr0 = SPR_BOOKE_MCSRR0;
+            srr1 = SPR_BOOKE_MCSRR1;
+            asrr0 = SPR_BOOKE_CSRR0;
+            asrr1 = SPR_BOOKE_CSRR1;
             break;
         default:
             break;
         }
-        msr_me = 0;
-        break;
-    case EXCP_DSI: /* 0x0300 */
-        /* Store exception cause */
-        /* data location address has been stored
-         * when the fault has been detected
-         */
-        idx = 2;
-        msr &= ~0xFFFF0000;
+        goto store_next;
+    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
 #if defined (DEBUG_EXCEPTIONS)
         if (loglevel != 0) {
             fprintf(logfile, "DSI exception: DSISR=0x" ADDRX" DAR=0x" ADDRX
                     "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
         }
+#endif
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            msr_hv = 1;
 #endif
         goto store_next;
-    case EXCP_ISI: /* 0x0400 */
-        /* Store exception cause */
-        idx = 3;
-        msr &= ~0xFFFF0000;
-        msr |= env->error_code;
+    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
 #if defined (DEBUG_EXCEPTIONS)
         if (loglevel != 0) {
             fprintf(logfile, "ISI exception: msr=0x" ADDRX ", nip=0x" ADDRX
                     "\n", msr, env->nip);
         }
 #endif
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            msr_hv = 1;
+#endif
+        msr |= env->error_code;
         goto store_next;
-    case EXCP_EXTERNAL: /* 0x0500 */
-        idx = 4;
+    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes0 == 1)
+            msr_hv = 1;
+#endif
         goto store_next;
-    case EXCP_ALIGN: /* 0x0600 */
-        if (likely(env->excp_model != POWERPC_EXCP_601)) {
-            /* Store exception cause */
-            idx = 5;
-            /* Get rS/rD and rA from faulting opcode */
-            env->spr[SPR_DSISR] |=
-                (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
-            /* data location address has been stored
-             * when the fault has been detected
-             */
-        } else {
-            /* IO error exception on PowerPC 601 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "601 IO error exception is not implemented yet !\n");
-        }
+    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            msr_hv = 1;
+#endif
+        /* XXX: this is false */
+        /* Get rS/rD and rA from faulting opcode */
+        env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
         goto store_current;
-    case EXCP_PROGRAM: /* 0x0700 */
-        idx = 6;
-        msr &= ~0xFFFF0000;
+    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
         switch (env->error_code & ~0xF) {
-        case EXCP_FP:
-            if (msr_fe0 == 0 && msr_fe1 == 0) {
+        case POWERPC_EXCP_FP:
+            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
 #if defined (DEBUG_EXCEPTIONS)
                 if (loglevel != 0) {
                     fprintf(logfile, "Ignore floating point exception\n");
@@ -1973,6 +1976,11 @@ void do_interrupt (CPUState *env)
 #endif
                 return;
             }
+            msr_ri = 0;
+#if defined(TARGET_PPC64H)
+            if (lpes1 == 0)
+                msr_hv = 1;
+#endif
             msr |= 0x00100000;
             /* Set FX */
             env->fpscr[7] |= 0x8;
@@ -1980,39 +1988,59 @@ void do_interrupt (CPUState *env)
             if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
                 ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
                 env->fpscr[7] |= 0x4;
+            if (msr_fe0 != msr_fe1) {
+                msr |= 0x00010000;
+                goto store_current;
+            }
             break;
-        case EXCP_INVAL:
+        case POWERPC_EXCP_INVAL:
 #if defined (DEBUG_EXCEPTIONS)
             if (loglevel != 0) {
                 fprintf(logfile, "Invalid instruction at 0x" ADDRX "\n",
                         env->nip);
             }
+#endif
+            msr_ri = 0;
+#if defined(TARGET_PPC64H)
+            if (lpes1 == 0)
+                msr_hv = 1;
 #endif
             msr |= 0x00080000;
             break;
-        case EXCP_PRIV:
+        case POWERPC_EXCP_PRIV:
+            msr_ri = 0;
+#if defined(TARGET_PPC64H)
+            if (lpes1 == 0)
+                msr_hv = 1;
+#endif
             msr |= 0x00040000;
             break;
-        case EXCP_TRAP:
-            idx = 15;
+        case POWERPC_EXCP_TRAP:
+            msr_ri = 0;
+#if defined(TARGET_PPC64H)
+            if (lpes1 == 0)
+                msr_hv = 1;
+#endif
             msr |= 0x00020000;
             break;
         default:
             /* Should never occur */
+            cpu_abort(env, "Invalid program exception %d. Aborting\n",
+                      env->error_code);
             break;
         }
-        msr |= 0x00010000;
-        goto store_current;
-    case EXCP_NO_FP: /* 0x0800 */
-        idx = 7;
-        msr &= ~0xFFFF0000;
-        goto store_current;
-    case EXCP_DECR:
         goto store_next;
-    case EXCP_SYSCALL: /* 0x0C00 */
-        idx = 8;
+    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            msr_hv = 1;
+#endif
+        goto store_current;
+    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
         /* NOTE: this is a temporary hack to support graphics OSI
            calls from the MOL driver */
+        /* XXX: To be removed */
         if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
             env->osi_call) {
             if (env->osi_call(env) != 0)
@@ -2021,166 +2049,254 @@ void do_interrupt (CPUState *env)
         if (loglevel & CPU_LOG_INT) {
             dump_syscall(env);
         }
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
+            msr_hv = 1;
+#endif
+        goto store_next;
+    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
+        msr_ri = 0;
+        goto store_current;
+    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            msr_hv = 1;
+#endif
+        goto store_next;
+    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
+        /* FIT on 4xx */
+#if defined (DEBUG_EXCEPTIONS)
+        if (loglevel != 0)
+            fprintf(logfile, "FIT exception\n");
+#endif
+        msr_ri = 0; /* XXX: check this */
         goto store_next;
-    case EXCP_TRACE: /* 0x0D00 */
+    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
+#if defined (DEBUG_EXCEPTIONS)
+        if (loglevel != 0)
+            fprintf(logfile, "WDT exception\n");
+#endif
+        switch (excp_model) {
+        case POWERPC_EXCP_BOOKE:
+            srr0 = SPR_BOOKE_CSRR0;
+            srr1 = SPR_BOOKE_CSRR1;
+            break;
+        default:
+            break;
+        }
+        msr_ri = 0; /* XXX: check this */
         goto store_next;
-    case EXCP_PERF: /* 0x0F00 */
+    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
+        msr_ri = 0; /* XXX: check this */
+        goto store_next;
+    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
+        msr_ri = 0; /* XXX: check this */
+        goto store_next;
+    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
+        switch (excp_model) {
+        case POWERPC_EXCP_BOOKE:
+            srr0 = SPR_BOOKE_DSRR0;
+            srr1 = SPR_BOOKE_DSRR1;
+            asrr0 = SPR_BOOKE_CSRR0;
+            asrr1 = SPR_BOOKE_CSRR1;
+            break;
+        default:
+            break;
+        }
         /* XXX: TODO */
-        cpu_abort(env,
-                  "Performance counter exception is not implemented yet !\n");
+        cpu_abort(env, "Debug exception is not implemented yet !\n");
         goto store_next;
-    /* 32 bits PowerPC specific exceptions */
-    case EXCP_FP_ASSIST: /* 0x0E00 */
+#if defined(TARGET_PPCEMB)
+    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
+        msr_ri = 0; /* XXX: check this */
+        goto store_current;
+    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
         /* XXX: TODO */
-        cpu_abort(env, "Floating point assist exception "
+        cpu_abort(env, "Embedded floating point data exception "
                   "is not implemented yet !\n");
         goto store_next;
-    /* 64 bits PowerPC exceptions */
-    case EXCP_DSEG: /* 0x0380 */
+    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
         /* XXX: TODO */
-        cpu_abort(env, "Data segment exception is not implemented yet !\n");
+        cpu_abort(env, "Embedded floating point round exception "
+                  "is not implemented yet !\n");
         goto store_next;
-    case EXCP_ISEG: /* 0x0480 */
+    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
+        msr_ri = 0;
         /* XXX: TODO */
         cpu_abort(env,
-                  "Instruction segment exception is not implemented yet !\n");
+                  "Performance counter exception is not implemented yet !\n");
         goto store_next;
-    case EXCP_HDECR: /* 0x0980 */
+    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
         /* XXX: TODO */
-        cpu_abort(env, "Hypervisor decrementer exception is not implemented "
-                  "yet !\n");
+        cpu_abort(env,
+                  "Embedded doorbell interrupt is not implemented yet !\n");
         goto store_next;
-    /* Implementation specific exceptions */
-    case 0x0A00:
-        switch (env->excp_model) {
-        case POWERPC_EXCP_G2:
-            /* Critical interrupt on G2 */
-            /* XXX: TODO */
-            cpu_abort(env, "G2 critical interrupt is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x0A00 !\n");
+    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
+        switch (excp_model) {
+        case POWERPC_EXCP_BOOKE:
+            srr0 = SPR_BOOKE_CSRR0;
+            srr1 = SPR_BOOKE_CSRR1;
             break;
-        }
-        return;
-    case 0x0F20:
-        idx = 9;
-        switch (env->excp_model) {
-        case POWERPC_EXCP_40x:
-            /* APU unavailable on 405 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "APU unavailable exception is not implemented yet !\n");
-            goto store_next;
-        case POWERPC_EXCP_74xx:
-            /* Altivec unavailable */
-            /* XXX: TODO */
-            cpu_abort(env, "Altivec unavailable exception "
-                      "is not implemented yet !\n");
-            goto store_next;
         default:
-            cpu_abort(env, "Invalid exception 0x0F20 !\n");
             break;
         }
-        return;
-    case 0x1000:
-        idx = 10;
-        switch (env->excp_model) {
-        case POWERPC_EXCP_40x:
-            /* PIT on 4xx */
-            msr &= ~0xFFFF0000;
+        /* XXX: TODO */
+        cpu_abort(env, "Embedded doorbell critical interrupt "
+                  "is not implemented yet !\n");
+        goto store_next;
+#endif /* defined(TARGET_PPCEMB) */
+    case POWERPC_EXCP_RESET:     /* System reset exception                   */
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        msr_hv = 1;
+#endif
+    excp_reset:
+        goto store_next;
+#if defined(TARGET_PPC64)
+    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            msr_hv = 1;
+#endif
+        /* XXX: TODO */
+        cpu_abort(env, "Data segment exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            msr_hv = 1;
+#endif
+        /* XXX: TODO */
+        cpu_abort(env,
+                  "Instruction segment exception is not implemented yet !\n");
+        goto store_next;
+#endif /* defined(TARGET_PPC64) */
+#if defined(TARGET_PPC64H)
+    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
+        srr0 = SPR_HSRR0;
+        srr1 = SPR_HSSR1;
+        msr_hv = 1;
+        goto store_next;
+#endif
+    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            msr_hv = 1;
+#endif
+        goto store_next;
+#if defined(TARGET_PPC64H)
+    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
+        srr0 = SPR_HSRR0;
+        srr1 = SPR_HSSR1;
+        msr_hv = 1;
+        goto store_next;
+    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
+        srr0 = SPR_HSRR0;
+        srr1 = SPR_HSSR1;
+        msr_hv = 1;
+        /* XXX: TODO */
+        cpu_abort(env, "Hypervisor instruction storage exception "
+                  "is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
+        srr0 = SPR_HSRR0;
+        srr1 = SPR_HSSR1;
+        msr_hv = 1;
+        goto store_next;
+    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
+        srr0 = SPR_HSRR0;
+        srr1 = SPR_HSSR1;
+        msr_hv = 1;
+        goto store_next;
+#endif /* defined(TARGET_PPC64H) */
+    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            msr_hv = 1;
+#endif
+        goto store_current;
+    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
 #if defined (DEBUG_EXCEPTIONS)
-            if (loglevel != 0)
-                fprintf(logfile, "PIT exception\n");
+        if (loglevel != 0)
+            fprintf(logfile, "PIT exception\n");
+#endif
+        msr_ri = 0; /* XXX: check this */
+        goto store_next;
+    case POWERPC_EXCP_IO:        /* IO error exception                       */
+        /* XXX: TODO */
+        cpu_abort(env, "601 IO error exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
+        /* XXX: TODO */
+        cpu_abort(env, "601 run mode exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
+        /* XXX: TODO */
+        cpu_abort(env, "602 emulation trap exception "
+                  "is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
+        msr_ri = 0; /* XXX: check this */
+#if defined(TARGET_PPC64H) /* XXX: check this */
+        if (lpes1 == 0)
+            msr_hv = 1;
 #endif
-            goto store_next;
+        switch (excp_model) {
         case POWERPC_EXCP_602:
         case POWERPC_EXCP_603:
         case POWERPC_EXCP_603E:
         case POWERPC_EXCP_G2:
-            /* ITLBMISS on 602/603 */
-            goto store_gprs;
+            goto tlb_miss_tgpr;
         case POWERPC_EXCP_7x5:
-            /* ITLBMISS on 745/755 */
             goto tlb_miss;
         default:
-            cpu_abort(env, "Invalid exception 0x1000 !\n");
-            break;
-        }
-        return;
-    case 0x1010:
-        idx = 11;
-        switch (env->excp_model) {
-        case POWERPC_EXCP_40x:
-            /* FIT on 4xx */
-            msr &= ~0xFFFF0000;
-#if defined (DEBUG_EXCEPTIONS)
-            if (loglevel != 0)
-                fprintf(logfile, "FIT exception\n");
-#endif
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1010 !\n");
+            cpu_abort(env, "Invalid instruction TLB miss exception\n");
             break;
         }
-        return;
-    case 0x1020:
-        idx = 12;
-        switch (env->excp_model) {
-        case POWERPC_EXCP_40x:
-            /* Watchdog on 4xx */
-            msr &= ~0xFFFF0000;
-#if defined (DEBUG_EXCEPTIONS)
-            if (loglevel != 0)
-                fprintf(logfile, "WDT exception\n");
+        break;
+    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
+        msr_ri = 0; /* XXX: check this */
+#if defined(TARGET_PPC64H) /* XXX: check this */
+        if (lpes1 == 0)
+            msr_hv = 1;
 #endif
-            goto store_next;
-        case POWERPC_EXCP_BOOKE:
-            srr_0 = &env->spr[SPR_BOOKE_CSRR0];
-            srr_1 = &env->spr[SPR_BOOKE_CSRR1];
-            break;
-        default:
-            cpu_abort(env, "Invalid exception 0x1020 !\n");
-            break;
-        }
-        return;
-    case 0x1100:
-        idx = 13;
-        switch (env->excp_model) {
-        case POWERPC_EXCP_40x:
-            /* DTLBMISS on 4xx */
-            msr &= ~0xFFFF0000;
-            goto store_next;
+        switch (excp_model) {
         case POWERPC_EXCP_602:
         case POWERPC_EXCP_603:
         case POWERPC_EXCP_603E:
         case POWERPC_EXCP_G2:
-            /* DLTLBMISS on 602/603 */
-            goto store_gprs;
+            goto tlb_miss_tgpr;
         case POWERPC_EXCP_7x5:
-            /* DLTLBMISS on 745/755 */
             goto tlb_miss;
         default:
-            cpu_abort(env, "Invalid exception 0x1100 !\n");
+            cpu_abort(env, "Invalid data load TLB miss exception\n");
             break;
         }
-        return;
-    case 0x1200:
-        idx = 14;
-        switch (env->excp_model) {
-        case POWERPC_EXCP_40x:
-            /* ITLBMISS on 4xx */
-            msr &= ~0xFFFF0000;
-            goto store_next;
+        break;
+    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
+        msr_ri = 0; /* XXX: check this */
+#if defined(TARGET_PPC64H) /* XXX: check this */
+        if (lpes1 == 0)
+            msr_hv = 1;
+#endif
+        switch (excp_model) {
         case POWERPC_EXCP_602:
         case POWERPC_EXCP_603:
         case POWERPC_EXCP_603E:
         case POWERPC_EXCP_G2:
-            /* DSTLBMISS on 602/603 */
-        store_gprs:
+        tlb_miss_tgpr:
             /* Swap temporary saved registers with GPRs */
             swap_gpr_tgpr(env);
             msr_tgpr = 1;
+            goto tlb_miss;
+        case POWERPC_EXCP_7x5:
+        tlb_miss:
 #if defined (DEBUG_SOFTWARE_TLB)
             if (loglevel != 0) {
                 const unsigned char *es;
@@ -2207,183 +2323,81 @@ void do_interrupt (CPUState *env)
                         env->error_code);
             }
 #endif
-            goto tlb_miss;
-        case POWERPC_EXCP_7x5:
-            /* DSTLBMISS on 745/755 */
-        tlb_miss:
-            msr &= ~0xF83F0000;
             msr |= env->crf[0] << 28;
             msr |= env->error_code; /* key, D/I, S/L bits */
             /* Set way using a LRU mechanism */
             msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1200 !\n");
-            break;
-        }
-        return;
-    case 0x1300:
-        switch (env->excp_model) {
-        case POWERPC_EXCP_601:
-        case POWERPC_EXCP_602:
-        case POWERPC_EXCP_603:
-        case POWERPC_EXCP_603E:
-        case POWERPC_EXCP_G2:
-        case POWERPC_EXCP_604:
-        case POWERPC_EXCP_7x0:
-        case POWERPC_EXCP_7x5:
-            /* IABR on 6xx/7xx */
-            /* XXX: TODO */
-            cpu_abort(env, "IABR exception is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1300 !\n");
-            break;
-        }
-        return;
-    case 0x1400:
-        switch (env->excp_model) {
-        case POWERPC_EXCP_601:
-        case POWERPC_EXCP_602:
-        case POWERPC_EXCP_603:
-        case POWERPC_EXCP_603E:
-        case POWERPC_EXCP_G2:
-        case POWERPC_EXCP_604:
-        case POWERPC_EXCP_7x0:
-        case POWERPC_EXCP_7x5:
-            /* SMI on 6xx/7xx */
-            /* XXX: TODO */
-            cpu_abort(env, "SMI exception is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1400 !\n");
-            break;
-        }
-        return;
-    case 0x1500:
-        switch (env->excp_model) {
-        case POWERPC_EXCP_602:
-            /* Watchdog on 602 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "602 watchdog exception is not implemented yet !\n");
-            goto store_next;
-        case POWERPC_EXCP_970:
-            /* Soft patch exception on 970 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "970 soft-patch exception is not implemented yet !\n");
-            goto store_next;
-        case POWERPC_EXCP_74xx:
-            /* VPU assist on 74xx */
-            /* XXX: TODO */
-            cpu_abort(env, "VPU assist exception is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1500 !\n");
-            break;
-        }
-        return;
-    case 0x1600:
-        switch (env->excp_model) {
-        case POWERPC_EXCP_602:
-            /* Emulation trap on 602 */
-            /* XXX: TODO */
-            cpu_abort(env, "602 emulation trap exception "
-                      "is not implemented yet !\n");
-            goto store_next;
-        case POWERPC_EXCP_970:
-            /* Maintenance exception on 970 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "970 maintenance exception is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1600 !\n");
-            break;
-        }
-        return;
-    case 0x1700:
-        switch (env->excp_model) {
-        case POWERPC_EXCP_7x0:
-        case POWERPC_EXCP_7x5:
-            /* Thermal management interrupt on G3 */
-            /* XXX: TODO */
-            cpu_abort(env, "G3 thermal management exception "
-                      "is not implemented yet !\n");
-            goto store_next;
-        case POWERPC_EXCP_970:
-            /* VPU assist on 970 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "970 VPU assist exception is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1700 !\n");
-            break;
-        }
-        return;
-    case 0x1800:
-        switch (env->excp_model) {
-        case POWERPC_EXCP_970:
-            /* Thermal exception on 970 */
-            /* XXX: TODO */
-            cpu_abort(env, "970 thermal management exception "
-                      "is not implemented yet !\n");
-            goto store_next;
-        default:
-            cpu_abort(env, "Invalid exception 0x1800 !\n");
-            break;
-        }
-        return;
-    case 0x2000:
-        switch (env->excp_model) {
-        case POWERPC_EXCP_40x:
-            /* DEBUG on 4xx */
-            /* XXX: TODO */
-            cpu_abort(env, "40x debug exception is not implemented yet !\n");
-            goto store_next;
-        case POWERPC_EXCP_601:
-            /* Run mode exception on 601 */
-            /* XXX: TODO */
-            cpu_abort(env,
-                      "601 run mode exception is not implemented yet !\n");
-            goto store_next;
-        case POWERPC_EXCP_BOOKE:
-            srr_0 = &env->spr[SPR_BOOKE_CSRR0];
-            srr_1 = &env->spr[SPR_BOOKE_CSRR1];
             break;
         default:
-            cpu_abort(env, "Invalid exception 0x1800 !\n");
+            cpu_abort(env, "Invalid data store TLB miss exception\n");
             break;
         }
-        return;
-    /* Other exceptions */
-    /* Qemu internal exceptions:
-     * we should never come here with those values: abort execution
-     */
+        goto store_next;
+    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
+        /* XXX: TODO */
+        cpu_abort(env, "Floating point assist exception "
+                  "is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
+        /* XXX: TODO */
+        cpu_abort(env, "IABR exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_SMI:       /* System management interrupt              */
+        /* XXX: TODO */
+        cpu_abort(env, "SMI exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
+        /* XXX: TODO */
+        cpu_abort(env, "Thermal management exception "
+                  "is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
+        msr_ri = 0;
+#if defined(TARGET_PPC64H)
+        if (lpes1 == 0)
+            msr_hv = 1;
+#endif
+        /* XXX: TODO */
+        cpu_abort(env,
+                  "Performance counter exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
+        /* XXX: TODO */
+        cpu_abort(env, "VPU assist exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
+        /* XXX: TODO */
+        cpu_abort(env,
+                  "970 soft-patch exception is not implemented yet !\n");
+        goto store_next;
+    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
+        /* XXX: TODO */
+        cpu_abort(env,
+                  "970 maintenance exception is not implemented yet !\n");
+        goto store_next;
     default:
-        cpu_abort(env, "Invalid exception: code %d (%04x)\n", excp, excp);
-        return;
+    excp_invalid:
+        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
+        break;
     store_current:
         /* save current instruction location */
-        *srr_0 = env->nip - 4;
+        env->spr[srr0] = env->nip - 4;
         break;
     store_next:
         /* save next instruction location */
-        *srr_0 = env->nip;
+        env->spr[srr0] = env->nip;
         break;
     }
-    /* Save msr */
-    *srr_1 = msr;
-    if (asrr_0 != NULL)
-        *asrr_0 = *srr_0;
-    if (asrr_1 != NULL)
-        *asrr_1 = *srr_1;
+    /* Save MSR */
+    env->spr[srr1] = msr;
+    /* If any alternate SRR register are defined, duplicate saved values */
+    if (asrr0 != -1)
+        env->spr[asrr0] = env->spr[srr0];
+    if (asrr1 != -1)
+        env->spr[asrr1] = env->spr[srr1];
     /* If we disactivated any translation, flush TLBs */
-    if (msr_ir || msr_dr) {
+    if (msr_ir || msr_dr)
         tlb_flush(env, 1);
-    }
     /* reload MSR with correct bits */
     msr_ee = 0;
     msr_pr = 0;
@@ -2394,37 +2408,42 @@ void do_interrupt (CPUState *env)
     msr_fe1 = 0;
     msr_ir = 0;
     msr_dr = 0;
-    msr_ri = 0;
+#if 0 /* Fix this: not on all targets */
+    msr_pmm = 0;
+#endif
     msr_le = msr_ile;
-    if (env->excp_model == POWERPC_EXCP_BOOKE) {
-        msr_cm = msr_icm;
-        if (idx == -1 || (idx >= 16 && idx < 32)) {
-            cpu_abort(env, "Invalid exception index for excp %d %08x idx %d\n",
-                      excp, excp, idx);
-        }
+    do_compute_hflags(env);
+    /* Jump to handler */
+    vector = env->excp_vectors[excp];
+    if (vector == (target_ulong)-1) {
+        cpu_abort(env, "Raised an exception without defined vector %d\n",
+                  excp);
+    }
+    vector |= env->excp_prefix;
 #if defined(TARGET_PPC64)
-        if (msr_cm)
-            env->nip = (uint64_t)env->spr[SPR_BOOKE_IVPR];
-        else
-#endif
-            env->nip = (uint32_t)env->spr[SPR_BOOKE_IVPR];
-        if (idx < 16)
-            env->nip |= env->spr[SPR_BOOKE_IVOR0 + idx];
-        else if (idx < 38)
-            env->nip |= env->spr[SPR_BOOKE_IVOR32 + idx - 32];
+    if (excp_model == POWERPC_EXCP_BOOKE) {
+        msr_cm = msr_icm;
+        if (!msr_cm)
+            vector = (uint32_t)vector;
     } else {
         msr_sf = msr_isf;
-        env->nip = excp;
+        if (!msr_sf)
+            vector = (uint32_t)vector;
     }
-    do_compute_hflags(env);
-    /* Jump to handler */
-    env->exception_index = EXCP_NONE;
+#endif
+    env->nip = vector;
+    /* Reset exception state */
+    env->exception_index = POWERPC_EXCP_NONE;
+    env->error_code = 0;
 }
 
-void ppc_hw_interrupt (CPUPPCState *env)
+void do_interrupt (CPUState *env)
 {
-    int raised = 0;
+    powerpc_excp(env, env->excp_model, env->exception_index);
+}
 
+void ppc_hw_interrupt (CPUPPCState *env)
+{
 #if 1
     if (loglevel & CPU_LOG_INT) {
         fprintf(logfile, "%s: %p pending %08x req %08x me %d ee %d\n",
@@ -2432,82 +2451,125 @@ void ppc_hw_interrupt (CPUPPCState *env)
                 env->interrupt_request, msr_me, msr_ee);
     }
 #endif
-    /* Raise it */
+    /* External reset */
     if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
-        /* External reset / critical input */
-        /* XXX: critical input should be handled another way.
-         *      This code is not correct !
-         */
-        env->exception_index = EXCP_RESET;
         env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
-        raised = 1;
-    }
-    if (raised == 0 && msr_me != 0) {
-        /* Machine check exception */
-        if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
-            env->exception_index = EXCP_MACHINE_CHECK;
-            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
-            raised = 1;
-        }
+        powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
+        return;
+    }
+    /* Machine check exception */
+    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
+        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
+        powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
+        return;
     }
-    if (raised == 0 && msr_ee != 0) {
-#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+#if 0 /* TODO */
+    /* External debug exception */
+    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
+        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
+        powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
+        return;
+    }
+#endif
+#if defined(TARGET_PPC64H)
+    if ((msr_ee != 0 || msr_hv == 0 || msr_pr == 1) & hdice != 0) {
         /* Hypervisor decrementer exception */
         if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
-            env->exception_index = EXCP_HDECR;
             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
-            raised = 1;
-        } else
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
+            return;
+        }
+    }
+#endif
+    if (msr_ce != 0) {
+        /* External critical interrupt */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
+            /* Taking a critical external interrupt does not clear the external
+             * critical interrupt status
+             */
+#if 0
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
 #endif
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
+            return;
+        }
+    }
+    if (msr_ee != 0) {
+        /* Watchdog timer on embedded PowerPC */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
+            return;
+        }
+#if defined(TARGET_PPCEMB)
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
+            return;
+        }
+#endif
+#if defined(TARGET_PPCEMB)
+        /* External interrupt */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
+            /* Taking an external interrupt does not clear the external
+             * interrupt status
+             */
+#if 0
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
+#endif
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
+            return;
+        }
+#endif
+        /* Fixed interval timer on embedded PowerPC */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
+            return;
+        }
+        /* Programmable interval timer on embedded PowerPC */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
+            return;
+        }
         /* Decrementer exception */
         if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
-            env->exception_index = EXCP_DECR;
             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
-            raised = 1;
-        /* Programmable interval timer on embedded PowerPC */
-        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
-            env->exception_index = EXCP_40x_PIT;
-            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
-            raised = 1;
-        /* Fixed interval timer on embedded PowerPC */
-        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
-            env->exception_index = EXCP_40x_FIT;
-            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
-            raised = 1;
-        /* Watchdog timer on embedded PowerPC */
-        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
-            env->exception_index = EXCP_40x_WATCHDOG;
-            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
-            raised = 1;
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
+            return;
+        }
+#if !defined(TARGET_PPCEMB)
         /* External interrupt */
-        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
-            env->exception_index = EXCP_EXTERNAL;
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
             /* Taking an external interrupt does not clear the external
              * interrupt status
              */
 #if 0
             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
 #endif
-            raised = 1;
-#if 0 // TODO
-        /* Thermal interrupt */
-        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
-            env->exception_index = EXCP_970_THRM;
-            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
-            raised = 1;
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
+            return;
+        }
 #endif
+#if defined(TARGET_PPCEMB)
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
+            return;
         }
-#if 0 // TODO
-    /* External debug exception */
-    } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
-        env->exception_index = EXCP_xxx;
-        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
-        raised = 1;
 #endif
-    }
-    if (raised != 0) {
-        env->error_code = 0;
-        do_interrupt(env);
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
+            return;
+        }
+        /* Thermal interrupt */
+        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
+            powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
+            return;
+        }
     }
 }
 #endif /* !CONFIG_USER_ONLY */
@@ -2572,7 +2634,8 @@ void cpu_ppc_reset (void *opaque)
     env->reserve = -1;
     /* Be sure no exception or interrupt is pending */
     env->pending_interrupts = 0;
-    env->exception_index = EXCP_NONE;
+    env->exception_index = POWERPC_EXCP_NONE;
+    env->error_code = 0;
     /* Flush all TLBs */
     tlb_flush(env, 1);
 }
index df00ba19c757c1cf781a92cd895ec351483fc427..9a79953f7d8a60d264be844af8e7e0f55d27b457 100644 (file)
@@ -47,8 +47,8 @@ void do_raise_exception_err (uint32_t exception, int error_code)
     printf("Raise exception %3x code : %d\n", exception, error_code);
 #endif
     switch (exception) {
-    case EXCP_PROGRAM:
-        if (error_code == EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
+    case POWERPC_EXCP_PROGRAM:
+        if (error_code == POWERPC_EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
             return;
         break;
     default:
@@ -947,7 +947,7 @@ void do_tw (int flags)
                   ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) ||
                   ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) ||
                   ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) {
-        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
     }
 }
 
@@ -959,7 +959,7 @@ void do_td (int flags)
                   ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) ||
                   ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) ||
                   ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01)))))
-        do_raise_exception_err(EXCP_PROGRAM, EXCP_TRAP);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);
 }
 #endif
 
@@ -1215,12 +1215,14 @@ void do_load_dcr (void)
         if (loglevel != 0) {
             fprintf(logfile, "No DCR environment\n");
         }
-        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
     } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
         if (loglevel != 0) {
             fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
         }
-        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
     } else {
         T0 = val;
     }
@@ -1232,12 +1234,14 @@ void do_store_dcr (void)
         if (loglevel != 0) {
             fprintf(logfile, "No DCR environment\n");
         }
-        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                               POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
     } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
         if (loglevel != 0) {
             fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
         }
-        do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
+        do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                               POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
     }
 }
 
index f1229859f3c91751c84a265e4fac0b6b43ebaba1..13440817bf344c5575d48a1521710a574c0667ca 100644 (file)
@@ -296,7 +296,9 @@ void OPPROTO glue(op_lswx, MEMSUFFIX) (void)
     if (likely(T1 != 0)) {
         if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
                      (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
-            do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
+            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL |
+                                   POWERPC_EXCP_INVAL_LSWX);
         } else {
             glue(do_lsw, MEMSUFFIX)(PARAM1);
         }
@@ -311,7 +313,9 @@ void OPPROTO glue(op_lswx_64, MEMSUFFIX) (void)
     if (likely(T1 != 0)) {
         if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
                      (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
-            do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
+            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL |
+                                   POWERPC_EXCP_INVAL_LSWX);
         } else {
             glue(do_lsw_64, MEMSUFFIX)(PARAM1);
         }
@@ -326,7 +330,9 @@ void OPPROTO glue(op_lswx_le, MEMSUFFIX) (void)
     if (likely(T1 != 0)) {
         if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
                      (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
-            do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
+            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL |
+                                   POWERPC_EXCP_INVAL_LSWX);
         } else {
             glue(do_lsw_le, MEMSUFFIX)(PARAM1);
         }
@@ -341,7 +347,9 @@ void OPPROTO glue(op_lswx_le_64, MEMSUFFIX) (void)
     if (likely(T1 != 0)) {
         if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
                      (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
-            do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
+            do_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL |
+                                   POWERPC_EXCP_INVAL_LSWX);
         } else {
             glue(do_lsw_le_64, MEMSUFFIX)(PARAM1);
         }
@@ -514,7 +522,7 @@ PPC_LDF_OP_64(fs_le, ldflr);
 void OPPROTO glue(op_lwarx, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ldl, MEMSUFFIX)((uint32_t)T0);
         env->reserve = (uint32_t)T0;
@@ -526,7 +534,7 @@ void OPPROTO glue(op_lwarx, MEMSUFFIX) (void)
 void OPPROTO glue(op_lwarx_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ldl, MEMSUFFIX)((uint64_t)T0);
         env->reserve = (uint64_t)T0;
@@ -537,7 +545,7 @@ void OPPROTO glue(op_lwarx_64, MEMSUFFIX) (void)
 void OPPROTO glue(op_ldarx, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ldq, MEMSUFFIX)((uint32_t)T0);
         env->reserve = (uint32_t)T0;
@@ -548,7 +556,7 @@ void OPPROTO glue(op_ldarx, MEMSUFFIX) (void)
 void OPPROTO glue(op_ldarx_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ldq, MEMSUFFIX)((uint64_t)T0);
         env->reserve = (uint64_t)T0;
@@ -560,7 +568,7 @@ void OPPROTO glue(op_ldarx_64, MEMSUFFIX) (void)
 void OPPROTO glue(op_lwarx_le, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
         env->reserve = (uint32_t)T0;
@@ -572,7 +580,7 @@ void OPPROTO glue(op_lwarx_le, MEMSUFFIX) (void)
 void OPPROTO glue(op_lwarx_le_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
         env->reserve = (uint64_t)T0;
@@ -583,7 +591,7 @@ void OPPROTO glue(op_lwarx_le_64, MEMSUFFIX) (void)
 void OPPROTO glue(op_ldarx_le, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ld64r, MEMSUFFIX)((uint32_t)T0);
         env->reserve = (uint32_t)T0;
@@ -594,7 +602,7 @@ void OPPROTO glue(op_ldarx_le, MEMSUFFIX) (void)
 void OPPROTO glue(op_ldarx_le_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         T1 = glue(ld64r, MEMSUFFIX)((uint64_t)T0);
         env->reserve = (uint64_t)T0;
@@ -607,7 +615,7 @@ void OPPROTO glue(op_ldarx_le_64, MEMSUFFIX) (void)
 void OPPROTO glue(op_stwcx, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint32_t)T0)) {
             env->crf[0] = xer_so;
@@ -624,7 +632,7 @@ void OPPROTO glue(op_stwcx, MEMSUFFIX) (void)
 void OPPROTO glue(op_stwcx_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint64_t)T0)) {
             env->crf[0] = xer_so;
@@ -640,7 +648,7 @@ void OPPROTO glue(op_stwcx_64, MEMSUFFIX) (void)
 void OPPROTO glue(op_stdcx, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint32_t)T0)) {
             env->crf[0] = xer_so;
@@ -656,7 +664,7 @@ void OPPROTO glue(op_stdcx, MEMSUFFIX) (void)
 void OPPROTO glue(op_stdcx_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint64_t)T0)) {
             env->crf[0] = xer_so;
@@ -673,7 +681,7 @@ void OPPROTO glue(op_stdcx_64, MEMSUFFIX) (void)
 void OPPROTO glue(op_stwcx_le, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint32_t)T0)) {
             env->crf[0] = xer_so;
@@ -690,7 +698,7 @@ void OPPROTO glue(op_stwcx_le, MEMSUFFIX) (void)
 void OPPROTO glue(op_stwcx_le_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint64_t)T0)) {
             env->crf[0] = xer_so;
@@ -706,7 +714,7 @@ void OPPROTO glue(op_stwcx_le_64, MEMSUFFIX) (void)
 void OPPROTO glue(op_stdcx_le, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint32_t)T0)) {
             env->crf[0] = xer_so;
@@ -722,7 +730,7 @@ void OPPROTO glue(op_stdcx_le, MEMSUFFIX) (void)
 void OPPROTO glue(op_stdcx_le_64, MEMSUFFIX) (void)
 {
     if (unlikely(T0 & 0x03)) {
-        do_raise_exception(EXCP_ALIGN);
+        do_raise_exception(POWERPC_EXCP_ALIGN);
     } else {
         if (unlikely(env->reserve != (uint64_t)T0)) {
             env->crf[0] = xer_so;
index 2e5cb6bcd47562ea70549c8a7be7da9d841cfcbe..dc4e7589145aee5e42081dd689064db524f18e49 100644 (file)
@@ -207,35 +207,44 @@ static inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
         gen_op_update_nip(nip);
 }
 
-#define RET_EXCP(ctx, excp, error)                                            \
+#define GEN_EXCP(ctx, excp, error)                                            \
 do {                                                                          \
-    if ((ctx)->exception == EXCP_NONE) {                                      \
+    if ((ctx)->exception == POWERPC_EXCP_NONE) {                              \
         gen_update_nip(ctx, (ctx)->nip);                                      \
     }                                                                         \
     gen_op_raise_exception_err((excp), (error));                              \
     ctx->exception = (excp);                                                  \
 } while (0)
 
-#define RET_INVAL(ctx)                                                        \
-RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL)
+#define GEN_EXCP_INVAL(ctx)                                                   \
+GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
+         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
 
-#define RET_PRIVOPC(ctx)                                                      \
-RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_OPC)
+#define GEN_EXCP_PRIVOPC(ctx)                                                 \
+GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
+         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
 
-#define RET_PRIVREG(ctx)                                                      \
-RET_EXCP((ctx), EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG)
+#define GEN_EXCP_PRIVREG(ctx)                                                 \
+GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM,                                         \
+         POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG)
+
+#define GEN_EXCP_NO_FP(ctx)                                                   \
+GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)
+
+#define GEN_EXCP_NO_AP(ctx)                                                   \
+GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
 
 /* Stop translation */
-static inline void RET_STOP (DisasContext *ctx)
+static inline void GEN_STOP (DisasContext *ctx)
 {
     gen_update_nip(ctx, ctx->nip);
-    ctx->exception = EXCP_MTMSR;
+    ctx->exception = POWERPC_EXCP_STOP;
 }
 
 /* No need to update nip here, as execution flow will change */
-static inline void RET_CHG_FLOW (DisasContext *ctx)
+static inline void GEN_SYNC (DisasContext *ctx)
 {
-    ctx->exception = EXCP_MTMSR;
+    ctx->exception = POWERPC_EXCP_SYNC;
 }
 
 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)                      \
@@ -535,7 +544,7 @@ GEN_OPCODE_MARK(start);
 /* Invalid instruction */
 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
 {
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
 static opc_handler_t invalid_handler = {
@@ -1550,7 +1559,7 @@ __GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type)                        \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_reset_scrfx();                                                     \
@@ -1574,7 +1583,7 @@ _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, type);
 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_reset_scrfx();                                                     \
@@ -1596,7 +1605,7 @@ _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1);
 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, PPC_FLOAT)                        \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_reset_scrfx();                                                     \
@@ -1618,7 +1627,7 @@ _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1);
 GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)                        \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_reset_scrfx();                                                     \
@@ -1633,7 +1642,7 @@ GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type)                        \
 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type)                        \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_reset_scrfx();                                                     \
@@ -1666,7 +1675,7 @@ GEN_FLOAT_AB(sub, 0x14, 0x000007C0);
 GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     gen_op_reset_scrfx();
@@ -1680,7 +1689,7 @@ GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     gen_op_reset_scrfx();
@@ -1723,7 +1732,7 @@ GEN_FLOAT_B(ctidz, 0x0F, 0x19, PPC_64B);
 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     gen_op_reset_scrfx();
@@ -1737,7 +1746,7 @@ GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     gen_op_reset_scrfx();
@@ -1755,7 +1764,7 @@ GEN_FLOAT_B(abs, 0x08, 0x08, PPC_FLOAT);
 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     gen_op_reset_scrfx();
@@ -1775,7 +1784,7 @@ GEN_FLOAT_B(neg, 0x08, 0x01, PPC_FLOAT);
 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     gen_op_load_fpscr_T0(crfS(ctx->opcode));
@@ -1787,7 +1796,7 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     gen_op_load_fpscr();
@@ -1802,7 +1811,7 @@ GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
     uint8_t crb;
 
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     crb = crbD(ctx->opcode) >> 2;
@@ -1819,7 +1828,7 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
     uint8_t crb;
 
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     crb = crbD(ctx->opcode) >> 2;
@@ -1834,7 +1843,7 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     gen_op_load_fpr_FT0(rB(ctx->opcode));
@@ -1847,7 +1856,7 @@ GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
 GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode));
@@ -2002,7 +2011,7 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                   \
 {                                                                             \
     if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                  rA(ctx->opcode) == rD(ctx->opcode))) {                       \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (type == PPC_64B)                                                      \
@@ -2019,7 +2028,7 @@ GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                 \
 {                                                                             \
     if (unlikely(rA(ctx->opcode) == 0 ||                                      \
                  rA(ctx->opcode) == rD(ctx->opcode))) {                       \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2067,7 +2076,7 @@ GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
     if (Rc(ctx->opcode)) {
         if (unlikely(rA(ctx->opcode) == 0 ||
                      rA(ctx->opcode) == rD(ctx->opcode))) {
-            RET_INVAL(ctx);
+            GEN_EXCP_INVAL(ctx);
             return;
         }
     }
@@ -2098,7 +2107,7 @@ GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type)                     \
 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
 {                                                                             \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (type == PPC_64B)                                                      \
@@ -2114,7 +2123,7 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type)                  \
 GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type)                \
 {                                                                             \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2152,7 +2161,7 @@ GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000002, PPC_64B)
 {
     if (Rc(ctx->opcode)) {
         if (unlikely(rA(ctx->opcode) == 0)) {
-            RET_INVAL(ctx);
+            GEN_EXCP_INVAL(ctx);
             return;
         }
     }
@@ -2367,7 +2376,8 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_INTEGER)
     if (unlikely(((start + nr) > 32  &&
                   start <= ra && (start + nr - 32) > ra) ||
                  ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
-        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
+        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
+                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
         return;
     }
     /* NIP cannot be restored if the memory exception comes from an helper */
@@ -2426,6 +2436,7 @@ GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FF0801, PPC_MEM_EIEIO)
 /* isync */
 GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FF0801, PPC_MEM)
 {
+    GEN_STOP(ctx);
 }
 
 #define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
@@ -2574,7 +2585,7 @@ GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x03CF0801, PPC_MEM_SYNC)
 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                 \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_imm_index(ctx, 0);                                               \
@@ -2586,11 +2597,11 @@ GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                 \
 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)              \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_imm_index(ctx, 0);                                               \
@@ -2603,11 +2614,11 @@ GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)              \
 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)             \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2620,7 +2631,7 @@ GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)             \
 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)             \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2645,7 +2656,7 @@ GEN_LDFS(fs, 0x10);
 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_imm_index(ctx, 0);                                               \
@@ -2657,11 +2668,11 @@ GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)                \
 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)             \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_imm_index(ctx, 0);                                               \
@@ -2674,11 +2685,11 @@ GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT)             \
 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)            \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     if (unlikely(rA(ctx->opcode) == 0)) {                                     \
-        RET_INVAL(ctx);                                                       \
+        GEN_EXCP_INVAL(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2691,7 +2702,7 @@ GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT)            \
 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, PPC_FLOAT)            \
 {                                                                             \
     if (unlikely(!ctx->fpu_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_FP, 0);                                         \
+        GEN_EXCP_NO_FP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -2716,12 +2727,12 @@ GEN_STFS(fs, 0x14);
 GEN_HANDLER(stfiwx, 0x1F, 0x17, 0x1E, 0x00000001, PPC_FLOAT_STFIWX)
 {
     if (unlikely(!ctx->fpu_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_FP, 0);
+        GEN_EXCP_NO_FP(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
     /* XXX: TODO: memcpy low order 32 bits of FRP(rs) into memory */
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
 /***                                Branch                                 ***/
@@ -2760,6 +2771,16 @@ static inline void gen_goto_tb (DisasContext *ctx, int n, target_ulong dest)
     }
 }
 
+static inline void gen_setlr (DisasContext *ctx, target_ulong nip)
+{
+#if defined(TARGET_PPC64)
+    if (ctx->sf_mode != 0 && (nip >> 32))
+        gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
+    else
+#endif
+        gen_op_setlr(ctx->nip);
+}
+
 /* b ba bl bla */
 GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
 {
@@ -2776,16 +2797,14 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
         target = ctx->nip + li - 4;
     else
         target = li;
-    if (LK(ctx->opcode)) {
 #if defined(TARGET_PPC64)
-        if (ctx->sf_mode)
-            gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
-        else
+    if (!ctx->sf_mode)
+        target = (uint32_t)target;
 #endif
-            gen_op_setlr(ctx->nip);
-    }
+    if (LK(ctx->opcode))
+        gen_setlr(ctx, ctx->nip);
     gen_goto_tb(ctx, 0, target);
-    ctx->exception = EXCP_BRANCH;
+    ctx->exception = POWERPC_EXCP_BRANCH;
 }
 
 #define BCOND_IM  0
@@ -2810,6 +2829,10 @@ static inline void gen_bcond (DisasContext *ctx, int type)
         } else {
             target = li;
         }
+#if defined(TARGET_PPC64)
+        if (!ctx->sf_mode)
+            target = (uint32_t)target;
+#endif
         break;
     case BCOND_CTR:
         gen_op_movl_T1_ctr();
@@ -2819,14 +2842,8 @@ static inline void gen_bcond (DisasContext *ctx, int type)
         gen_op_movl_T1_lr();
         break;
     }
-    if (LK(ctx->opcode)) {
-#if defined(TARGET_PPC64)
-        if (ctx->sf_mode)
-            gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
-        else
-#endif
-            gen_op_setlr(ctx->nip);
-    }
+    if (LK(ctx->opcode))
+        gen_setlr(ctx, ctx->nip);
     if (bo & 0x10) {
         /* No CR condition */
         switch (bo & 0x6) {
@@ -2934,7 +2951,7 @@ static inline void gen_bcond (DisasContext *ctx, int type)
             gen_op_debug();
         gen_op_exit_tb();
     }
-    ctx->exception = EXCP_BRANCH;
+    ctx->exception = POWERPC_EXCP_BRANCH;
 }
 
 GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
@@ -2995,15 +3012,15 @@ GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
 GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     /* Restore CPU state */
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_rfi();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
@@ -3011,26 +3028,29 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
 GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     /* Restore CPU state */
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_rfid();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 #endif
 
 /* sc */
-GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFFFFD, PPC_FLOW)
+GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
 {
+    uint32_t lev;
+
+    lev = (ctx->opcode >> 5) & 0x7F;
 #if defined(CONFIG_USER_ONLY)
-    RET_EXCP(ctx, EXCP_SYSCALL_USER, 0);
+    GEN_EXCP(ctx, POWERPC_EXCP_SYSCALL_USER, lev);
 #else
-    RET_EXCP(ctx, EXCP_SYSCALL, 0);
+    GEN_EXCP(ctx, POWERPC_EXCP_SYSCALL, lev);
 #endif
 }
 
@@ -3108,10 +3128,10 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_msr();
@@ -3153,7 +3173,7 @@ static inline void gen_op_mfspr (DisasContext *ctx)
                         sprn, sprn);
             }
             printf("Trying to read privileged spr %d %03x\n", sprn, sprn);
-            RET_PRIVREG(ctx);
+            GEN_EXCP_PRIVREG(ctx);
         }
     } else {
         /* Not defined */
@@ -3162,7 +3182,8 @@ static inline void gen_op_mfspr (DisasContext *ctx)
                     sprn, sprn);
         }
         printf("Trying to read invalid spr %d %03x\n", sprn, sprn);
-        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
+        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
+                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
     }
 }
 
@@ -3199,17 +3220,17 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
 GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_64B)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_update_nip(ctx, ctx->nip);
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_store_msr();
     /* Must stop the translation as machine state (may have) changed */
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 #endif
@@ -3217,10 +3238,10 @@ GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_64B)
 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_update_nip(ctx, ctx->nip);
@@ -3232,7 +3253,7 @@ GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
 #endif
         gen_op_store_msr();
     /* Must stop the translation as machine state (may have) changed */
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
@@ -3259,7 +3280,7 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
                         sprn, sprn);
             }
             printf("Trying to write privileged spr %d %03x\n", sprn, sprn);
-            RET_PRIVREG(ctx);
+            GEN_EXCP_PRIVREG(ctx);
         }
     } else {
         /* Not defined */
@@ -3268,7 +3289,8 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
                     sprn, sprn);
         }
         printf("Trying to write invalid spr %d %03x\n", sprn, sprn);
-        RET_EXCP(ctx, EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_SPR);
+        GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
+                 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
     }
 }
 
@@ -3288,10 +3310,10 @@ GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03E00001, PPC_CACHE)
 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
@@ -3407,13 +3429,11 @@ static GenOpFunc *gen_op_icbi[] = {
 };
 #endif
 #endif
+
 GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE)
 {
-    /* NIP cannot be restored if the memory exception comes from an helper */
-    gen_update_nip(ctx, ctx->nip - 4);
     gen_addr_reg_index(ctx);
     op_icbi();
-    RET_STOP(ctx);
 }
 
 /* Optional: */
@@ -3428,10 +3448,10 @@ GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_set_T1(SR(ctx->opcode));
@@ -3444,10 +3464,10 @@ GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T1(rB(ctx->opcode));
@@ -3461,16 +3481,15 @@ GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_set_T1(SR(ctx->opcode));
     gen_op_store_sr();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -3478,17 +3497,16 @@ GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T0(rS(ctx->opcode));
     gen_op_load_gpr_T1(rB(ctx->opcode));
     gen_op_srli_T1(28);
     gen_op_store_sr();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -3498,16 +3516,15 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
         if (loglevel != 0)
             fprintf(logfile, "%s: ! supervisor\n", __func__);
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_tlbia();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -3515,10 +3532,10 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rB(ctx->opcode));
@@ -3528,7 +3545,6 @@ GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
     else
 #endif
         gen_op_tlbie();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -3536,16 +3552,16 @@ GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* This has no effect: it should ensure that all previous
      * tlbie have completed
      */
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 #endif
 }
 
@@ -3554,16 +3570,15 @@ GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
 GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
         if (loglevel != 0)
             fprintf(logfile, "%s: ! supervisor\n", __func__);
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_slbia();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -3571,15 +3586,14 @@ GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
 GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rB(ctx->opcode));
     gen_op_slbie();
-    RET_STOP(ctx);
 #endif
 }
 #endif
@@ -4073,24 +4087,24 @@ GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
 GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
 {
     /* XXX: TODO */
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
 /* esa */
 GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
 {
     /* XXX: TODO */
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
 /* mfrom */
 GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rA(ctx->opcode));
@@ -4104,15 +4118,14 @@ GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
 GEN_HANDLER(tlbld, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rB(ctx->opcode));
     gen_op_6xx_tlbld();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -4120,15 +4133,14 @@ GEN_HANDLER(tlbld, 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
 GEN_HANDLER(tlbli, 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rB(ctx->opcode));
     gen_op_6xx_tlbli();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -4144,10 +4156,10 @@ GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
 {
     /* Cache line invalidate: privileged and treated as no-op */
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
 #endif
@@ -4162,10 +4174,10 @@ GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
 GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     int ra = rA(ctx->opcode);
@@ -4182,10 +4194,10 @@ GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
 GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
@@ -4197,14 +4209,14 @@ GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
 GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_POWER_rfsvc();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
@@ -4347,17 +4359,17 @@ GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
 GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_BOOKE_EXT)
 {
     /* XXX: TODO */
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
 /* XXX: not implemented on 440 ? */
 GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE_EXT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
@@ -4368,7 +4380,6 @@ GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_BOOKE_EXT)
     else
 #endif
         gen_op_tlbie();
-    RET_STOP(ctx);
 #endif
 }
 
@@ -4550,12 +4561,12 @@ GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
 GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     uint32_t dcrn = SPR(ctx->opcode);
 
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_set_T0(dcrn);
@@ -4568,12 +4579,12 @@ GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_EMB_COMMON)
 GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     uint32_t dcrn = SPR(ctx->opcode);
 
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_set_T0(dcrn);
@@ -4587,10 +4598,10 @@ GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_EMB_COMMON)
 GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_BOOKE_EXT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T0(rA(ctx->opcode));
@@ -4605,10 +4616,10 @@ GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_BOOKE_EXT)
 GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_BOOKE_EXT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVREG(ctx);
+    GEN_EXCP_PRIVREG(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVREG(ctx);
+        GEN_EXCP_PRIVREG(ctx);
         return;
     }
     gen_op_load_gpr_T0(rA(ctx->opcode));
@@ -4640,10 +4651,10 @@ GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
 GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* interpreted as no-op */
@@ -4654,10 +4665,10 @@ GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
 GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
@@ -4679,10 +4690,10 @@ GEN_HANDLER(icbt_40x, 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
 GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* interpreted as no-op */
@@ -4693,10 +4704,10 @@ GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
 GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* interpreted as no-op */
@@ -4707,30 +4718,30 @@ GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
 GEN_HANDLER(rfci_40x, 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* Restore CPU state */
     gen_op_40x_rfci();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
 GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* Restore CPU state */
     gen_op_rfci();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
@@ -4739,15 +4750,15 @@ GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
 GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE_EXT)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* Restore CPU state */
     gen_op_rfdi();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
@@ -4755,15 +4766,15 @@ GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_BOOKE_EXT)
 GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     /* Restore CPU state */
     gen_op_rfmci();
-    RET_CHG_FLOW(ctx);
+    GEN_SYNC(ctx);
 #endif
 }
 
@@ -4772,10 +4783,10 @@ GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
 GEN_HANDLER(tlbre_40x, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     switch (rB(ctx->opcode)) {
@@ -4790,7 +4801,7 @@ GEN_HANDLER(tlbre_40x, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
         gen_op_store_T0_gpr(rD(ctx->opcode));
         break;
     default:
-        RET_INVAL(ctx);
+        GEN_EXCP_INVAL(ctx);
         break;
     }
 #endif
@@ -4800,10 +4811,10 @@ GEN_HANDLER(tlbre_40x, 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
 GEN_HANDLER(tlbsx_40x, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
@@ -4819,10 +4830,10 @@ GEN_HANDLER(tlbsx_40x, 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
 GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     switch (rB(ctx->opcode)) {
@@ -4837,7 +4848,7 @@ GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
         gen_op_4xx_tlbwe_lo();
         break;
     default:
-        RET_INVAL(ctx);
+        GEN_EXCP_INVAL(ctx);
         break;
     }
 #endif
@@ -4848,10 +4859,10 @@ GEN_HANDLER(tlbwe_40x, 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
 GEN_HANDLER(tlbre_440, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     switch (rB(ctx->opcode)) {
@@ -4863,7 +4874,7 @@ GEN_HANDLER(tlbre_440, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
         gen_op_store_T0_gpr(rD(ctx->opcode));
         break;
     default:
-        RET_INVAL(ctx);
+        GEN_EXCP_INVAL(ctx);
         break;
     }
 #endif
@@ -4873,10 +4884,10 @@ GEN_HANDLER(tlbre_440, 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
 GEN_HANDLER(tlbsx_440, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_addr_reg_index(ctx);
@@ -4892,10 +4903,10 @@ GEN_HANDLER(tlbsx_440, 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
 GEN_HANDLER(tlbwe_440, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     switch (rB(ctx->opcode)) {
@@ -4907,7 +4918,7 @@ GEN_HANDLER(tlbwe_440, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
         gen_op_440_tlbwe(rB(ctx->opcode));
         break;
     default:
-        RET_INVAL(ctx);
+        GEN_EXCP_INVAL(ctx);
         break;
     }
 #endif
@@ -4917,15 +4928,15 @@ GEN_HANDLER(tlbwe_440, 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
 GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_load_gpr_T0(rD(ctx->opcode));
     gen_op_wrte();
-    RET_EXCP(ctx, EXCP_MTMSR, 0);
+    GEN_STOP(ctx);
 #endif
 }
 
@@ -4933,15 +4944,15 @@ GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_EMB_COMMON)
 GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_EMB_COMMON)
 {
 #if defined(CONFIG_USER_ONLY)
-    RET_PRIVOPC(ctx);
+    GEN_EXCP_PRIVOPC(ctx);
 #else
     if (unlikely(!ctx->supervisor)) {
-        RET_PRIVOPC(ctx);
+        GEN_EXCP_PRIVOPC(ctx);
         return;
     }
     gen_op_set_T0(ctx->opcode & 0x00010000);
     gen_op_wrte();
-    RET_EXCP(ctx, EXCP_MTMSR, 0);
+    GEN_STOP(ctx);
 #endif
 }
 
@@ -5009,7 +5020,7 @@ GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type)                   \
 /* Handler for undefined SPE opcodes */
 static inline void gen_speundef (DisasContext *ctx)
 {
-    RET_INVAL(ctx);
+    GEN_EXCP_INVAL(ctx);
 }
 
 /* SPE load and stores */
@@ -5101,7 +5112,7 @@ static GenOpFunc *gen_op_spe_st##name[] = {                                   \
 static inline void gen_evl##name (DisasContext *ctx)                          \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_spe_imm_index(ctx, sh);                                          \
@@ -5113,7 +5124,7 @@ static inline void gen_evl##name (DisasContext *ctx)                          \
 static inline void gen_evl##name##x (DisasContext *ctx)                       \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -5130,7 +5141,7 @@ GEN_SPE_LDX(name)
 static inline void gen_evst##name (DisasContext *ctx)                         \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_spe_imm_index(ctx, sh);                                          \
@@ -5142,7 +5153,7 @@ static inline void gen_evst##name (DisasContext *ctx)                         \
 static inline void gen_evst##name##x (DisasContext *ctx)                      \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_addr_reg_index(ctx);                                                  \
@@ -5164,7 +5175,7 @@ GEN_SPEOP_ST(name, sh)
 static inline void gen_##name (DisasContext *ctx)                             \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
@@ -5177,7 +5188,7 @@ static inline void gen_##name (DisasContext *ctx)                             \
 static inline void gen_##name (DisasContext *ctx)                             \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
@@ -5189,7 +5200,7 @@ static inline void gen_##name (DisasContext *ctx)                             \
 static inline void gen_##name (DisasContext *ctx)                             \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
@@ -5239,7 +5250,7 @@ static inline void gen_brinc (DisasContext *ctx)
 static inline void gen_##name##i (DisasContext *ctx)                          \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_load_gpr64_T0(rB(ctx->opcode));                                    \
@@ -5252,7 +5263,7 @@ static inline void gen_##name##i (DisasContext *ctx)                          \
 static inline void gen_##name##i (DisasContext *ctx)                          \
 {                                                                             \
     if (unlikely(!ctx->spe_enabled)) {                                        \
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);                                        \
+        GEN_EXCP_NO_AP(ctx);                                                  \
         return;                                                               \
     }                                                                         \
     gen_op_load_gpr64_T0(rA(ctx->opcode));                                    \
@@ -5324,7 +5335,7 @@ GEN_SPE(evcmpeq,        speundef,      0x1A, 0x08, 0x00600000, PPC_SPE); ////
 static inline void gen_evsel (DisasContext *ctx)
 {
     if (unlikely(!ctx->spe_enabled)) {
-        RET_EXCP(ctx, EXCP_NO_SPE, 0);
+        GEN_EXCP_NO_AP(ctx);
         return;
     }
     gen_op_load_crf_T0(ctx->opcode & 0x7);
@@ -5942,7 +5953,7 @@ static inline int gen_intermediate_code_internal (CPUState *env,
     nb_gen_labels = 0;
     ctx.nip = pc_start;
     ctx.tb = tb;
-    ctx.exception = EXCP_NONE;
+    ctx.exception = POWERPC_EXCP_NONE;
     ctx.spr_cb = env->spr_cb;
 #if defined(CONFIG_USER_ONLY)
     ctx.mem_idx = msr_le;
@@ -5969,7 +5980,7 @@ static inline int gen_intermediate_code_internal (CPUState *env,
     msr_se = 1;
 #endif
     /* Set env in case of segfault during code fetch */
-    while (ctx.exception == EXCP_NONE && gen_opc_ptr < gen_opc_end) {
+    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
         if (unlikely(env->nb_breakpoints > 0)) {
             for (j = 0; j < env->nb_breakpoints; j++) {
                 if (env->breakpoints[j] == ctx.nip) {
@@ -6038,18 +6049,18 @@ static inline int gen_intermediate_code_internal (CPUState *env,
             if (unlikely((ctx.opcode & handler->inval) != 0)) {
                 if (loglevel != 0) {
                     fprintf(logfile, "invalid bits: %08x for opcode: "
-                            "%02x -%02x - %02x (%08x) 0x" ADDRX "\n",
+                            "%02x - %02x - %02x (%08x) 0x" ADDRX "\n",
                             ctx.opcode & handler->inval, opc1(ctx.opcode),
                             opc2(ctx.opcode), opc3(ctx.opcode),
                             ctx.opcode, ctx.nip - 4);
                 } else {
                     printf("invalid bits: %08x for opcode: "
-                           "%02x -%02x - %02x (%08x) 0x" ADDRX "\n",
+                           "%02x - %02x - %02x (%08x) 0x" ADDRX "\n",
                            ctx.opcode & handler->inval, opc1(ctx.opcode),
                            opc2(ctx.opcode), opc3(ctx.opcode),
                            ctx.opcode, ctx.nip - 4);
                 }
-                RET_INVAL(ctxp);
+                GEN_EXCP_INVAL(ctxp);
                 break;
             }
         }
@@ -6059,7 +6070,7 @@ static inline int gen_intermediate_code_internal (CPUState *env,
 #endif
         /* Check trace mode exceptions */
 #if 0 // XXX: buggy on embedded PowerPC
-        if (unlikely((msr_be && ctx.exception == EXCP_BRANCH) ||
+        if (unlikely((msr_be && ctx.exception == POWERPC_EXCP_BRANCH) ||
                      /* Check in single step trace mode
                       * we need to stop except if:
                       * - rfi, trap or syscall
@@ -6068,10 +6079,13 @@ static inline int gen_intermediate_code_internal (CPUState *env,
                      (msr_se && (ctx.nip < 0x100 ||
                                  ctx.nip > 0xF00 ||
                                  (ctx.nip & 0xFC) != 0x04) &&
-                      ctx.exception != EXCP_SYSCALL &&
-                      ctx.exception != EXCP_SYSCALL_USER &&
-                      ctx.exception != EXCP_TRAP))) {
-            RET_EXCP(ctxp, EXCP_TRACE, 0);
+#if defined(CONFIG_USER_ONLY)
+                      ctx.exception != POWERPC_EXCP_SYSCALL_USER &&
+#else
+                      ctx.exception != POWERPC_EXCP_SYSCALL &&
+#endif
+                      ctx.exception != POWERPC_EXCP_TRAP))) {
+            GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
         }
 #endif
         /* if we reach a page boundary or are single stepping, stop
@@ -6085,9 +6099,9 @@ static inline int gen_intermediate_code_internal (CPUState *env,
         break;
 #endif
     }
-    if (ctx.exception == EXCP_NONE) {
+    if (ctx.exception == POWERPC_EXCP_NONE) {
         gen_goto_tb(&ctx, 0, ctx.nip);
-    } else if (ctx.exception != EXCP_BRANCH) {
+    } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
         gen_op_reset_T0();
         /* Generate the return instruction */
         gen_op_exit_tb();
index e3cb183609010a8e122c34c8f8aaacf2c114231f..109dcdc2565b709b2cd4f543255d0849bd5b0518 100644 (file)
@@ -192,7 +192,7 @@ static void spr_write_ibatu (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_ibatu((sprn - SPR_IBAT0U) / 2);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 static void spr_write_ibatu_h (void *opaque, int sprn)
@@ -200,7 +200,7 @@ static void spr_write_ibatu_h (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_ibatu((sprn - SPR_IBAT4U) / 2);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 static void spr_write_ibatl (void *opaque, int sprn)
@@ -208,7 +208,7 @@ static void spr_write_ibatl (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_ibatl((sprn - SPR_IBAT0L) / 2);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 static void spr_write_ibatl_h (void *opaque, int sprn)
@@ -216,7 +216,7 @@ static void spr_write_ibatl_h (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_ibatl((sprn - SPR_IBAT4L) / 2);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 /* DBAT0U...DBAT7U */
@@ -236,7 +236,7 @@ static void spr_write_dbatu (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_dbatu((sprn - SPR_DBAT0U) / 2);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 static void spr_write_dbatu_h (void *opaque, int sprn)
@@ -244,7 +244,7 @@ static void spr_write_dbatu_h (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_dbatu((sprn - SPR_DBAT4U) / 2);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 static void spr_write_dbatl (void *opaque, int sprn)
@@ -252,7 +252,7 @@ static void spr_write_dbatl (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_dbatl((sprn - SPR_DBAT0L) / 2);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 static void spr_write_dbatl_h (void *opaque, int sprn)
@@ -260,7 +260,7 @@ static void spr_write_dbatl_h (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_dbatl((sprn - SPR_DBAT4L) / 2);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 /* SDR1 */
@@ -274,7 +274,7 @@ static void spr_write_sdr1 (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_sdr1();
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 /* 64 bits PowerPC specific SPRs */
@@ -291,7 +291,7 @@ static void spr_write_asr (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_asr();
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 #endif
 #endif
@@ -332,7 +332,7 @@ static void spr_write_601_ubatu (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_601_batu((sprn - SPR_IBAT0U) / 2);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 static void spr_write_601_ubatl (void *opaque, int sprn)
@@ -340,7 +340,7 @@ static void spr_write_601_ubatl (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_601_batl((sprn - SPR_IBAT0L) / 2);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 #endif
 
@@ -362,7 +362,7 @@ static void spr_write_40x_dbcr0 (void *opaque, int sprn)
 
     gen_op_store_40x_dbcr0();
     /* We must stop translation as we may have rebooted */
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 static void spr_write_40x_sler (void *opaque, int sprn)
@@ -373,7 +373,7 @@ static void spr_write_40x_sler (void *opaque, int sprn)
     /* We must stop the translation as we may have changed
      * some regions endianness
      */
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 static void spr_write_booke_tcr (void *opaque, int sprn)
@@ -400,7 +400,7 @@ static void spr_write_403_pbr (void *opaque, int sprn)
     DisasContext *ctx = opaque;
 
     gen_op_store_403_pb(sprn - SPR_403_PBL1);
-    RET_STOP(ctx);
+    GEN_STOP(ctx);
 }
 
 static void spr_write_pir (void *opaque, int sprn)
@@ -2152,6 +2152,323 @@ static void gen_spr_620 (CPUPPCState *env)
  * ... and more (thermal management, performance counters, ...)
  */
 
+/*****************************************************************************/
+/* Exception vectors models                                                  */
+static void init_excp_4xx_real (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_PIT]      = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_FIT]      = 0x00001010;
+    env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00001020;
+    env->excp_vectors[POWERPC_EXCP_DEBUG]    = 0x00002000;
+#endif
+}
+
+static void init_excp_4xx_softmmu (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_PIT]      = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_FIT]      = 0x00001010;
+    env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00001020;
+    env->excp_vectors[POWERPC_EXCP_DTLB]     = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_ITLB]     = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_DEBUG]    = 0x00002000;
+#endif
+}
+
+static void init_excp_BookE (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_APU]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_FIT]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_DTLB]     = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_ITLB]     = 0x00000000;
+    env->excp_vectors[POWERPC_EXCP_DEBUG]    = 0x00000000;
+    env->excp_prefix = 0x00000000;
+    env->ivor_mask = 0x0000FFE0;
+    env->ivpr_mask = 0xFFFF0000;
+#endif
+}
+
+static void init_excp_601 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_IO]       = 0x00000A00;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_RUNM]     = 0x00002000;
+    env->excp_prefix = 0xFFF00000;
+#endif
+}
+
+static void init_excp_602 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_FPA]      = 0x00000E00;
+    env->excp_vectors[POWERPC_EXCP_IFTLB]    = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_DLTLB]    = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    env->excp_vectors[POWERPC_EXCP_WDT]      = 0x00001500;
+    env->excp_vectors[POWERPC_EXCP_EMUL]     = 0x00001600;
+    env->excp_prefix = 0xFFF00000;
+#endif
+}
+
+static void init_excp_603 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_IFTLB]    = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_DLTLB]    = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+#endif
+}
+
+static void init_excp_G2 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000A00;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_IFTLB]    = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_DLTLB]    = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+#endif
+}
+
+static void init_excp_604 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+#endif
+}
+
+#if defined (TODO)
+static void init_excp_620 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_FPA]      = 0x00000E00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+#endif
+}
+#endif /* defined (TODO) */
+
+static void init_excp_7x0 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
+#endif
+}
+
+static void init_excp_750FX (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
+#endif
+}
+
+static void init_excp_7400 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_VPU]      = 0x00000F20;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001600;
+    env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001700;
+#endif
+}
+
+#if defined (TODO)
+static void init_excp_7450 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_VPU]      = 0x00000F20;
+    env->excp_vectors[POWERPC_EXCP_IFTLB]    = 0x00001000;
+    env->excp_vectors[POWERPC_EXCP_DLTLB]    = 0x00001100;
+    env->excp_vectors[POWERPC_EXCP_DSTLB]    = 0x00001200;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_SMI]      = 0x00001400;
+    env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001600;
+#endif
+}
+#endif /* defined (TODO) */
+
+#if defined (TARGET_PPC64)
+static void init_excp_970 (CPUPPCState *env)
+{
+#if !defined(CONFIG_USER_ONLY)
+    env->excp_vectors[POWERPC_EXCP_RESET]    = 0x00000100;
+    env->excp_vectors[POWERPC_EXCP_MCHECK]   = 0x00000200;
+    env->excp_vectors[POWERPC_EXCP_DSI]      = 0x00000300;
+    env->excp_vectors[POWERPC_EXCP_DSEG]     = 0x00000380;
+    env->excp_vectors[POWERPC_EXCP_ISI]      = 0x00000400;
+    env->excp_vectors[POWERPC_EXCP_ISEG]     = 0x00000480;
+    env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
+    env->excp_vectors[POWERPC_EXCP_ALIGN]    = 0x00000600;
+    env->excp_vectors[POWERPC_EXCP_PROGRAM]  = 0x00000700;
+    env->excp_vectors[POWERPC_EXCP_FPU]      = 0x00000800;
+    env->excp_vectors[POWERPC_EXCP_DECR]     = 0x00000900;
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+    env->excp_vectors[POWERPC_EXCP_HDECR]    = 0x00000980;
+#endif
+    env->excp_vectors[POWERPC_EXCP_SYSCALL]  = 0x00000C00;
+    env->excp_vectors[POWERPC_EXCP_TRACE]    = 0x00000D00;
+    env->excp_vectors[POWERPC_EXCP_PERFM]    = 0x00000F00;
+    env->excp_vectors[POWERPC_EXCP_VPU]      = 0x00000F20;
+    env->excp_vectors[POWERPC_EXCP_IABR]     = 0x00001300;
+    env->excp_vectors[POWERPC_EXCP_MAINT]    = 0x00001600;
+    env->excp_vectors[POWERPC_EXCP_VPUA]     = 0x00001700;
+    env->excp_vectors[POWERPC_EXCP_THERM]    = 0x00001800;
+#endif
+}
+#endif
+
 /*****************************************************************************/
 /* PowerPC implementations definitions                                       */
 
@@ -2183,6 +2500,7 @@ static void init_proc_401 (CPUPPCState *env)
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
+    init_excp_4xx_real(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
@@ -2218,6 +2536,7 @@ static void init_proc_401x2 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    init_excp_4xx_softmmu(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
@@ -2234,8 +2553,9 @@ static void init_proc_401x2 (CPUPPCState *env)
 #define POWERPC_INPUT_401x3  (PPC_FLAGS_INPUT_401)
 #define POWERPC_BFDM_401x3   (bfd_mach_ppc_403)
 
-static void init_proc_401x2 (CPUPPCState *env)
+static void init_proc_401x3 (CPUPPCState *env)
 {
+    init_excp_4xx_softmmu(env);
 }
 #endif /* TODO */
 
@@ -2271,6 +2591,7 @@ static void init_proc_IOP480 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    init_excp_4xx_softmmu(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
@@ -2291,6 +2612,7 @@ static void init_proc_403 (CPUPPCState *env)
     gen_spr_401_403(env);
     gen_spr_403(env);
     gen_spr_403_real(env);
+    init_excp_4xx_real(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
@@ -2326,6 +2648,7 @@ static void init_proc_403GCX (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    init_excp_4xx_softmmu(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
@@ -2361,6 +2684,7 @@ static void init_proc_405 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    init_excp_4xx_softmmu(env);
     /* Allocate hardware IRQ controller */
     ppc405_irq_init(env);
 }
@@ -2402,6 +2726,7 @@ static void init_proc_440EP (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    init_excp_BookE(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
@@ -2426,6 +2751,7 @@ static void init_proc_440GP (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    init_excp_BookE(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
@@ -2451,6 +2777,7 @@ static void init_proc_440x4 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    init_excp_BookE(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 #endif /* TODO */
@@ -2492,6 +2819,7 @@ static void init_proc_440x5 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    init_excp_BookE(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
@@ -2509,6 +2837,36 @@ static void init_proc_440x5 (CPUPPCState *env)
 
 static void init_proc_460 (CPUPPCState *env)
 {
+    /* Time base */
+    gen_tbl(env);
+    gen_spr_BookE(env);
+    gen_spr_440(env);
+    spr_register(env, SPR_BOOKE_MCSR, "MCSR",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_BOOKE_MCSRR1, "MCSRR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_440_CCR1, "CCR1",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_DCRIPR, "SPR_DCRIPR",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    /* Memory management */
+    env->nb_tlb = 64;
+    env->nb_ways = 1;
+    env->id_tlbs = 0;
+    init_excp_BookE(env);
+    /* XXX: TODO: allocate internal IRQ controller */
 }
 #endif /* TODO */
 
@@ -2527,7 +2885,7 @@ static void init_proc_460 (CPUPPCState *env)
 #define POWERPC_INPUT_460F   (PPC_FLAGS_INPUT_BookE)
 #define POWERPC_BFDM_460F    (bfd_mach_ppc_403)
 
-static void init_proc_460 (CPUPPCState *env)
+static void init_proc_460F (CPUPPCState *env)
 {
     /* Time base */
     gen_tbl(env);
@@ -2557,6 +2915,7 @@ static void init_proc_460 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    init_excp_BookE(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 #endif /* TODO */
@@ -2578,6 +2937,7 @@ static void init_proc_460 (CPUPPCState *env)
 
 static void init_proc_BookE (CPUPPCState *env)
 {
+    init_excp_BookE(env);
 }
 #endif /* TODO */
 
@@ -2610,6 +2970,7 @@ static void init_proc_e500 (CPUPPCState *env)
     env->nb_tlb = 64;
     env->nb_ways = 1;
     env->id_tlbs = 0;
+    init_excp_BookE(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 #endif /* TODO */
@@ -2678,6 +3039,7 @@ static void init_proc_601 (CPUPPCState *env)
     env->nb_ways = 2;
     env->id_tlbs = 0;
     env->id_tlbs = 0;
+    init_excp_601(env);
     /* XXX: TODO: allocate internal IRQ controller */
 }
 
@@ -2712,6 +3074,7 @@ static void init_proc_602 (CPUPPCState *env)
     /* Memory management */
     gen_low_BATs(env);
     gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_602(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -2744,6 +3107,7 @@ static void init_proc_603 (CPUPPCState *env)
     /* Memory management */
     gen_low_BATs(env);
     gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_603(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -2781,6 +3145,7 @@ static void init_proc_603E (CPUPPCState *env)
     /* Memory management */
     gen_low_BATs(env);
     gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_603(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -2820,6 +3185,7 @@ static void init_proc_G2 (CPUPPCState *env)
     gen_low_BATs(env);
     gen_high_BATs(env);
     gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_G2(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -2859,6 +3225,7 @@ static void init_proc_G2LE (CPUPPCState *env)
     gen_low_BATs(env);
     gen_high_BATs(env);
     gen_6xx_7xx_soft_tlb(env, 64, 2);
+    init_excp_G2(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -2890,6 +3257,7 @@ static void init_proc_604 (CPUPPCState *env)
                  0x00000000);
     /* Memory management */
     gen_low_BATs(env);
+    init_excp_604(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -2923,6 +3291,7 @@ static void init_proc_7x0 (CPUPPCState *env)
                  0x00000000);
     /* Memory management */
     gen_low_BATs(env);
+    init_excp_7x0(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -2963,6 +3332,7 @@ static void init_proc_750fx (CPUPPCState *env)
     gen_low_BATs(env);
     /* PowerPC 750fx & 750gx has 8 DBATs and 8 IBATs */
     gen_high_BATs(env);
+    init_excp_750FX(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -3038,6 +3408,7 @@ static void init_proc_7400 (CPUPPCState *env)
     gen_spr_thrm(env);
     /* Memory management */
     gen_low_BATs(env);
+    init_excp_7400(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -3076,6 +3447,7 @@ static void init_proc_7410 (CPUPPCState *env)
                  0x00000000);
     /* Memory management */
     gen_low_BATs(env);
+    init_excp_7400(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -3201,6 +3573,7 @@ static void init_proc_7450 (CPUPPCState *env)
     /* Memory management */
     gen_low_BATs(env);
     gen_74xx_soft_tlb(env);
+    init_excp_7450(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -3297,6 +3670,7 @@ static void init_proc_7445 (CPUPPCState *env)
     gen_low_BATs(env);
     gen_high_BATs(env);
     gen_74xx_soft_tlb(env);
+    init_excp_7450(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -3395,6 +3769,7 @@ static void init_proc_7455 (CPUPPCState *env)
     gen_low_BATs(env);
     gen_high_BATs(env);
     gen_74xx_soft_tlb(env);
+    init_excp_7450(env);
     /* Allocate hardware IRQ controller */
     ppc6xx_irq_init(env);
 }
@@ -3439,6 +3814,7 @@ static void init_proc_970 (CPUPPCState *env)
 #if 0 // TODO
     env->slb_nr = 32;
 #endif
+    init_excp_970(env);
     /* Allocate hardware IRQ controller */
     ppc970_irq_init(env);
 }
@@ -3481,6 +3857,7 @@ static void init_proc_970FX (CPUPPCState *env)
 #if 0 // TODO
     env->slb_nr = 32;
 #endif
+    init_excp_970(env);
     /* Allocate hardware IRQ controller */
     ppc970_irq_init(env);
 }
@@ -3523,6 +3900,7 @@ static void init_proc_970GX (CPUPPCState *env)
 #if 0 // TODO
     env->slb_nr = 32;
 #endif
+    init_excp_970(env);
     /* Allocate hardware IRQ controller */
     ppc970_irq_init(env);
 }
@@ -3552,6 +3930,7 @@ static void init_proc_620 (CPUPPCState *env)
     /* Memory management */
     gen_low_BATs(env);
     gen_high_BATs(env);
+    init_excp_620(env);
     /* XXX: TODO: initialize internal interrupt controller */
 }
 #endif /* TODO */
@@ -5046,7 +5425,15 @@ static ppc_def_t ppc_defs[] = {
 static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
 {
 #if !defined(CONFIG_USER_ONLY)
+    int i;
+
     env->irq_inputs = NULL;
+    /* Set all exception vectors to an invalid address */
+    for (i = 0; i < POWERPC_EXCP_NB; i++)
+        env->excp_vectors[i] = (target_ulong)(-1ULL);
+    env->excp_prefix = 0x00000000;
+    env->ivor_mask = 0x00000000;
+    env->ivpr_mask = 0x00000000;
 #endif
     /* Default MMU definitions */
     env->nb_BATs = 0;