diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-09-29 13:06:16 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-09-29 13:06:16 +0000 |
commit | e1833e1f96456fd8fc17463246fe0b2050e68efb (patch) | |
tree | 5d50859e3cb0a1c2628811d7255f112a9f87cdca | |
parent | f93732914e0b06539170e84f046f01ebe99980f3 (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.c | 570 | ||||
-rw-r--r-- | linux-user/main.c | 458 | ||||
-rw-r--r-- | target-ppc/cpu.h | 268 | ||||
-rw-r--r-- | target-ppc/helper.c | 993 | ||||
-rw-r--r-- | target-ppc/op_helper.c | 20 | ||||
-rw-r--r-- | target-ppc/op_mem.h | 48 | ||||
-rw-r--r-- | target-ppc/translate.c | 440 | ||||
-rw-r--r-- | target-ppc/translate_init.c | 421 |
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; |