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>
This commit is contained in:
WANG Rui 2025-04-14 15:49:52 +08:00 committed by Song Gao
parent 0d4c2e408d
commit a9d3d1dff6

View file

@ -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;