From eaf98149ed6bcb800e361b07efc1a77481d9bf19 Mon Sep 17 00:00:00 2001 From: wangyang Date: Sat, 5 Sep 2026 18:59:50 +0800 Subject: [PATCH] fpu: implement Zfa minimum-number-or-NaN operations --- src/cpu/riscv_fpu.c | 8 ++++---- src/util/fpu_lib.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/cpu/riscv_fpu.c b/src/cpu/riscv_fpu.c index aa2daa341..b8e9b155e 100644 --- a/src/cpu/riscv_fpu.c +++ b/src/cpu/riscv_fpu.c @@ -324,10 +324,10 @@ static slow_path void riscv_emulate_f_opc_op_impl(rvvm_hart_t* vm, const uint32_ riscv_emit_s(vm, rds, fpu_max32(riscv_read_s(vm, rs1), riscv_read_s(vm, rs2))); return; case 0x28002000UL: // fminm.s (Zfa) - riscv_write_s(vm, rds, fpu_min32(riscv_read_s(vm, rs1), riscv_read_s(vm, rs2))); + riscv_write_s(vm, rds, fpu_minm32(riscv_read_s(vm, rs1), riscv_read_s(vm, rs2))); return; case 0x28003000UL: // fmaxm.s (Zfa) - riscv_write_s(vm, rds, fpu_max32(riscv_read_s(vm, rs1), riscv_read_s(vm, rs2))); + riscv_write_s(vm, rds, fpu_maxm32(riscv_read_s(vm, rs1), riscv_read_s(vm, rs2))); return; case 0x2A000000UL: // fmin.d riscv_emit_d(vm, rds, fpu_min64(riscv_view_d(vm, rs1), riscv_view_d(vm, rs2))); @@ -336,10 +336,10 @@ static slow_path void riscv_emulate_f_opc_op_impl(rvvm_hart_t* vm, const uint32_ riscv_emit_d(vm, rds, fpu_max64(riscv_view_d(vm, rs1), riscv_view_d(vm, rs2))); return; case 0x2A002000UL: // fminm.d (Zfa) - riscv_write_d(vm, rds, fpu_min64(riscv_view_d(vm, rs1), riscv_view_d(vm, rs2))); + riscv_write_d(vm, rds, fpu_minm64(riscv_view_d(vm, rs1), riscv_view_d(vm, rs2))); return; case 0x2A003000UL: // fmaxm.d (Zfa) - riscv_write_d(vm, rds, fpu_max64(riscv_view_d(vm, rs1), riscv_view_d(vm, rs2))); + riscv_write_d(vm, rds, fpu_maxm64(riscv_view_d(vm, rs1), riscv_view_d(vm, rs2))); return; case 0xA0000000UL: // fle.s riscv_write_reg(vm, rds, fpu_is_fle32_sig(riscv_read_s(vm, rs1), riscv_read_s(vm, rs2))); diff --git a/src/util/fpu_lib.h b/src/util/fpu_lib.h index 6541da22a..c3dd7e7da 100644 --- a/src/util/fpu_lib.h +++ b/src/util/fpu_lib.h @@ -2001,4 +2001,48 @@ static forceinline fpu_f64_t fpu_max64(fpu_f64_t a, fpu_f64_t b) #endif } +static forceinline fpu_f32_t fpu_minm32(fpu_f32_t a, fpu_f32_t b) +{ + if (fpu_is_nan32_soft(a) || fpu_is_nan32_soft(b)) { + if (fpu_is_snan32_soft(a) || fpu_is_snan32_soft(b)) { + fpu_raise_invalid(); + } + return fpu_bit_u32_to_f32(FPU_LIB_FP32_CANONICAL_NAN); + } + return fpu_min32(a, b); +} + +static forceinline fpu_f32_t fpu_maxm32(fpu_f32_t a, fpu_f32_t b) +{ + if (fpu_is_nan32_soft(a) || fpu_is_nan32_soft(b)) { + if (fpu_is_snan32_soft(a) || fpu_is_snan32_soft(b)) { + fpu_raise_invalid(); + } + return fpu_bit_u32_to_f32(FPU_LIB_FP32_CANONICAL_NAN); + } + return fpu_max32(a, b); +} + +static forceinline fpu_f64_t fpu_minm64(fpu_f64_t a, fpu_f64_t b) +{ + if (fpu_is_nan64_soft(a) || fpu_is_nan64_soft(b)) { + if (fpu_is_snan64_soft(a) || fpu_is_snan64_soft(b)) { + fpu_raise_invalid(); + } + return fpu_bit_u64_to_f64(FPU_LIB_FP64_CANONICAL_NAN); + } + return fpu_min64(a, b); +} + +static forceinline fpu_f64_t fpu_maxm64(fpu_f64_t a, fpu_f64_t b) +{ + if (fpu_is_nan64_soft(a) || fpu_is_nan64_soft(b)) { + if (fpu_is_snan64_soft(a) || fpu_is_snan64_soft(b)) { + fpu_raise_invalid(); + } + return fpu_bit_u64_to_f64(FPU_LIB_FP64_CANONICAL_NAN); + } + return fpu_max64(a, b); +} + #endif