summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-09-29 13:06:16 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-09-29 13:06:16 +0000
commite1833e1f96456fd8fc17463246fe0b2050e68efb (patch)
tree5d50859e3cb0a1c2628811d7255f112a9f87cdca
parentf93732914e0b06539170e84f046f01ebe99980f3 (diff)
Rework PowerPC exceptions model to make it more versatile:
* 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
-rw-r--r--darwin-user/main.c570
-rw-r--r--linux-user/main.c458
-rw-r--r--target-ppc/cpu.h268
-rw-r--r--target-ppc/helper.c993
-rw-r--r--target-ppc/op_helper.c20
-rw-r--r--target-ppc/op_mem.h48
-rw-r--r--target-ppc/translate.c440
-rw-r--r--target-ppc/translate_init.c421
8 files changed, 1958 insertions, 1260 deletions
diff --git a/darwin-user/main.c b/darwin-user/main.c
index fd62fc1b86..affd874543 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -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);
}
diff --git a/linux-user/main.c b/linux-user/main.c
index b70c070c3f..fb424ad887 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -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);
}
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 79712b0c65..57e8f358c2 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -149,6 +149,127 @@ enum {
};
/*****************************************************************************/
+/* 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 {
PPC_FLAGS_INPUT_UNKNOWN = 0,
@@ -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 */
};
/*****************************************************************************/
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index f27a7f50a5..8b6bed1e51 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -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);
}
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index df00ba19c7..9a79953f7d 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -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);
}
}
diff --git a/target-ppc/op_mem.h b/target-ppc/op_mem.h
index f1229859f3..13440817bf 100644
--- a/target-ppc/op_mem.h
+++ b/target-ppc/op_mem.h
@@ -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;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 2e5cb6bcd4..dc4e758914 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -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();
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index e3cb183609..109dcdc256 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -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)
@@ -2153,6 +2153,323 @@ static void gen_spr_620 (CPUPPCState *env)
*/
/*****************************************************************************/
+/* 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 */
/* PowerPC 40x instruction set */
@@ -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;