@@ -76,8 +76,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
void cpu_loop(CPUPPCState *env)
{
CPUState *cs = env_cpu(env);
- target_siginfo_t info;
- int trapnr;
+ int trapnr, si_signo, si_code;
target_ulong ret;
for(;;) {
@@ -102,61 +101,10 @@ void cpu_loop(CPUPPCState *env)
"Aborting\n");
break;
case POWERPC_EXCP_DSI: /* Data storage exception */
- /* XXX: check this. Seems bugged */
- switch (env->error_code & 0xFF000000) {
- case 0x40000000:
- case 0x42000000:
- 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->spr[SPR_DAR];
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_ISI: /* Instruction storage exception */
- /* 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(env, info.si_signo, QEMU_SI_FAULT, &info);
+ /* FIXME: handle maperr in ppc_cpu_record_sigsegv. */
+ force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR,
+ env->spr[SPR_DAR]);
break;
case POWERPC_EXCP_EXTERNAL: /* External input */
cpu_abort(cs, "External interrupt while in user mode. "
@@ -167,24 +115,23 @@ void cpu_loop(CPUPPCState *env)
/* XXX: check this */
switch (env->error_code & ~0xF) {
case POWERPC_EXCP_FP:
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
+ si_signo = TARGET_SIGFPE;
switch (env->error_code & 0xF) {
case POWERPC_EXCP_FP_OX:
- info.si_code = TARGET_FPE_FLTOVF;
+ si_code = TARGET_FPE_FLTOVF;
break;
case POWERPC_EXCP_FP_UX:
- info.si_code = TARGET_FPE_FLTUND;
+ si_code = TARGET_FPE_FLTUND;
break;
case POWERPC_EXCP_FP_ZX:
case POWERPC_EXCP_FP_VXZDZ:
- info.si_code = TARGET_FPE_FLTDIV;
+ si_code = TARGET_FPE_FLTDIV;
break;
case POWERPC_EXCP_FP_XX:
- info.si_code = TARGET_FPE_FLTRES;
+ si_code = TARGET_FPE_FLTRES;
break;
case POWERPC_EXCP_FP_VXSOFT:
- info.si_code = TARGET_FPE_FLTINV;
+ si_code = TARGET_FPE_FLTINV;
break;
case POWERPC_EXCP_FP_VXSNAN:
case POWERPC_EXCP_FP_VXISI:
@@ -193,51 +140,50 @@ void cpu_loop(CPUPPCState *env)
case POWERPC_EXCP_FP_VXVC:
case POWERPC_EXCP_FP_VXSQRT:
case POWERPC_EXCP_FP_VXCVI:
- info.si_code = TARGET_FPE_FLTSUB;
+ si_code = TARGET_FPE_FLTSUB;
break;
default:
EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
env->error_code);
+ si_code = 0;
break;
}
break;
case POWERPC_EXCP_INVAL:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
+ si_signo = TARGET_SIGILL;
switch (env->error_code & 0xF) {
case POWERPC_EXCP_INVAL_INVAL:
- info.si_code = TARGET_ILL_ILLOPC;
+ si_code = TARGET_ILL_ILLOPC;
break;
case POWERPC_EXCP_INVAL_LSWX:
- info.si_code = TARGET_ILL_ILLOPN;
+ si_code = TARGET_ILL_ILLOPN;
break;
case POWERPC_EXCP_INVAL_SPR:
- info.si_code = TARGET_ILL_PRVREG;
+ si_code = TARGET_ILL_PRVREG;
break;
case POWERPC_EXCP_INVAL_FP:
- info.si_code = TARGET_ILL_COPROC;
+ 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;
+ si_code = TARGET_ILL_ILLADR;
break;
}
break;
case POWERPC_EXCP_PRIV:
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
+ si_signo = TARGET_SIGILL;
switch (env->error_code & 0xF) {
case POWERPC_EXCP_PRIV_OPC:
- info.si_code = TARGET_ILL_PRVOPC;
+ si_code = TARGET_ILL_PRVOPC;
break;
case POWERPC_EXCP_PRIV_REG:
- info.si_code = TARGET_ILL_PRVREG;
+ 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;
+ si_code = TARGET_ILL_PRVOPC;
break;
}
break;
@@ -250,28 +196,19 @@ void cpu_loop(CPUPPCState *env)
env->error_code);
break;
}
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(si_signo, si_code, env->nip);
break;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
+ case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
+ case POWERPC_EXCP_VPU: /* Vector unavailable exception */
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->nip);
break;
case POWERPC_EXCP_SYSCALL: /* System call exception */
case POWERPC_EXCP_SYSCALL_VECTORED:
cpu_abort(cs, "Syscall exception while in user mode. "
"Aborting\n");
break;
- case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_DECR: /* Decrementer exception */
cpu_abort(cs, "Decrementer interrupt while in user mode. "
"Aborting\n");
@@ -292,13 +229,6 @@ void cpu_loop(CPUPPCState *env)
cpu_abort(cs, "Instruction TLB exception while in user mode. "
"Aborting\n");
break;
- case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
cpu_abort(cs, "Embedded floating-point data IRQ not handled\n");
break;
@@ -355,13 +285,6 @@ void cpu_loop(CPUPPCState *env)
cpu_abort(cs, "Hypervisor instruction segment exception "
"while in user mode. Aborting\n");
break;
- case POWERPC_EXCP_VPU: /* Vector unavailable exception */
- info.si_signo = TARGET_SIGILL;
- info.si_errno = 0;
- info.si_code = TARGET_ILL_COPROC;
- info._sifields._sigfault._addr = env->nip;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
- break;
case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
cpu_abort(cs, "Programmable interval timer interrupt "
"while in user mode. Aborting\n");
@@ -444,10 +367,7 @@ void cpu_loop(CPUPPCState *env)
env->gpr[3] = ret;
break;
case EXCP_DEBUG:
- info.si_signo = TARGET_SIGTRAP;
- info.si_errno = 0;
- info.si_code = TARGET_TRAP_BRKPT;
- queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->nip);
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */