diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2021-05-18 16:17:22 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2021-05-18 16:17:22 +0100 |
| commit | c313e52e6459de2e9064767083a0c949c476e32b (patch) | |
| tree | 9bf8c4a6927fe0c714c06c5e4967e0501a1ca335 /linux-user/arm/cpu_loop.c | |
| parent | 15e147b3c778f9f4c08c79b99747b848b6e2117b (diff) | |
| parent | 4a1e8931eca05077afd0b7ed092ab0f10c5b457e (diff) | |
| download | focaccia-qemu-c313e52e6459de2e9064767083a0c949c476e32b.tar.gz focaccia-qemu-c313e52e6459de2e9064767083a0c949c476e32b.zip | |
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-6.1-pull-request' into staging
linux-user pull request 20210517 - alpha sigaction fixes/cleanups - s390x sigaction fixes/cleanup - sparc sigaction fixes/cleanup - s390x core dumping support - core dump fix (app name) - arm fpa11 fix and cleanup - strace fixes (unshare(), llseek()) - fix copy_file_range() - use GDateTime - Remove dead code # gpg: Signature made Tue 18 May 2021 06:31:12 BST # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-6.1-pull-request: (59 commits) linux-user/elfload: add s390x core dumping support linux-user/elfload: fix filling psinfo->pr_psargs linux-user: Tidy TARGET_NR_rt_sigaction linux-user/alpha: Share code for TARGET_NR_sigaction linux-user/alpha: Define TARGET_ARCH_HAS_KA_RESTORER linux-user: Honor TARGET_ARCH_HAS_SA_RESTORER in do_syscall linux-user: Pass ka_restorer to do_sigaction linux-user/alpha: Rename the sigaction restorer field linux-user/alpha: Fix rt sigframe return linux-user: use GDateTime for formatting timestamp for core file linux-user: Fix erroneous conversion in copy_file_range linux-user: Add copy_file_range to strace.list linux-user/s390x: Handle vector regs in signal stack linux-user/s390x: Clean up signal.c linux-user/s390x: Add build asserts for sigset sizes linux-user/s390x: Fix frame_addr corruption in setup_frame linux-user/s390x: Add stub sigframe argument for last_break linux-user/s390x: Set psw.mask properly for the signal handler linux-user/s390x: Clean up single-use gotos in signal.c linux-user/s390x: Tidy save_sigregs ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/arm/cpu_loop.c')
| -rw-r--r-- | linux-user/arm/cpu_loop.c | 125 |
1 files changed, 66 insertions, 59 deletions
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index 989d03cd89..69632d15be 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -224,6 +224,64 @@ static bool insn_is_linux_bkpt(uint32_t opcode, bool is_thumb) } } +static bool emulate_arm_fpa11(CPUARMState *env, uint32_t opcode) +{ + TaskState *ts = env_cpu(env)->opaque; + int rc = EmulateAll(opcode, &ts->fpa, env); + int raise, enabled; + + if (rc == 0) { + /* Illegal instruction */ + return false; + } + if (rc > 0) { + /* Everything ok. */ + env->regs[15] += 4; + return true; + } + + /* FP exception */ + rc = -rc; + raise = 0; + + /* Translate softfloat flags to FPSR flags */ + if (rc & float_flag_invalid) { + raise |= BIT_IOC; + } + if (rc & float_flag_divbyzero) { + raise |= BIT_DZC; + } + if (rc & float_flag_overflow) { + raise |= BIT_OFC; + } + if (rc & float_flag_underflow) { + raise |= BIT_UFC; + } + if (rc & float_flag_inexact) { + raise |= BIT_IXC; + } + + /* Accumulate unenabled exceptions */ + enabled = ts->fpa.fpsr >> 16; + ts->fpa.fpsr |= raise & ~enabled; + + if (raise & enabled) { + target_siginfo_t info = { }; + + /* + * The kernel's nwfpe emulator does not pass a real si_code. + * It merely uses send_sig(SIGFPE, current, 1). + */ + info.si_signo = TARGET_SIGFPE; + info.si_code = TARGET_SI_KERNEL; + + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + } else { + env->regs[15] += 4; + } + return true; +} + void cpu_loop(CPUARMState *env) { CPUState *cs = env_cpu(env); @@ -244,9 +302,7 @@ void cpu_loop(CPUARMState *env) case EXCP_NOCP: case EXCP_INVSTATE: { - TaskState *ts = cs->opaque; uint32_t opcode; - int rc; /* we handle the FPU emulation here, as Linux */ /* we get the opcode */ @@ -263,64 +319,15 @@ void cpu_loop(CPUARMState *env) goto excp_debug; } - rc = EmulateAll(opcode, &ts->fpa, env); - if (rc == 0) { /* illegal instruction */ - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPN; - info._sifields._sigfault._addr = env->regs[15]; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - } else if (rc < 0) { /* FP exception */ - int arm_fpe=0; - - /* translate softfloat flags to FPSR flags */ - if (-rc & float_flag_invalid) - arm_fpe |= BIT_IOC; - if (-rc & float_flag_divbyzero) - arm_fpe |= BIT_DZC; - if (-rc & float_flag_overflow) - arm_fpe |= BIT_OFC; - if (-rc & float_flag_underflow) - arm_fpe |= BIT_UFC; - if (-rc & float_flag_inexact) - arm_fpe |= BIT_IXC; - - FPSR fpsr = ts->fpa.fpsr; - //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe); - - if (fpsr & (arm_fpe << 16)) { /* exception enabled? */ - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - - /* ordered by priority, least first */ - if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES; - if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND; - if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF; - if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV; - if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; - - info._sifields._sigfault._addr = env->regs[15]; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - } else { - env->regs[15] += 4; - } - - /* accumulate unenabled exceptions */ - if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) - fpsr |= BIT_IXC; - if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) - fpsr |= BIT_UFC; - if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) - fpsr |= BIT_OFC; - if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) - fpsr |= BIT_DZC; - if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) - fpsr |= BIT_IOC; - ts->fpa.fpsr=fpsr; - } else { /* everything OK */ - /* increment PC */ - env->regs[15] += 4; + if (!env->thumb && emulate_arm_fpa11(env, opcode)) { + break; } + + info.si_signo = TARGET_SIGILL; + info.si_errno = 0; + info.si_code = TARGET_ILL_ILLOPN; + info._sifields._sigfault._addr = env->regs[15]; + queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); } break; case EXCP_SWI: |