aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorBlue Swirl <blauwirbel@gmail.com>2013-01-12 12:46:57 +0000
committerBlue Swirl <blauwirbel@gmail.com>2013-01-12 12:46:57 +0000
commit837d1f978224f7e7b020c71ffb10b291952cc596 (patch)
treef1e4e0b95ad756a48976b6d6889b41e44552454a /linux-user
parenta6fc23e5dc76660792c8363d058adf22caa82945 (diff)
parent2b35e93fbfc52c2be6cf85e5a54a3707cdabd914 (diff)
Merge branch 's390-reorg' of git://repo.or.cz/qemu/rth
* 's390-reorg' of git://repo.or.cz/qemu/rth: (149 commits) target-s390: Claim maintainership target-s390: Use noreturn for exception and load_psw target-s390: Use TCG_CALL_NO_WG for misc helpers target-s390: Use TCG_CALL_NO_WG for integer helpers target-s390: Use TCG_CALL_NO_WG for floating-point helpers target-s390: Use TCG_CALL_NO_WG for memory helpers target-s390: Perform COMPARE AND SWAP inline target-s390: Optimize get_address target-s390: Optimize ADDC/SUBB target-s390: Optimize ADDU/SUBU CC testing target-s390: Tidy comparisons target-s390: Optmize emitting discards target-s390: Optimize XC target-s390: Fix cpu_clone_regs target-s390: Implement LOAD/SET FP AND SIGNAL target-s390: Implement SET ROUNDING MODE target-s390: Use uint64_to_float128 target-s390: Implement LCDFR target-s390: Check insn operand specifications target-s390: Implement CPSDR ...
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/main.c140
-rw-r--r--linux-user/s390x/syscall.h2
2 files changed, 93 insertions, 49 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 9ade1bfabd..0181bc2112 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2938,71 +2938,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);
- }
+ case EXCP_SVC:
+ 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_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);
+
+ 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);
}
diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h
index c2ea151ea5..e4603b79c3 100644
--- a/linux-user/s390x/syscall.h
+++ b/linux-user/s390x/syscall.h
@@ -16,7 +16,7 @@ struct target_pt_regs {
target_psw_t psw;
abi_ulong gprs[TARGET_NUM_GPRS];
abi_ulong orig_gpr2;
- unsigned short ilc;
+ unsigned short ilen;
unsigned short trap;
};