mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-29 05:13:54 -06:00
target-s390: Reorg exception handling
Make the user path more like the system path. Prepare for more kinds of runtime exceptions. Rename ILC to ILEN to make it clear that we want to pass around a full instruction length, rather than a "code" that happens to be stored one bit left in a larger field. Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
3fde06f5fb
commit
d5a103cd6e
7 changed files with 242 additions and 261 deletions
|
@ -2933,71 +2933,115 @@ void cpu_loop(CPUAlphaState *env)
|
|||
#ifdef TARGET_S390X
|
||||
void cpu_loop(CPUS390XState *env)
|
||||
{
|
||||
int trapnr;
|
||||
int trapnr, n, sig;
|
||||
target_siginfo_t info;
|
||||
target_ulong addr;
|
||||
|
||||
while (1) {
|
||||
trapnr = cpu_s390x_exec (env);
|
||||
|
||||
trapnr = cpu_s390x_exec(env);
|
||||
switch (trapnr) {
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
/* Just indicate that signals should be handled asap. */
|
||||
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(env, info.si_signo, &info);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EXCP_SVC:
|
||||
{
|
||||
int n = env->int_svc_code;
|
||||
if (!n) {
|
||||
/* syscalls > 255 */
|
||||
n = env->regs[1];
|
||||
}
|
||||
env->psw.addr += env->int_svc_ilc;
|
||||
env->regs[2] = do_syscall(env, n,
|
||||
env->regs[2],
|
||||
env->regs[3],
|
||||
env->regs[4],
|
||||
env->regs[5],
|
||||
env->regs[6],
|
||||
env->regs[7],
|
||||
0, 0);
|
||||
n = env->int_svc_code;
|
||||
if (!n) {
|
||||
/* syscalls > 255 */
|
||||
n = env->regs[1];
|
||||
}
|
||||
env->psw.addr += env->int_svc_ilen;
|
||||
env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
|
||||
env->regs[4], env->regs[5],
|
||||
env->regs[6], env->regs[7], 0, 0);
|
||||
break;
|
||||
|
||||
case EXCP_DEBUG:
|
||||
sig = gdb_handlesig(env, TARGET_SIGTRAP);
|
||||
if (sig) {
|
||||
n = TARGET_TRAP_BRKPT;
|
||||
goto do_signal_pc;
|
||||
}
|
||||
break;
|
||||
case EXCP_ADDR:
|
||||
{
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
case EXCP_PGM:
|
||||
n = env->int_pgm_code;
|
||||
switch (n) {
|
||||
case PGM_OPERATION:
|
||||
case PGM_PRIVILEGED:
|
||||
sig = SIGILL;
|
||||
n = TARGET_ILL_ILLOPC;
|
||||
goto do_signal_pc;
|
||||
case PGM_PROTECTION:
|
||||
case PGM_ADDRESSING:
|
||||
sig = SIGSEGV;
|
||||
/* XXX: check env->error_code */
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
info._sifields._sigfault._addr = env->__excp_addr;
|
||||
queue_signal(env, info.si_signo, &info);
|
||||
n = TARGET_SEGV_MAPERR;
|
||||
addr = env->__excp_addr;
|
||||
goto do_signal;
|
||||
case PGM_EXECUTE:
|
||||
case PGM_SPECIFICATION:
|
||||
case PGM_SPECIAL_OP:
|
||||
case PGM_OPERAND:
|
||||
do_sigill_opn:
|
||||
sig = SIGILL;
|
||||
n = TARGET_ILL_ILLOPN;
|
||||
goto do_signal_pc;
|
||||
|
||||
case PGM_FIXPT_OVERFLOW:
|
||||
sig = SIGFPE;
|
||||
n = TARGET_FPE_INTOVF;
|
||||
goto do_signal_pc;
|
||||
case PGM_FIXPT_DIVIDE:
|
||||
sig = SIGFPE;
|
||||
n = TARGET_FPE_INTDIV;
|
||||
goto do_signal_pc;
|
||||
|
||||
case PGM_DATA:
|
||||
n = (env->fpc >> 8) & 0xff;
|
||||
if (n == 0xff) {
|
||||
/* compare-and-trap */
|
||||
goto do_sigill_opn;
|
||||
} else {
|
||||
/* An IEEE exception, simulated or otherwise. */
|
||||
if (n & 0x80) {
|
||||
n = TARGET_FPE_FLTINV;
|
||||
} else if (n & 0x40) {
|
||||
n = TARGET_FPE_FLTDIV;
|
||||
} else if (n & 0x20) {
|
||||
n = TARGET_FPE_FLTOVF;
|
||||
} else if (n & 0x10) {
|
||||
n = TARGET_FPE_FLTUND;
|
||||
} else if (n & 0x08) {
|
||||
n = TARGET_FPE_FLTRES;
|
||||
} else {
|
||||
/* ??? Quantum exception; BFP, DFP error. */
|
||||
goto do_sigill_opn;
|
||||
}
|
||||
sig = SIGFPE;
|
||||
goto do_signal_pc;
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unhandled program exception: %#x\n", n);
|
||||
cpu_dump_state(env, stderr, fprintf, 0);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case EXCP_SPEC:
|
||||
{
|
||||
fprintf(stderr,"specification exception insn 0x%08x%04x\n", ldl(env->psw.addr), lduw(env->psw.addr + 4));
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TARGET_ILL_ILLOPC;
|
||||
info._sifields._sigfault._addr = env->__excp_addr;
|
||||
queue_signal(env, info.si_signo, &info);
|
||||
}
|
||||
|
||||
do_signal_pc:
|
||||
addr = env->psw.addr;
|
||||
do_signal:
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = n;
|
||||
info._sifields._sigfault._addr = addr;
|
||||
queue_signal(env, info.si_signo, &info);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("Unhandled trap: 0x%x\n", trapnr);
|
||||
fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr);
|
||||
cpu_dump_state(env, stderr, fprintf, 0);
|
||||
exit (1);
|
||||
exit(1);
|
||||
}
|
||||
process_pending_signals (env);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue