diff options
author | WANG Rui <wangrui@loongson.cn> | 2025-04-14 15:49:52 +0800 |
---|---|---|
committer | Song Gao <gaosong@loongson.cn> | 2025-04-24 10:46:09 +0800 |
commit | a9d3d1dff6f9e1544e8a84e74645b8e4fe08c0ad (patch) | |
tree | 766501cbd7a94e1cd8f0235132e62cd17d917745 | |
parent | 0d4c2e408d418ec5c412ec9f58e7b8f3aecc6948 (diff) | |
download | qemu-a9d3d1dff6f9e1544e8a84e74645b8e4fe08c0ad.zip qemu-a9d3d1dff6f9e1544e8a84e74645b8e4fe08c0ad.tar.gz qemu-a9d3d1dff6f9e1544e8a84e74645b8e4fe08c0ad.tar.bz2 |
linux-user/loongarch64: Decode BRK break codes for FPE signals
Handle specific LoongArch BRK break codes in user-mode emulation
to deliver accurate floating-point exception signals. Specifically,
BRK_OVERFLOW (6) triggers TARGET_FPE_INTOVF, and BRK_DIVZERO (7)
triggers TARGET_FPE_INTDIV. Other BRK codes fall back to a generic
SIGTRAP.
This improves correctness for programs that rely on BRK to signal
overflow or divide-by-zero conditions.
Signed-off-by: WANG Rui <wangrui@loongson.cn>
Acked-by: Song Gao <gaosong@loongson.cn>
Message-Id: <20250414074952.6253-1-wangrui@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
-rw-r--r-- | linux-user/loongarch64/cpu_loop.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c index 0614d3d..ec8a06c 100644 --- a/linux-user/loongarch64/cpu_loop.c +++ b/linux-user/loongarch64/cpu_loop.c @@ -11,6 +11,12 @@ #include "user/cpu_loop.h" #include "signal-common.h" +/* Break codes */ +enum { + BRK_OVERFLOW = 6, + BRK_DIVZERO = 7 +}; + void cpu_loop(CPULoongArchState *env) { CPUState *cs = env_cpu(env); @@ -66,9 +72,26 @@ void cpu_loop(CPULoongArchState *env) force_sig_fault(TARGET_SIGFPE, si_code, env->pc); break; case EXCP_DEBUG: - case EXCCODE_BRK: force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; + case EXCCODE_BRK: + { + unsigned int opcode; + + get_user_u32(opcode, env->pc); + + switch (opcode & 0x7fff) { + case BRK_OVERFLOW: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->pc); + break; + case BRK_DIVZERO: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc); + break; + default: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); + } + } + break; case EXCCODE_BCE: force_sig_fault(TARGET_SIGSYS, TARGET_SI_KERNEL, env->pc); break; |