mirror of https://github.com/xemu-project/xemu.git
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
This commit is contained in:
parent
f93732914e
commit
e1833e1f96
|
@ -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,16 +183,336 @@ 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:
|
||||
case POWERPC_EXCP_CRITICAL: /* Critical input */
|
||||
cpu_abort(env, "Critical interrupt while in user mode. "
|
||||
"Aborting\n");
|
||||
break;
|
||||
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
|
||||
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 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 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 POWERPC_EXCP_PROGRAM: /* Program exception */
|
||||
/* XXX: check this */
|
||||
switch (env->error_code & ~0xF) {
|
||||
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;
|
||||
default:
|
||||
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 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 POWERPC_EXCP_SYSCALL: /* System call exception */
|
||||
cpu_abort(env, "Syscall exception while in user mode. "
|
||||
"Aborting\n");
|
||||
break;
|
||||
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 POWERPC_EXCP_DECR: /* Decrementer exception */
|
||||
cpu_abort(env, "Decrementer interrupt while in user mode. "
|
||||
"Aborting\n");
|
||||
break;
|
||||
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 */
|
||||
gdb_handlesig (env, SIGTRAP);
|
||||
break;
|
||||
#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],
|
||||
|
@ -209,235 +539,9 @@ void cpu_loop(CPUPPCState *env)
|
|||
/* Return value */
|
||||
env->gpr[3] = ret;
|
||||
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:
|
||||
#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]);
|
||||
}
|
||||
/* 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");
|
||||
/* 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;
|
||||
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:
|
||||
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);
|
||||
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();
|
||||
}
|
||||
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;
|
||||
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);
|
||||
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();
|
||||
}
|
||||
break;
|
||||
case EXCP_BRANCH:
|
||||
/* We stopped because of a jump... */
|
||||
break;
|
||||
case EXCP_INTERRUPT:
|
||||
/* Don't know why this should ever happen... */
|
||||
fprintf(stderr, "EXCP_INTERRUPT\n");
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
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);
|
||||
}
|
||||
abort();
|
||||
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,17 +741,385 @@ 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 */
|
||||
case POWERPC_EXCP_CRITICAL: /* Critical input */
|
||||
cpu_abort(env, "Critical interrupt while in user mode. "
|
||||
"Aborting\n");
|
||||
break;
|
||||
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;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
case 0x04000000:
|
||||
info.si_signo = TARGET_SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_ILL_ILLADR;
|
||||
break;
|
||||
case 0x08000000:
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_SEGV_ACCERR;
|
||||
break;
|
||||
default:
|
||||
/* Let's send a regular segfault... */
|
||||
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;
|
||||
break;
|
||||
}
|
||||
info._sifields._sigfault._addr = env->nip;
|
||||
queue_signal(info.si_signo, &info);
|
||||
break;
|
||||
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;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
case 0x10000000:
|
||||
case 0x08000000:
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_SEGV_ACCERR;
|
||||
break;
|
||||
default:
|
||||
/* Let's send a regular segfault... */
|
||||
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;
|
||||
break;
|
||||
}
|
||||
info._sifields._sigfault._addr = env->nip - 4;
|
||||
queue_signal(info.si_signo, &info);
|
||||
break;
|
||||
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 POWERPC_EXCP_PROGRAM: /* Program exception */
|
||||
/* XXX: check this */
|
||||
switch (env->error_code & ~0xF) {
|
||||
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 = TARGET_SIGFPE;
|
||||
info.si_errno = 0;
|
||||
switch (env->error_code & 0xF) {
|
||||
case POWERPC_EXCP_FP_OX:
|
||||
info.si_code = TARGET_FPE_FLTOVF;
|
||||
break;
|
||||
case POWERPC_EXCP_FP_UX:
|
||||
info.si_code = TARGET_FPE_FLTUND;
|
||||
break;
|
||||
case POWERPC_EXCP_FP_ZX:
|
||||
case POWERPC_EXCP_FP_VXZDZ:
|
||||
info.si_code = TARGET_FPE_FLTDIV;
|
||||
break;
|
||||
case POWERPC_EXCP_FP_XX:
|
||||
info.si_code = TARGET_FPE_FLTRES;
|
||||
break;
|
||||
case POWERPC_EXCP_FP_VXSOFT:
|
||||
info.si_code = TARGET_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 = TARGET_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 = TARGET_SIGILL;
|
||||
info.si_errno = 0;
|
||||
switch (env->error_code & 0xF) {
|
||||
case POWERPC_EXCP_INVAL_INVAL:
|
||||
info.si_code = TARGET_ILL_ILLOPC;
|
||||
break;
|
||||
case POWERPC_EXCP_INVAL_LSWX:
|
||||
info.si_code = TARGET_ILL_ILLOPN;
|
||||
break;
|
||||
case POWERPC_EXCP_INVAL_SPR:
|
||||
info.si_code = TARGET_ILL_PRVREG;
|
||||
break;
|
||||
case POWERPC_EXCP_INVAL_FP:
|
||||
info.si_code = TARGET_ILL_COPROC;
|
||||
break;
|
||||
default:
|
||||
EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
|
||||
env->error_code & 0xF);
|
||||
info.si_code = TARGET_ILL_ILLADR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
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 POWERPC_EXCP_PRIV_OPC:
|
||||
info.si_code = TARGET_ILL_PRVOPC;
|
||||
break;
|
||||
case POWERPC_EXCP_PRIV_REG:
|
||||
info.si_code = TARGET_ILL_PRVREG;
|
||||
break;
|
||||
default:
|
||||
EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
|
||||
env->error_code & 0xF);
|
||||
info.si_code = TARGET_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._sifields._sigfault._addr = env->nip - 4;
|
||||
queue_signal(info.si_signo, &info);
|
||||
break;
|
||||
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 POWERPC_EXCP_SYSCALL: /* System call exception */
|
||||
cpu_abort(env, "Syscall exception while in user mode. "
|
||||
"Aborting\n");
|
||||
break;
|
||||
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 POWERPC_EXCP_DECR: /* Decrementer exception */
|
||||
cpu_abort(env, "Decrementer interrupt while in user mode. "
|
||||
"Aborting\n");
|
||||
break;
|
||||
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) {
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_TRAP_BRKPT;
|
||||
queue_signal(info.si_signo, &info);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#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.
|
||||
|
@ -763,287 +1141,9 @@ void cpu_loop(CPUPPCState *env)
|
|||
printf("syscall returned 0x%08x (%d)\n", ret, ret);
|
||||
#endif
|
||||
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]);
|
||||
}
|
||||
switch (env->error_code & 0xFF000000) {
|
||||
case 0x40000000:
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
case 0x04000000:
|
||||
info.si_signo = TARGET_SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_ILL_ILLADR;
|
||||
break;
|
||||
case 0x08000000:
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_SEGV_ACCERR;
|
||||
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);
|
||||
}
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
}
|
||||
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");
|
||||
switch (env->error_code & 0xFF000000) {
|
||||
case 0x40000000:
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
case 0x10000000:
|
||||
case 0x08000000:
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_SEGV_ACCERR;
|
||||
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);
|
||||
}
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
}
|
||||
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");
|
||||
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:
|
||||
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 = TARGET_SIGFPE;
|
||||
info.si_errno = 0;
|
||||
switch (env->error_code & 0xF) {
|
||||
case EXCP_FP_OX:
|
||||
info.si_code = TARGET_FPE_FLTOVF;
|
||||
break;
|
||||
case EXCP_FP_UX:
|
||||
info.si_code = TARGET_FPE_FLTUND;
|
||||
break;
|
||||
case EXCP_FP_ZX:
|
||||
case EXCP_FP_VXZDZ:
|
||||
info.si_code = TARGET_FPE_FLTDIV;
|
||||
break;
|
||||
case EXCP_FP_XX:
|
||||
info.si_code = TARGET_FPE_FLTRES;
|
||||
break;
|
||||
case 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:
|
||||
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);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EXCP_INVAL:
|
||||
fprintf(stderr, "Invalid instruction\n");
|
||||
if (loglevel)
|
||||
fprintf(logfile, "Invalid instruction\n");
|
||||
info.si_signo = TARGET_SIGILL;
|
||||
info.si_errno = 0;
|
||||
switch (env->error_code & 0xF) {
|
||||
case EXCP_INVAL_INVAL:
|
||||
info.si_code = TARGET_ILL_ILLOPC;
|
||||
break;
|
||||
case EXCP_INVAL_LSWX:
|
||||
info.si_code = TARGET_ILL_ILLOPN;
|
||||
break;
|
||||
case EXCP_INVAL_SPR:
|
||||
info.si_code = TARGET_ILL_PRVREG;
|
||||
break;
|
||||
case 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);
|
||||
}
|
||||
info.si_code = TARGET_ILL_ILLADR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EXCP_PRIV:
|
||||
fprintf(stderr, "Privilege violation\n");
|
||||
if (loglevel)
|
||||
fprintf(logfile, "Privilege violation\n");
|
||||
info.si_signo = TARGET_SIGILL;
|
||||
info.si_errno = 0;
|
||||
switch (env->error_code & 0xF) {
|
||||
case EXCP_PRIV_OPC:
|
||||
info.si_code = TARGET_ILL_PRVOPC;
|
||||
break;
|
||||
case EXCP_PRIV_REG:
|
||||
info.si_code = TARGET_ILL_PRVREG;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "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();
|
||||
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();
|
||||
}
|
||||
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");
|
||||
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();
|
||||
}
|
||||
break;
|
||||
case EXCP_BRANCH:
|
||||
/* We stopped because of a jump... */
|
||||
break;
|
||||
case EXCP_INTERRUPT:
|
||||
/* Don't know why this should ever happen... */
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
{
|
||||
int sig;
|
||||
|
||||
sig = gdb_handlesig (env, TARGET_SIGTRAP);
|
||||
if (sig)
|
||||
{
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_TRAP_BRKPT;
|
||||
queue_signal(info.si_signo, &info);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
abort();
|
||||
cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
|
||||
break;
|
||||
}
|
||||
process_pending_signals(env);
|
||||
}
|
||||
|
|
268
target-ppc/cpu.h
268
target-ppc/cpu.h
|
@ -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 */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
1015
target-ppc/helper.c
1015
target-ppc/helper.c
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
||||
}
|
||||
|
||||
|
@ -2507,26 +2835,6 @@ static void init_proc_440x5 (CPUPPCState *env)
|
|||
#define POWERPC_INPUT_460 (PPC_FLAGS_INPUT_BookE)
|
||||
#define POWERPC_BFDM_460 (bfd_mach_ppc_403)
|
||||
|
||||
static void init_proc_460 (CPUPPCState *env)
|
||||
{
|
||||
}
|
||||
#endif /* TODO */
|
||||
|
||||
/* PowerPC 460F (guessed) */
|
||||
#if defined(TODO)
|
||||
#define POWERPC_INSNS_460F (POWERPC_INSNS_EMB | \
|
||||
PPC_CACHE_DCBA | PPC_MEM_TLBSYNC | \
|
||||
PPC_FLOAT | PPC_FLOAT_FSQRT | PPC_FLOAT_FRES | \
|
||||
PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL | \
|
||||
PPC_FLOAT_STFIWX | \
|
||||
PPC_BOOKE | PPC_BOOKE_EXT | PPC_4xx_COMMON | \
|
||||
PPC_405_MAC | PPC_440_SPEC | PPC_DCRUX)
|
||||
#define POWERPC_MSRM_460 (0x000000000006FF30ULL)
|
||||
#define POWERPC_MMU_460F (POWERPC_MMU_BOOKE)
|
||||
#define POWERPC_EXCP_460F (POWERPC_EXCP_BOOKE)
|
||||
#define POWERPC_INPUT_460F (PPC_FLAGS_INPUT_BookE)
|
||||
#define POWERPC_BFDM_460F (bfd_mach_ppc_403)
|
||||
|
||||
static void init_proc_460 (CPUPPCState *env)
|
||||
{
|
||||
/* Time base */
|
||||
|
@ -2557,6 +2865,57 @@ 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 */
|
||||
|
||||
/* PowerPC 460F (guessed) */
|
||||
#if defined(TODO)
|
||||
#define POWERPC_INSNS_460F (POWERPC_INSNS_EMB | \
|
||||
PPC_CACHE_DCBA | PPC_MEM_TLBSYNC | \
|
||||
PPC_FLOAT | PPC_FLOAT_FSQRT | PPC_FLOAT_FRES | \
|
||||
PPC_FLOAT_FRSQRTE | PPC_FLOAT_FSEL | \
|
||||
PPC_FLOAT_STFIWX | \
|
||||
PPC_BOOKE | PPC_BOOKE_EXT | PPC_4xx_COMMON | \
|
||||
PPC_405_MAC | PPC_440_SPEC | PPC_DCRUX)
|
||||
#define POWERPC_MSRM_460 (0x000000000006FF30ULL)
|
||||
#define POWERPC_MMU_460F (POWERPC_MMU_BOOKE)
|
||||
#define POWERPC_EXCP_460F (POWERPC_EXCP_BOOKE)
|
||||
#define POWERPC_INPUT_460F (PPC_FLAGS_INPUT_BookE)
|
||||
#define POWERPC_BFDM_460F (bfd_mach_ppc_403)
|
||||
|
||||
static void init_proc_460F (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 */
|
||||
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue