Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/cpu/riscv_fpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ static slow_path void riscv_emulate_f_opc_op_impl(rvvm_hart_t* vm, const uint32_
const uint32_t rm = bit_ext_u32(insn, 12, 3);
const size_t rs1 = bit_ext_u32(insn, 15, 5);
const size_t rs2 = bit_ext_u32(insn, 20, 5);
const uint32_t eff_rm = rm == RM_DYN ? bit_cut(vm->csr.fcsr, 5, 3) : rm;

if (likely(riscv_fpu_is_enabled(vm))) {

Expand Down Expand Up @@ -184,8 +185,8 @@ static slow_path void riscv_emulate_f_opc_op_impl(rvvm_hart_t* vm, const uint32_
riscv_write_s(vm, rds, fpu_fcvt_f64_to_f32(riscv_view_d(vm, rs1)));
return;
case 0x04: // fround.s (Zfa)
case 0x05: // TODO: froundx.s (Zfa)
riscv_emit_s(vm, rds, fpu_fcvt_i64_to_f32(fpu_round_f32_to_i64(riscv_read_s(vm, rs1), rm)));
case 0x05: // froundnx.s (Zfa)
riscv_emit_s(vm, rds, fpu_round_to_integral32(riscv_read_s(vm, rs1), eff_rm, rs2 == 0x05));
return;
}
break;
Expand All @@ -195,8 +196,8 @@ static slow_path void riscv_emulate_f_opc_op_impl(rvvm_hart_t* vm, const uint32_
riscv_write_d(vm, rds, fpu_fcvt_f32_to_f64(riscv_read_s(vm, rs1)));
return;
case 0x04: // fround.s (Zfa)
case 0x05: // TODO: froundx.s (Zfa)
riscv_emit_d(vm, rds, fpu_fcvt_i64_to_f64(fpu_round_f64_to_i64(riscv_view_d(vm, rs1), rm)));
case 0x05: // froundnx.d (Zfa)
riscv_emit_d(vm, rds, fpu_round_to_integral64(riscv_view_d(vm, rs1), eff_rm, rs2 == 0x05));
return;
}
break;
Expand Down
30 changes: 30 additions & 0 deletions src/util/fpu_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1753,6 +1753,36 @@ static forceinline int64_t fpu_round_f64_to_i64(fpu_f64_t d, uint32_t mode)
return ret;
}

static forceinline fpu_f32_t fpu_round_to_integral32(fpu_f32_t f, uint32_t mode, bool set_inexact)
{
if (fpu_is_nan32_soft(f)) {
if (fpu_is_snan32_soft(f)) {
fpu_raise_invalid();
}
return fpu_bit_u32_to_f32(FPU_LIB_FP32_CANONICAL_NAN);
}
fpu_f32_t ret = fpu_round_f32_internal(f, mode);
if (set_inexact && !fpu_is_bit_equal32(f, ret)) {
fpu_raise_inexact();
}
return ret;
}

static forceinline fpu_f64_t fpu_round_to_integral64(fpu_f64_t d, uint32_t mode, bool set_inexact)
{
if (fpu_is_nan64_soft(d)) {
if (fpu_is_snan64_soft(d)) {
fpu_raise_invalid();
}
return fpu_bit_u64_to_f64(FPU_LIB_FP64_CANONICAL_NAN);
}
fpu_f64_t ret = fpu_round_f64_internal(d, mode);
if (set_inexact && !fpu_is_bit_equal64(d, ret)) {
fpu_raise_inexact();
}
return ret;
}

/*
* IEEE 754 Signaling Comparisons
*
Expand Down
Loading