]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
linux-user/loongarch64: Decode BRK break codes for FPE signals
authorWANG Rui <wangrui@loongson.cn>
Mon, 14 Apr 2025 07:49:52 +0000 (15:49 +0800)
committerSong Gao <gaosong@loongson.cn>
Thu, 24 Apr 2025 02:46:09 +0000 (10:46 +0800)
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>
linux-user/loongarch64/cpu_loop.c

index 0614d3de224e53914809adad02d172cc68fb5e7b..ec8a06c88c79e2871162585ecd909cabaec8c32e 100644 (file)
 #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;