mirror of https://gitee.com/openkylin/qemu.git
target-mips: Translate breaks and traps into the appropriate signal
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 <meadori@codesourcery.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
20c334a797
commit
54b2f42cb1
|
@ -2186,6 +2186,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)
|
||||
{
|
||||
CPUState *cs = CPU(mips_env_get_cpu(env));
|
||||
|
@ -2302,8 +2329,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);
|
||||
|
|
Loading…
Reference in New Issue