On Thu, Jan 10, 2013 at 04:50:22PM -0600, Meador Inge wrote: > GCC and GAS are capable of generating traps or breaks to check for > division by zero. Additionally, GAS is capable of generating traps > or breaks to check for overflow on certain division and multiplication > operations. The Linux kernel translates these traps and breaks into > signals. This patch implements the corresponding feature in QEMU. > > Signed-off-by: Meador Inge <mead...@codesourcery.com> > --- > Changes since v1: > > * Moved the BRK_* enumerations from target-mips/cpu.h to > linux-user/main.c since they are only used in main.c > > * Fixed some style violations found by checkpatch.pl. > > * Removed a superfluous break. > > linux-user/main.c | 76 > ++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 75 insertions(+), 1 deletion(-) > > diff --git a/linux-user/main.c b/linux-user/main.c > index 9ade1bf..583940c 100644 > --- a/linux-user/main.c > +++ b/linux-user/main.c > @@ -2182,6 +2182,33 @@ static int do_store_exclusive(CPUMIPSState *env) > return segv; > } > > +/* Break codes */ > +enum { > + BRK_OVERFLOW = 6, > + BRK_DIVZERO = 7 > +}; > + > +static int do_break(CPUMIPSState *env, target_siginfo_t *info, > + unsigned int code) > +{ > + int ret = -1; > + > + switch (code) { > + case BRK_OVERFLOW: > + case BRK_DIVZERO: > + info->si_signo = TARGET_SIGFPE; > + info->si_errno = 0; > + info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; > + queue_signal(env, info->si_signo, &*info); > + ret = 0; > + break; > + default: > + break; > + } > + > + return ret; > +} > + > void cpu_loop(CPUMIPSState *env) > { > target_siginfo_t info; > @@ -2297,8 +2324,55 @@ done_syscall: > info.si_code = TARGET_ILL_ILLOPC; > queue_signal(env, info.si_signo, &info); > break; > + /* The code below was inspired by the MIPS Linux kernel trap > + * handling code in arch/mips/kernel/traps.c. > + */ > + case EXCP_BREAK: > + { > + abi_ulong trap_instr; > + unsigned int code; > + > + ret = get_user_ual(trap_instr, env->active_tc.PC); > + if (ret != 0) { > + goto error; > + } > + > + /* As described in the original Linux kernel code, the > + * below checks on 'code' are to work around an old > + * assembly bug. > + */ > + code = ((trap_instr >> 6) & ((1 << 20) - 1)); > + if (code >= (1 << 10)) { > + code >>= 10; > + } > + > + if (do_break(env, &info, code) != 0) { > + goto error; > + } > + } > + break; > + case EXCP_TRAP: > + { > + abi_ulong trap_instr; > + unsigned int code = 0; > + > + ret = get_user_ual(trap_instr, env->active_tc.PC); > + if (ret != 0) { > + goto error; > + } > + > + /* The immediate versions don't provide a code. */ > + if (!(trap_instr & 0xFC000000)) { > + code = ((trap_instr >> 6) & ((1 << 10) - 1)); > + } > + > + if (do_break(env, &info, code) != 0) { > + goto error; > + } > + } > + break; > default: > - // error: > +error: > fprintf(stderr, "qemu: unhandled CPU exception 0x%x - > aborting\n", > trapnr); > cpu_dump_state(env, stderr, fprintf, 0);
Thanks, applied, and sorry for the delay. -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurel...@aurel32.net http://www.aurel32.net