From: Frank Chang <frank.ch...@sifive.com> * Add fp16 nan-box check generator function, if a 16-bit input is not properly nanboxed, then the input is replaced with the default qnan. * Add do_nanbox() helper function to utilize gen_check_nanbox_X() to generate the NaN-boxed floating-point values based on SEW setting. * Apply nanbox helper in opfvf_trans
Signed-off-by: Frank Chang <frank.ch...@sifive.com> --- target/riscv/insn_trans/trans_rvv.inc.c | 35 ++++++++++++++++++++++++- target/riscv/translate.c | 10 +++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/target/riscv/insn_trans/trans_rvv.inc.c b/target/riscv/insn_trans/trans_rvv.inc.c index daaa47ac9c3..4b8ae5470c3 100644 --- a/target/riscv/insn_trans/trans_rvv.inc.c +++ b/target/riscv/insn_trans/trans_rvv.inc.c @@ -2076,6 +2076,33 @@ GEN_OPIVI_NARROW_TRANS(vnclip_vi, IMM_ZX, vnclip_vx) /* *** Vector Float Point Arithmetic Instructions */ + +/* + * As RVF-only cpus always have values NaN-boxed to 64-bits, + * RVF and RVD can be treated equally. + * We don't have to deal with the cases of: SEW > FLEN. + * + * If SEW < FLEN, check whether input fp register is a valid + * NaN-boxed value, in which case the least-significant SEW bits + * of the f regsiter are used, else the canonical NaN value is used. + */ +static void do_nanbox(DisasContext *s, TCGv_i64 out, TCGv_i64 in) +{ + switch (s->sew) { + case 1: + gen_check_nanbox_h(out, in); + break; + case 2: + gen_check_nanbox_s(out, in); + break; + case 3: + tcg_gen_mov_i64(out, in); + break; + default: + g_assert_not_reached(); + } +} + /* Vector Single-Width Floating-Point Add/Subtract Instructions */ /* @@ -2128,6 +2155,7 @@ static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, { TCGv_ptr dest, src2, mask; TCGv_i32 desc; + TCGv_i64 t1; TCGLabel *over = gen_new_label(); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); @@ -2141,12 +2169,17 @@ static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2)); tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0)); - fn(dest, mask, cpu_fpr[rs1], src2, cpu_env, desc); + /* NaN-box f[rs1] */ + t1 = tcg_temp_new_i64(); + do_nanbox(s, t1, cpu_fpr[rs1]); + + fn(dest, mask, t1, src2, cpu_env, desc); tcg_temp_free_ptr(dest); tcg_temp_free_ptr(mask); tcg_temp_free_ptr(src2); tcg_temp_free_i32(desc); + tcg_temp_free_i64(t1); mark_vs_dirty(s); gen_set_label(over); return true; diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 10ef55bbeb7..0b3f5f1b4ba 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -121,6 +121,16 @@ static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in) * * Here, the result is always nan-boxed, even the canonical nan. */ +static void gen_check_nanbox_h(TCGv_i64 out, TCGv_i64 in) +{ + TCGv_i64 t_max = tcg_const_i64(0xffffffffffff0000ull); + TCGv_i64 t_nan = tcg_const_i64(0xffffffffffff7e00ull); + + tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan); + tcg_temp_free_i64(t_max); + tcg_temp_free_i64(t_nan); +} + static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in) { TCGv_i64 t_max = tcg_const_i64(0xffffffff00000000ull); -- 2.17.1