aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWANG Rui <wangrui@loongson.cn>2025-04-14 15:49:52 +0800
committerSong Gao <gaosong@loongson.cn>2025-04-24 10:46:09 +0800
commita9d3d1dff6f9e1544e8a84e74645b8e4fe08c0ad (patch)
tree766501cbd7a94e1cd8f0235132e62cd17d917745
parent0d4c2e408d418ec5c412ec9f58e7b8f3aecc6948 (diff)
downloadqemu-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.c25
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;