提交 e1833e1f 编写于 作者: J j_mayer

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
上级 f9373291
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -148,6 +148,127 @@ enum {
POWERPC_EXCP_BOOKE,
};
/*****************************************************************************/
/* Exception vectors definitions */
enum {
POWERPC_EXCP_NONE = -1,
/* The 64 first entries are used by the PowerPC embedded specification */
POWERPC_EXCP_CRITICAL = 0, /* Critical input */
POWERPC_EXCP_MCHECK = 1, /* Machine check exception */
POWERPC_EXCP_DSI = 2, /* Data storage exception */
POWERPC_EXCP_ISI = 3, /* Instruction storage exception */
POWERPC_EXCP_EXTERNAL = 4, /* External input */
POWERPC_EXCP_ALIGN = 5, /* Alignment exception */
POWERPC_EXCP_PROGRAM = 6, /* Program exception */
POWERPC_EXCP_FPU = 7, /* Floating-point unavailable exception */
POWERPC_EXCP_SYSCALL = 8, /* System call exception */
POWERPC_EXCP_APU = 9, /* Auxiliary processor unavailable */
POWERPC_EXCP_DECR = 10, /* Decrementer exception */
POWERPC_EXCP_FIT = 11, /* Fixed-interval timer interrupt */
POWERPC_EXCP_WDT = 12, /* Watchdog timer interrupt */
POWERPC_EXCP_DTLB = 13, /* Data TLB error */
POWERPC_EXCP_ITLB = 14, /* Instruction TLB error */
POWERPC_EXCP_DEBUG = 15, /* Debug interrupt */
/* Vectors 16 to 31 are reserved */
#if defined(TARGET_PPCEMB)
POWERPC_EXCP_SPEU = 32, /* SPE/embedded floating-point unavailable */
POWERPC_EXCP_EFPDI = 33, /* Embedded floating-point data interrupt */
POWERPC_EXCP_EFPRI = 34, /* Embedded floating-point round interrupt */
POWERPC_EXCP_EPERFM = 35, /* Embedded performance monitor interrupt */
POWERPC_EXCP_DOORI = 36, /* Embedded doorbell interrupt */
POWERPC_EXCP_DOORCI = 37, /* Embedded doorbell critical interrupt */
#endif /* defined(TARGET_PPCEMB) */
/* Vectors 38 to 63 are reserved */
/* Exceptions defined in the PowerPC server specification */
POWERPC_EXCP_RESET = 64, /* System reset exception */
#if defined(TARGET_PPC64) /* PowerPC 64 */
POWERPC_EXCP_DSEG = 65, /* Data segment exception */
POWERPC_EXCP_ISEG = 66, /* Instruction segment exception */
#endif /* defined(TARGET_PPC64) */
#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
POWERPC_EXCP_HDECR = 67, /* Hypervisor decrementer exception */
#endif /* defined(TARGET_PPC64H) */
POWERPC_EXCP_TRACE = 68, /* Trace exception */
#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
POWERPC_EXCP_HDSI = 69, /* Hypervisor data storage exception */
POWERPC_EXCP_HISI = 70, /* Hypervisor instruction storage exception */
POWERPC_EXCP_HDSEG = 71, /* Hypervisor data segment exception */
POWERPC_EXCP_HISEG = 72, /* Hypervisor instruction segment exception */
#endif /* defined(TARGET_PPC64H) */
POWERPC_EXCP_VPU = 73, /* Vector unavailable exception */
/* 40x specific exceptions */
POWERPC_EXCP_PIT = 74, /* Programmable interval timer interrupt */
/* 601 specific exceptions */
POWERPC_EXCP_IO = 75, /* IO error exception */
POWERPC_EXCP_RUNM = 76, /* Run mode exception */
/* 602 specific exceptions */
POWERPC_EXCP_EMUL = 77, /* Emulation trap exception */
/* 602/603 specific exceptions */
POWERPC_EXCP_IFTLB = 78, /* Instruction fetch TLB error */
POWERPC_EXCP_DLTLB = 79, /* Data load TLB miss */
POWERPC_EXCP_DSTLB = 80, /* Data store TLB miss */
/* Exceptions available on most PowerPC */
POWERPC_EXCP_FPA = 81, /* Floating-point assist exception */
POWERPC_EXCP_IABR = 82, /* Instruction address breakpoint */
POWERPC_EXCP_SMI = 83, /* System management interrupt */
POWERPC_EXCP_PERFM = 84, /* Embedded performance monitor interrupt */
/* 7xx/74xx specific exceptions */
POWERPC_EXCP_THERM = 85, /* Thermal interrupt */
/* 74xx specific exceptions */
POWERPC_EXCP_VPUA = 86, /* Vector assist exception */
/* 970FX specific exceptions */
POWERPC_EXCP_SOFTP = 87, /* Soft patch exception */
POWERPC_EXCP_MAINT = 88, /* Maintenance exception */
/* EOL */
POWERPC_EXCP_NB = 96,
/* Qemu exceptions: used internally during code translation */
POWERPC_EXCP_STOP = 0x200, /* stop translation */
POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */
/* Qemu exceptions: special cases we want to stop translation */
POWERPC_EXCP_SYNC = 0x202, /* context synchronizing instruction */
POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only */
};
/* Exceptions error codes */
enum {
/* Exception subtypes for POWERPC_EXCP_ALIGN */
POWERPC_EXCP_ALIGN_FP = 0x01, /* FP alignment exception */
POWERPC_EXCP_ALIGN_LST = 0x02, /* Unaligned mult/extern load/store */
POWERPC_EXCP_ALIGN_LE = 0x03, /* Multiple little-endian access */
POWERPC_EXCP_ALIGN_PROT = 0x04, /* Access cross protection boundary */
POWERPC_EXCP_ALIGN_BAT = 0x05, /* Access cross a BAT/seg boundary */
POWERPC_EXCP_ALIGN_CACHE = 0x06, /* Impossible dcbz access */
/* Exception subtypes for POWERPC_EXCP_PROGRAM */
/* FP exceptions */
POWERPC_EXCP_FP = 0x10,
POWERPC_EXCP_FP_OX = 0x01, /* FP overflow */
POWERPC_EXCP_FP_UX = 0x02, /* FP underflow */
POWERPC_EXCP_FP_ZX = 0x03, /* FP divide by zero */
POWERPC_EXCP_FP_XX = 0x04, /* FP inexact */
POWERPC_EXCP_FP_VXNAN = 0x05, /* FP invalid SNaN op */
POWERPC_EXCP_FP_VXISI = 0x06, /* FP invalid infinite subtraction */
POWERPC_EXCP_FP_VXIDI = 0x07, /* FP invalid infinite divide */
POWERPC_EXCP_FP_VXZDZ = 0x08, /* FP invalid zero divide */
POWERPC_EXCP_FP_VXIMZ = 0x09, /* FP invalid infinite * zero */
POWERPC_EXCP_FP_VXVC = 0x0A, /* FP invalid compare */
POWERPC_EXCP_FP_VXSOFT = 0x0B, /* FP invalid operation */
POWERPC_EXCP_FP_VXSQRT = 0x0C, /* FP invalid square root */
POWERPC_EXCP_FP_VXCVI = 0x0D, /* FP invalid integer conversion */
/* Invalid instruction */
POWERPC_EXCP_INVAL = 0x20,
POWERPC_EXCP_INVAL_INVAL = 0x01, /* Invalid instruction */
POWERPC_EXCP_INVAL_LSWX = 0x02, /* Invalid lswx instruction */
POWERPC_EXCP_INVAL_SPR = 0x03, /* Invalid SPR access */
POWERPC_EXCP_INVAL_FP = 0x04, /* Unimplemented mandatory fp instr */
/* Privileged instruction */
POWERPC_EXCP_PRIV = 0x30,
POWERPC_EXCP_PRIV_OPC = 0x01, /* Privileged operation exception */
POWERPC_EXCP_PRIV_REG = 0x02, /* Privileged register exception */
/* Trap */
POWERPC_EXCP_TRAP = 0x40,
};
/*****************************************************************************/
/* Input pins model */
enum {
......@@ -411,6 +532,11 @@ struct CPUPPCState {
*/
uint32_t irq_input_state;
void **irq_inputs;
/* Exception vectors */
target_ulong excp_vectors[POWERPC_EXCP_NB];
target_ulong excp_prefix;
target_ulong ivor_mask;
target_ulong ivpr_mask;
#endif
/* Those resources are used only during code translation */
......@@ -634,9 +760,9 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
#define SPR_BOOKE_IAC1 (0x138)
#define SPR_HRMOR (0x139)
#define SPR_BOOKE_IAC2 (0x139)
#define SPR_HSSR0 (0x13A)
#define SPR_HSRR0 (0x13A)
#define SPR_BOOKE_IAC3 (0x13A)
#define SPR_HSSR1 (0x13B)
#define SPR_HSRR1 (0x13B)
#define SPR_BOOKE_IAC4 (0x13B)
#define SPR_LPCR (0x13C)
#define SPR_BOOKE_DAC1 (0x13C)
......@@ -948,117 +1074,6 @@ enum {
ACCESS_CACHE = 0x60, /* Cache manipulation */
};
/*****************************************************************************/
/* Exceptions */
#define EXCP_NONE -1
/* PowerPC hardware exceptions : exception vectors defined in PowerPC book 3 */
#define EXCP_RESET 0x0100 /* System reset */
#define EXCP_MACHINE_CHECK 0x0200 /* Machine check exception */
#define EXCP_DSI 0x0300 /* Data storage exception */
#define EXCP_DSEG 0x0380 /* Data segment exception */
#define EXCP_ISI 0x0400 /* Instruction storage exception */
#define EXCP_ISEG 0x0480 /* Instruction segment exception */
#define EXCP_EXTERNAL 0x0500 /* External interruption */
#define EXCP_ALIGN 0x0600 /* Alignment exception */
#define EXCP_PROGRAM 0x0700 /* Program exception */
#define EXCP_NO_FP 0x0800 /* Floating point unavailable exception */
#define EXCP_DECR 0x0900 /* Decrementer exception */
#define EXCP_HDECR 0x0980 /* Hypervisor decrementer exception */
#define EXCP_SYSCALL 0x0C00 /* System call */
#define EXCP_TRACE 0x0D00 /* Trace exception */
#define EXCP_PERF 0x0F00 /* Performance monitor exception */
/* Exceptions defined in PowerPC 32 bits programming environment manual */
#define EXCP_FP_ASSIST 0x0E00 /* Floating-point assist */
/* Implementation specific exceptions */
/* 40x exceptions */
#define EXCP_40x_PIT 0x1000 /* Programmable interval timer interrupt */
#define EXCP_40x_FIT 0x1010 /* Fixed interval timer interrupt */
#define EXCP_40x_WATCHDOG 0x1020 /* Watchdog timer exception */
#define EXCP_40x_DTLBMISS 0x1100 /* Data TLB miss exception */
#define EXCP_40x_ITLBMISS 0x1200 /* Instruction TLB miss exception */
#define EXCP_40x_DEBUG 0x2000 /* Debug exception */
/* 405 specific exceptions */
#define EXCP_405_APU 0x0F20 /* APU unavailable exception */
/* 440 specific exceptions */
#define EXCP_440_CRIT 0x0100 /* Critical interrupt */
#define EXCP_440_SPEU 0x1600 /* SPE unavailable exception */
#define EXCP_440_SPED 0x1700 /* SPE floating-point data exception */
#define EXCP_440_SPER 0x1800 /* SPE floating-point round exception */
/* TLB assist exceptions (602/603) */
#define EXCP_I_TLBMISS 0x1000 /* Instruction TLB miss */
#define EXCP_DL_TLBMISS 0x1100 /* Data load TLB miss */
#define EXCP_DS_TLBMISS 0x1200 /* Data store TLB miss */
/* Breakpoint exceptions (602/603/604/620/740/745/750/755...) */
#define EXCP_IABR 0x1300 /* Instruction address breakpoint */
#define EXCP_SMI 0x1400 /* System management interrupt */
/* Altivec related exceptions */
#define EXCP_VPU 0x0F20 /* VPU unavailable exception */
/* 601 specific exceptions */
#define EXCP_601_IO 0x0A00 /* IO error exception */
#define EXCP_601_RUNM 0x2000 /* Run mode exception */
/* 602 specific exceptions */
#define EXCP_602_WATCHDOG 0x1500 /* Watchdog exception */
#define EXCP_602_EMUL 0x1600 /* Emulation trap exception */
/* G2 specific exceptions */
#define EXCP_G2_CRIT 0x0A00 /* Critical interrupt */
/* MPC740/745/750 & IBM 750 specific exceptions */
#define EXCP_THRM 0x1700 /* Thermal management interrupt */
/* 74xx specific exceptions */
#define EXCP_74xx_VPUA 0x1600 /* VPU assist exception */
/* 970FX specific exceptions */
#define EXCP_970_SOFTP 0x1500 /* Soft patch exception */
#define EXCP_970_MAINT 0x1600 /* Maintenance exception */
#define EXCP_970_THRM 0x1800 /* Thermal exception */
#define EXCP_970_VPUA 0x1700 /* VPU assist exception */
/* SPE related exceptions */
#define EXCP_NO_SPE 0x0F20 /* SPE unavailable exception */
/* End of exception vectors area */
#define EXCP_PPC_MAX 0x4000
/* Qemu exceptions: special cases we want to stop translation */
#define EXCP_MTMSR 0x11000 /* mtmsr instruction: */
/* may change privilege level */
#define EXCP_BRANCH 0x11001 /* branch instruction */
#define EXCP_SYSCALL_USER 0x12000 /* System call in user mode only */
/* Error codes */
enum {
/* Exception subtypes for EXCP_ALIGN */
EXCP_ALIGN_FP = 0x01, /* FP alignment exception */
EXCP_ALIGN_LST = 0x02, /* Unaligned mult/extern load/store */
EXCP_ALIGN_LE = 0x03, /* Multiple little-endian access */
EXCP_ALIGN_PROT = 0x04, /* Access cross protection boundary */
EXCP_ALIGN_BAT = 0x05, /* Access cross a BAT/seg boundary */
EXCP_ALIGN_CACHE = 0x06, /* Impossible dcbz access */
/* Exception subtypes for EXCP_PROGRAM */
/* FP exceptions */
EXCP_FP = 0x10,
EXCP_FP_OX = 0x01, /* FP overflow */
EXCP_FP_UX = 0x02, /* FP underflow */
EXCP_FP_ZX = 0x03, /* FP divide by zero */
EXCP_FP_XX = 0x04, /* FP inexact */
EXCP_FP_VXNAN = 0x05, /* FP invalid SNaN op */
EXCP_FP_VXISI = 0x06, /* FP invalid infinite subtraction */
EXCP_FP_VXIDI = 0x07, /* FP invalid infinite divide */
EXCP_FP_VXZDZ = 0x08, /* FP invalid zero divide */
EXCP_FP_VXIMZ = 0x09, /* FP invalid infinite * zero */
EXCP_FP_VXVC = 0x0A, /* FP invalid compare */
EXCP_FP_VXSOFT = 0x0B, /* FP invalid operation */
EXCP_FP_VXSQRT = 0x0C, /* FP invalid square root */
EXCP_FP_VXCVI = 0x0D, /* FP invalid integer conversion */
/* Invalid instruction */
EXCP_INVAL = 0x20,
EXCP_INVAL_INVAL = 0x01, /* Invalid instruction */
EXCP_INVAL_LSWX = 0x02, /* Invalid lswx instruction */
EXCP_INVAL_SPR = 0x03, /* Invalid SPR access */
EXCP_INVAL_FP = 0x04, /* Unimplemented mandatory fp instr */
/* Privileged instruction */
EXCP_PRIV = 0x30,
EXCP_PRIV_OPC = 0x01, /* Privileged operation exception */
EXCP_PRIV_REG = 0x02, /* Privileged register exception */
/* Trap */
EXCP_TRAP = 0x40,
};
/* Hardware interruption sources:
* all those exception can be raised simulteaneously
*/
......@@ -1130,19 +1145,22 @@ enum {
/* Hardware exceptions definitions */
enum {
/* External hardware exception sources */
PPC_INTERRUPT_RESET = 0, /* Reset exception */
PPC_INTERRUPT_MCK = 1, /* Machine check exception */
PPC_INTERRUPT_EXT = 2, /* External interrupt */
PPC_INTERRUPT_SMI = 3, /* System management interrupt */
PPC_INTERRUPT_CEXT = 4, /* Critical external interrupt */
PPC_INTERRUPT_DEBUG = 5, /* External debug exception */
PPC_INTERRUPT_THERM = 6, /* Thermal exception */
PPC_INTERRUPT_RESET = 0, /* Reset exception */
PPC_INTERRUPT_MCK = 1, /* Machine check exception */
PPC_INTERRUPT_EXT = 2, /* External interrupt */
PPC_INTERRUPT_SMI = 3, /* System management interrupt */
PPC_INTERRUPT_CEXT = 4, /* Critical external interrupt */
PPC_INTERRUPT_DEBUG = 5, /* External debug exception */
PPC_INTERRUPT_THERM = 6, /* Thermal exception */
/* Internal hardware exception sources */
PPC_INTERRUPT_DECR = 7, /* Decrementer exception */
PPC_INTERRUPT_HDECR = 8, /* Hypervisor decrementer exception */
PPC_INTERRUPT_PIT = 9, /* Programmable inteval timer interrupt */
PPC_INTERRUPT_FIT = 10, /* Fixed interval timer interrupt */
PPC_INTERRUPT_WDT = 11, /* Watchdog timer interrupt */
PPC_INTERRUPT_DECR = 7, /* Decrementer exception */
PPC_INTERRUPT_HDECR = 8, /* Hypervisor decrementer exception */
PPC_INTERRUPT_PIT = 9, /* Programmable inteval timer interrupt */
PPC_INTERRUPT_FIT = 10, /* Fixed interval timer interrupt */
PPC_INTERRUPT_WDT = 11, /* Watchdog timer interrupt */
PPC_INTERRUPT_CDOORBELL = 12, /* Critical doorbell interrupt */
PPC_INTERRUPT_DOORBELL = 13, /* Doorbell interrupt */
PPC_INTERRUPT_PERFM = 14, /* Performance monitor interrupt */
};
/*****************************************************************************/
......
......@@ -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);
}
......
......@@ -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);
}
}
......
......@@ -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;
......
......@@ -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();
......
......@@ -192,7 +192,7 @@ static void spr_write_ibatu (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_ibatu((sprn - SPR_IBAT0U) / 2);
RET_STOP(ctx);
GEN_STOP(ctx);
}
static void spr_write_ibatu_h (void *opaque, int sprn)
......@@ -200,7 +200,7 @@ static void spr_write_ibatu_h (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_ibatu((sprn - SPR_IBAT4U) / 2);
RET_STOP(ctx);
GEN_STOP(ctx);
}
static void spr_write_ibatl (void *opaque, int sprn)
......@@ -208,7 +208,7 @@ static void spr_write_ibatl (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_ibatl((sprn - SPR_IBAT0L) / 2);
RET_STOP(ctx);
GEN_STOP(ctx);
}
static void spr_write_ibatl_h (void *opaque, int sprn)
......@@ -216,7 +216,7 @@ static void spr_write_ibatl_h (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_ibatl((sprn - SPR_IBAT4L) / 2);
RET_STOP(ctx);
GEN_STOP(ctx);
}
/* DBAT0U...DBAT7U */
......@@ -236,7 +236,7 @@ static void spr_write_dbatu (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_dbatu((sprn - SPR_DBAT0U) / 2);
RET_STOP(ctx);
GEN_STOP(ctx);
}
static void spr_write_dbatu_h (void *opaque, int sprn)
......@@ -244,7 +244,7 @@ static void spr_write_dbatu_h (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_dbatu((sprn - SPR_DBAT4U) / 2);
RET_STOP(ctx);
GEN_STOP(ctx);
}
static void spr_write_dbatl (void *opaque, int sprn)
......@@ -252,7 +252,7 @@ static void spr_write_dbatl (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_dbatl((sprn - SPR_DBAT0L) / 2);
RET_STOP(ctx);
GEN_STOP(ctx);
}
static void spr_write_dbatl_h (void *opaque, int sprn)
......@@ -260,7 +260,7 @@ static void spr_write_dbatl_h (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_dbatl((sprn - SPR_DBAT4L) / 2);
RET_STOP(ctx);
GEN_STOP(ctx);
}
/* SDR1 */
......@@ -274,7 +274,7 @@ static void spr_write_sdr1 (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_sdr1();
RET_STOP(ctx);
GEN_STOP(ctx);
}
/* 64 bits PowerPC specific SPRs */
......@@ -291,7 +291,7 @@ static void spr_write_asr (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_asr();
RET_STOP(ctx);
GEN_STOP(ctx);
}
#endif
#endif
......@@ -332,7 +332,7 @@ static void spr_write_601_ubatu (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_601_batu((sprn - SPR_IBAT0U) / 2);
RET_STOP(ctx);
GEN_STOP(ctx);
}
static void spr_write_601_ubatl (void *opaque, int sprn)
......@@ -340,7 +340,7 @@ static void spr_write_601_ubatl (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_601_batl((sprn - SPR_IBAT0L) / 2);
RET_STOP(ctx);
GEN_STOP(ctx);
}
#endif
......@@ -362,7 +362,7 @@ static void spr_write_40x_dbcr0 (void *opaque, int sprn)
gen_op_store_40x_dbcr0();
/* We must stop translation as we may have rebooted */
RET_STOP(ctx);
GEN_STOP(ctx);
}
static void spr_write_40x_sler (void *opaque, int sprn)
......@@ -373,7 +373,7 @@ static void spr_write_40x_sler (void *opaque, int sprn)
/* We must stop the translation as we may have changed
* some regions endianness
*/
RET_STOP(ctx);
GEN_STOP(ctx);
}
static void spr_write_booke_tcr (void *opaque, int sprn)
......@@ -400,7 +400,7 @@ static void spr_write_403_pbr (void *opaque, int sprn)
DisasContext *ctx = opaque;
gen_op_store_403_pb(sprn - SPR_403_PBL1);
RET_STOP(ctx);
GEN_STOP(ctx);
}
static void spr_write_pir (void *opaque, int sprn)
......@@ -2152,6 +2152,323 @@ static void gen_spr_620 (CPUPPCState *env)
* ... and more (thermal management, performance counters, ...)
*/
/*****************************************************************************/
/* Exception vectors models */
static void init_excp_4xx_real (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_PIT] = 0x00001000;
env->excp_vectors[POWERPC_EXCP_FIT] = 0x00001010;
env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001020;
env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00002000;
#endif
}
static void init_excp_4xx_softmmu (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_PIT] = 0x00001000;
env->excp_vectors[POWERPC_EXCP_FIT] = 0x00001010;
env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001020;
env->excp_vectors[POWERPC_EXCP_DTLB] = 0x00001100;
env->excp_vectors[POWERPC_EXCP_ITLB] = 0x00001200;
env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00002000;
#endif
}
static void init_excp_BookE (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_APU] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_FIT] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_WDT] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_DTLB] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_ITLB] = 0x00000000;
env->excp_vectors[POWERPC_EXCP_DEBUG] = 0x00000000;
env->excp_prefix = 0x00000000;
env->ivor_mask = 0x0000FFE0;
env->ivpr_mask = 0xFFFF0000;
#endif
}
static void init_excp_601 (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
env->excp_vectors[POWERPC_EXCP_IO] = 0x00000A00;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_RUNM] = 0x00002000;
env->excp_prefix = 0xFFF00000;
#endif
}
static void init_excp_602 (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_FPA] = 0x00000E00;
env->excp_vectors[POWERPC_EXCP_IFTLB] = 0x00001000;
env->excp_vectors[POWERPC_EXCP_DLTLB] = 0x00001100;
env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
env->excp_vectors[POWERPC_EXCP_WDT] = 0x00001500;
env->excp_vectors[POWERPC_EXCP_EMUL] = 0x00001600;
env->excp_prefix = 0xFFF00000;
#endif
}
static void init_excp_603 (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_IFTLB] = 0x00001000;
env->excp_vectors[POWERPC_EXCP_DLTLB] = 0x00001100;
env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
#endif
}
static void init_excp_G2 (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
env->excp_vectors[POWERPC_EXCP_CRITICAL] = 0x00000A00;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_IFTLB] = 0x00001000;
env->excp_vectors[POWERPC_EXCP_DLTLB] = 0x00001100;
env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
#endif
}
static void init_excp_604 (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
#endif
}
#if defined (TODO)
static void init_excp_620 (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_FPA] = 0x00000E00;
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
#endif
}
#endif /* defined (TODO) */
static void init_excp_7x0 (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700;
#endif
}
static void init_excp_750FX (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700;
#endif
}
static void init_excp_7400 (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_VPU] = 0x00000F20;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001600;
env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001700;
#endif
}
#if defined (TODO)
static void init_excp_7450 (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_VPU] = 0x00000F20;
env->excp_vectors[POWERPC_EXCP_IFTLB] = 0x00001000;
env->excp_vectors[POWERPC_EXCP_DLTLB] = 0x00001100;
env->excp_vectors[POWERPC_EXCP_DSTLB] = 0x00001200;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_SMI] = 0x00001400;
env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001600;
#endif
}
#endif /* defined (TODO) */
#if defined (TARGET_PPC64)
static void init_excp_970 (CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_RESET] = 0x00000100;
env->excp_vectors[POWERPC_EXCP_MCHECK] = 0x00000200;
env->excp_vectors[POWERPC_EXCP_DSI] = 0x00000300;
env->excp_vectors[POWERPC_EXCP_DSEG] = 0x00000380;
env->excp_vectors[POWERPC_EXCP_ISI] = 0x00000400;
env->excp_vectors[POWERPC_EXCP_ISEG] = 0x00000480;
env->excp_vectors[POWERPC_EXCP_EXTERNAL] = 0x00000500;
env->excp_vectors[POWERPC_EXCP_ALIGN] = 0x00000600;
env->excp_vectors[POWERPC_EXCP_PROGRAM] = 0x00000700;
env->excp_vectors[POWERPC_EXCP_FPU] = 0x00000800;
env->excp_vectors[POWERPC_EXCP_DECR] = 0x00000900;
#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
env->excp_vectors[POWERPC_EXCP_HDECR] = 0x00000980;
#endif
env->excp_vectors[POWERPC_EXCP_SYSCALL] = 0x00000C00;
env->excp_vectors[POWERPC_EXCP_TRACE] = 0x00000D00;
env->excp_vectors[POWERPC_EXCP_PERFM] = 0x00000F00;
env->excp_vectors[POWERPC_EXCP_VPU] = 0x00000F20;
env->excp_vectors[POWERPC_EXCP_IABR] = 0x00001300;
env->excp_vectors[POWERPC_EXCP_MAINT] = 0x00001600;
env->excp_vectors[POWERPC_EXCP_VPUA] = 0x00001700;
env->excp_vectors[POWERPC_EXCP_THERM] = 0x00001800;
#endif
}
#endif
/*****************************************************************************/
/* PowerPC implementations definitions */
......@@ -2183,6 +2500,7 @@ static void init_proc_401 (CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
init_excp_4xx_real(env);
/* XXX: TODO: allocate internal IRQ controller */
}
......@@ -2218,6 +2536,7 @@ static void init_proc_401x2 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_4xx_softmmu(env);
/* XXX: TODO: allocate internal IRQ controller */
}
......@@ -2234,8 +2553,9 @@ static void init_proc_401x2 (CPUPPCState *env)
#define POWERPC_INPUT_401x3 (PPC_FLAGS_INPUT_401)
#define POWERPC_BFDM_401x3 (bfd_mach_ppc_403)
static void init_proc_401x2 (CPUPPCState *env)
static void init_proc_401x3 (CPUPPCState *env)
{
init_excp_4xx_softmmu(env);
}
#endif /* TODO */
......@@ -2271,6 +2591,7 @@ static void init_proc_IOP480 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_4xx_softmmu(env);
/* XXX: TODO: allocate internal IRQ controller */
}
......@@ -2291,6 +2612,7 @@ static void init_proc_403 (CPUPPCState *env)
gen_spr_401_403(env);
gen_spr_403(env);
gen_spr_403_real(env);
init_excp_4xx_real(env);
/* XXX: TODO: allocate internal IRQ controller */
}
......@@ -2326,6 +2648,7 @@ static void init_proc_403GCX (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_4xx_softmmu(env);
/* XXX: TODO: allocate internal IRQ controller */
}
......@@ -2361,6 +2684,7 @@ static void init_proc_405 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_4xx_softmmu(env);
/* Allocate hardware IRQ controller */
ppc405_irq_init(env);
}
......@@ -2402,6 +2726,7 @@ static void init_proc_440EP (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_BookE(env);
/* XXX: TODO: allocate internal IRQ controller */
}
......@@ -2426,6 +2751,7 @@ static void init_proc_440GP (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_BookE(env);
/* XXX: TODO: allocate internal IRQ controller */
}
......@@ -2451,6 +2777,7 @@ static void init_proc_440x4 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_BookE(env);
/* XXX: TODO: allocate internal IRQ controller */
}
#endif /* TODO */
......@@ -2492,6 +2819,7 @@ static void init_proc_440x5 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_BookE(env);
/* XXX: TODO: allocate internal IRQ controller */
}
......@@ -2509,6 +2837,36 @@ static void init_proc_440x5 (CPUPPCState *env)
static void init_proc_460 (CPUPPCState *env)
{
/* Time base */
gen_tbl(env);
gen_spr_BookE(env);
gen_spr_440(env);
spr_register(env, SPR_BOOKE_MCSR, "MCSR",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
spr_register(env, SPR_BOOKE_MCSRR0, "MCSRR0",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
spr_register(env, SPR_BOOKE_MCSRR1, "MCSRR1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
spr_register(env, SPR_440_CCR1, "CCR1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
spr_register(env, SPR_DCRIPR, "SPR_DCRIPR",
&spr_read_generic, &spr_write_generic,
&spr_read_generic, &spr_write_generic,
0x00000000);
/* Memory management */
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_BookE(env);
/* XXX: TODO: allocate internal IRQ controller */
}
#endif /* TODO */
......@@ -2527,7 +2885,7 @@ static void init_proc_460 (CPUPPCState *env)
#define POWERPC_INPUT_460F (PPC_FLAGS_INPUT_BookE)
#define POWERPC_BFDM_460F (bfd_mach_ppc_403)
static void init_proc_460 (CPUPPCState *env)
static void init_proc_460F (CPUPPCState *env)
{
/* Time base */
gen_tbl(env);
......@@ -2557,6 +2915,7 @@ static void init_proc_460 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_BookE(env);
/* XXX: TODO: allocate internal IRQ controller */
}
#endif /* TODO */
......@@ -2578,6 +2937,7 @@ static void init_proc_460 (CPUPPCState *env)
static void init_proc_BookE (CPUPPCState *env)
{
init_excp_BookE(env);
}
#endif /* TODO */
......@@ -2610,6 +2970,7 @@ static void init_proc_e500 (CPUPPCState *env)
env->nb_tlb = 64;
env->nb_ways = 1;
env->id_tlbs = 0;
init_excp_BookE(env);
/* XXX: TODO: allocate internal IRQ controller */
}
#endif /* TODO */
......@@ -2678,6 +3039,7 @@ static void init_proc_601 (CPUPPCState *env)
env->nb_ways = 2;
env->id_tlbs = 0;
env->id_tlbs = 0;
init_excp_601(env);
/* XXX: TODO: allocate internal IRQ controller */
}
......@@ -2712,6 +3074,7 @@ static void init_proc_602 (CPUPPCState *env)
/* Memory management */
gen_low_BATs(env);
gen_6xx_7xx_soft_tlb(env, 64, 2);
init_excp_602(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -2744,6 +3107,7 @@ static void init_proc_603 (CPUPPCState *env)
/* Memory management */
gen_low_BATs(env);
gen_6xx_7xx_soft_tlb(env, 64, 2);
init_excp_603(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -2781,6 +3145,7 @@ static void init_proc_603E (CPUPPCState *env)
/* Memory management */
gen_low_BATs(env);
gen_6xx_7xx_soft_tlb(env, 64, 2);
init_excp_603(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -2820,6 +3185,7 @@ static void init_proc_G2 (CPUPPCState *env)
gen_low_BATs(env);
gen_high_BATs(env);
gen_6xx_7xx_soft_tlb(env, 64, 2);
init_excp_G2(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -2859,6 +3225,7 @@ static void init_proc_G2LE (CPUPPCState *env)
gen_low_BATs(env);
gen_high_BATs(env);
gen_6xx_7xx_soft_tlb(env, 64, 2);
init_excp_G2(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -2890,6 +3257,7 @@ static void init_proc_604 (CPUPPCState *env)
0x00000000);
/* Memory management */
gen_low_BATs(env);
init_excp_604(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -2923,6 +3291,7 @@ static void init_proc_7x0 (CPUPPCState *env)
0x00000000);
/* Memory management */
gen_low_BATs(env);
init_excp_7x0(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -2963,6 +3332,7 @@ static void init_proc_750fx (CPUPPCState *env)
gen_low_BATs(env);
/* PowerPC 750fx & 750gx has 8 DBATs and 8 IBATs */
gen_high_BATs(env);
init_excp_750FX(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -3038,6 +3408,7 @@ static void init_proc_7400 (CPUPPCState *env)
gen_spr_thrm(env);
/* Memory management */
gen_low_BATs(env);
init_excp_7400(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -3076,6 +3447,7 @@ static void init_proc_7410 (CPUPPCState *env)
0x00000000);
/* Memory management */
gen_low_BATs(env);
init_excp_7400(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -3201,6 +3573,7 @@ static void init_proc_7450 (CPUPPCState *env)
/* Memory management */
gen_low_BATs(env);
gen_74xx_soft_tlb(env);
init_excp_7450(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -3297,6 +3670,7 @@ static void init_proc_7445 (CPUPPCState *env)
gen_low_BATs(env);
gen_high_BATs(env);
gen_74xx_soft_tlb(env);
init_excp_7450(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -3395,6 +3769,7 @@ static void init_proc_7455 (CPUPPCState *env)
gen_low_BATs(env);
gen_high_BATs(env);
gen_74xx_soft_tlb(env);
init_excp_7450(env);
/* Allocate hardware IRQ controller */
ppc6xx_irq_init(env);
}
......@@ -3439,6 +3814,7 @@ static void init_proc_970 (CPUPPCState *env)
#if 0 // TODO
env->slb_nr = 32;
#endif
init_excp_970(env);
/* Allocate hardware IRQ controller */
ppc970_irq_init(env);
}
......@@ -3481,6 +3857,7 @@ static void init_proc_970FX (CPUPPCState *env)
#if 0 // TODO
env->slb_nr = 32;
#endif
init_excp_970(env);
/* Allocate hardware IRQ controller */
ppc970_irq_init(env);
}
......@@ -3523,6 +3900,7 @@ static void init_proc_970GX (CPUPPCState *env)
#if 0 // TODO
env->slb_nr = 32;
#endif
init_excp_970(env);
/* Allocate hardware IRQ controller */
ppc970_irq_init(env);
}
......@@ -3552,6 +3930,7 @@ static void init_proc_620 (CPUPPCState *env)
/* Memory management */
gen_low_BATs(env);
gen_high_BATs(env);
init_excp_620(env);
/* XXX: TODO: initialize internal interrupt controller */
}
#endif /* TODO */
......@@ -5046,7 +5425,15 @@ static ppc_def_t ppc_defs[] = {
static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
{
#if !defined(CONFIG_USER_ONLY)
int i;
env->irq_inputs = NULL;
/* Set all exception vectors to an invalid address */
for (i = 0; i < POWERPC_EXCP_NB; i++)
env->excp_vectors[i] = (target_ulong)(-1ULL);
env->excp_prefix = 0x00000000;
env->ivor_mask = 0x00000000;
env->ivpr_mask = 0x00000000;
#endif
/* Default MMU definitions */
env->nb_BATs = 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册