Message ID | 20200724002807.441147-5-richard.henderson@linaro.org |
---|---|
State | New |
Headers | show |
Series | target/riscv: NaN-boxing for multiple precison | expand |
On 2020/7/24 8:28, Richard Henderson wrote: > If a 32-bit input is not properly nanboxed, then the input is > replaced with the default qnan. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > target/riscv/internals.h | 11 +++++++ > target/riscv/fpu_helper.c | 64 ++++++++++++++++++++++++++++----------- > 2 files changed, 57 insertions(+), 18 deletions(-) > > diff --git a/target/riscv/internals.h b/target/riscv/internals.h > index 9f4ba7d617..f1a546dba6 100644 > --- a/target/riscv/internals.h > +++ b/target/riscv/internals.h > @@ -43,4 +43,15 @@ static inline uint64_t nanbox_s(float32 f) > return f | MAKE_64BIT_MASK(32, 32); > } > > +static inline float32 check_nanbox_s(uint64_t f) > +{ > + uint64_t mask = MAKE_64BIT_MASK(32, 32); > + > + if (likely((f & mask) == mask)) { > + return (uint32_t)f; > + } else { > + return 0x7fc00000u; /* default qnan */ > + } > +} > + If possible, +static inline float32 check_nanbox(uint64_t f, uint32_t flen) +{ + uint64_t mask = MAKE_64BIT_MASK(flen, 64 - flen); + + if (likely((f & mask) == mask)) { + return (uint32_t)f; + } else { + return (flen == 32) ? 0x7fc00000u : 0x7e00u; /* default qnan */ + } +} + Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com> Zhiwei > #endif > diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c > index 72541958a7..bb346a8249 100644 > --- a/target/riscv/fpu_helper.c > +++ b/target/riscv/fpu_helper.c > @@ -81,9 +81,12 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm) > set_float_rounding_mode(softrm, &env->fp_status); > } > > -static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, > - uint64_t frs3, int flags) > +static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2, > + uint64_t rs3, int flags) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > + float32 frs3 = check_nanbox_s(rs3); > return nanbox_s(float32_muladd(frs1, frs2, frs3, flags, &env->fp_status)); > } > > @@ -139,74 +142,97 @@ uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, > float_muladd_negate_product, &env->fp_status); > } > > -uint64_t helper_fadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_add(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_sub(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fmul_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_mul(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_div(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_minnum(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fmax_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_maxnum(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t frs1) > +uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return nanbox_s(float32_sqrt(frs1, &env->fp_status)); > } > > -target_ulong helper_fle_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +target_ulong helper_fle_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return float32_le(frs1, frs2, &env->fp_status); > } > > -target_ulong helper_flt_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +target_ulong helper_flt_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return float32_lt(frs1, frs2, &env->fp_status); > } > > -target_ulong helper_feq_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return float32_eq_quiet(frs1, frs2, &env->fp_status); > } > > -target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t frs1) > +target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return float32_to_int32(frs1, &env->fp_status); > } > > -target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t frs1) > +target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return (int32_t)float32_to_uint32(frs1, &env->fp_status); > } > > #if defined(TARGET_RISCV64) > -uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t frs1) > +uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return float32_to_int64(frs1, &env->fp_status); > } > > -uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t frs1) > +uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return float32_to_uint64(frs1, &env->fp_status); > } > #endif > @@ -233,8 +259,9 @@ uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t rs1) > } > #endif > > -target_ulong helper_fclass_s(uint64_t frs1) > +target_ulong helper_fclass_s(uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return fclass_s(frs1); > } > > @@ -275,7 +302,8 @@ uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1) > > uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1) > { > - return float32_to_float64(rs1, &env->fp_status); > + float32 frs1 = check_nanbox_s(rs1); > + return float32_to_float64(frs1, &env->fp_status); > } > > uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)
On 7/23/20 7:47 PM, LIU Zhiwei wrote: > > > On 2020/7/24 8:28, Richard Henderson wrote: >> If a 32-bit input is not properly nanboxed, then the input is >> replaced with the default qnan. >> >> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> >> --- >> target/riscv/internals.h | 11 +++++++ >> target/riscv/fpu_helper.c | 64 ++++++++++++++++++++++++++++----------- >> 2 files changed, 57 insertions(+), 18 deletions(-) >> >> diff --git a/target/riscv/internals.h b/target/riscv/internals.h >> index 9f4ba7d617..f1a546dba6 100644 >> --- a/target/riscv/internals.h >> +++ b/target/riscv/internals.h >> @@ -43,4 +43,15 @@ static inline uint64_t nanbox_s(float32 f) >> return f | MAKE_64BIT_MASK(32, 32); >> } >> +static inline float32 check_nanbox_s(uint64_t f) >> +{ >> + uint64_t mask = MAKE_64BIT_MASK(32, 32); >> + >> + if (likely((f & mask) == mask)) { >> + return (uint32_t)f; >> + } else { >> + return 0x7fc00000u; /* default qnan */ >> + } >> +} >> + > If possible, > > +static inline float32 check_nanbox(uint64_t f, uint32_t flen) > +{ > + uint64_t mask = MAKE_64BIT_MASK(flen, 64 - flen); > + > + if (likely((f & mask) == mask)) { > + return (uint32_t)f; > + } else { > + return (flen == 32) ? 0x7fc00000u : 0x7e00u; /* default qnan */ > + } > +} The difficulty of choosing the proper default qnan is an example of why we should *not* attempt to make this function fully general, but should instead define separate functions for each type. E.g. static inline float16 check_nanbox_h(uint64_t f); static inline bfloat16 check_nanbox_b(uint64_t f); r~
On Fri, Jul 24, 2020 at 8:29 AM Richard Henderson < richard.henderson@linaro.org> wrote: > If a 32-bit input is not properly nanboxed, then the input is > replaced with the default qnan. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > target/riscv/internals.h | 11 +++++++ > target/riscv/fpu_helper.c | 64 ++++++++++++++++++++++++++++----------- > 2 files changed, 57 insertions(+), 18 deletions(-) > > diff --git a/target/riscv/internals.h b/target/riscv/internals.h > index 9f4ba7d617..f1a546dba6 100644 > --- a/target/riscv/internals.h > +++ b/target/riscv/internals.h > @@ -43,4 +43,15 @@ static inline uint64_t nanbox_s(float32 f) > return f | MAKE_64BIT_MASK(32, 32); > } > > +static inline float32 check_nanbox_s(uint64_t f) > +{ > + uint64_t mask = MAKE_64BIT_MASK(32, 32); > + > + if (likely((f & mask) == mask)) { > + return (uint32_t)f; > + } else { > + return 0x7fc00000u; /* default qnan */ > + } > +} > + > #endif > diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c > index 72541958a7..bb346a8249 100644 > --- a/target/riscv/fpu_helper.c > +++ b/target/riscv/fpu_helper.c > @@ -81,9 +81,12 @@ void helper_set_rounding_mode(CPURISCVState *env, > uint32_t rm) > set_float_rounding_mode(softrm, &env->fp_status); > } > > -static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t > frs2, > - uint64_t frs3, int flags) > +static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2, > + uint64_t rs3, int flags) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > + float32 frs3 = check_nanbox_s(rs3); > return nanbox_s(float32_muladd(frs1, frs2, frs3, flags, > &env->fp_status)); > } > > @@ -139,74 +142,97 @@ uint64_t helper_fnmadd_d(CPURISCVState *env, > uint64_t frs1, uint64_t frs2, > float_muladd_negate_product, &env->fp_status); > } > > -uint64_t helper_fadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_add(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_sub(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fmul_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_mul(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_div(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_minnum(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fmax_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) > +uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return nanbox_s(float32_maxnum(frs1, frs2, &env->fp_status)); > } > > -uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t frs1) > +uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return nanbox_s(float32_sqrt(frs1, &env->fp_status)); > } > > -target_ulong helper_fle_s(CPURISCVState *env, uint64_t frs1, uint64_t > frs2) > +target_ulong helper_fle_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return float32_le(frs1, frs2, &env->fp_status); > } > > -target_ulong helper_flt_s(CPURISCVState *env, uint64_t frs1, uint64_t > frs2) > +target_ulong helper_flt_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return float32_lt(frs1, frs2, &env->fp_status); > } > > -target_ulong helper_feq_s(CPURISCVState *env, uint64_t frs1, uint64_t > frs2) > +target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) > { > + float32 frs1 = check_nanbox_s(rs1); > + float32 frs2 = check_nanbox_s(rs2); > return float32_eq_quiet(frs1, frs2, &env->fp_status); > } > > -target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t frs1) > +target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return float32_to_int32(frs1, &env->fp_status); > } > > -target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t frs1) > +target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return (int32_t)float32_to_uint32(frs1, &env->fp_status); > } > > #if defined(TARGET_RISCV64) > -uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t frs1) > +uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return float32_to_int64(frs1, &env->fp_status); > } > > -uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t frs1) > +uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return float32_to_uint64(frs1, &env->fp_status); > } > #endif > @@ -233,8 +259,9 @@ uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t > rs1) > } > #endif > > -target_ulong helper_fclass_s(uint64_t frs1) > +target_ulong helper_fclass_s(uint64_t rs1) > { > + float32 frs1 = check_nanbox_s(rs1); > return fclass_s(frs1); > } > > @@ -275,7 +302,8 @@ uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t > rs1) > > uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1) > { > - return float32_to_float64(rs1, &env->fp_status); > + float32 frs1 = check_nanbox_s(rs1); > + return float32_to_float64(frs1, &env->fp_status); > } > > uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1) > -- > 2.25.1 > > > Reviewed-by: Chih-Min Chao <chihmin.chao@sifive.com> Chih-Min Chao <div dir="ltr"><div dir="ltr"><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">On Fri, Jul 24, 2020 at 8:29 AM Richard Henderson <<a href="mailto:richard.henderson@linaro.org">richard.henderson@linaro.org</a>> wrote:<br></div></div></div></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">If a 32-bit input is not properly nanboxed, then the input is<br> replaced with the default qnan.<br> <br> Signed-off-by: Richard Henderson <<a href="mailto:richard.henderson@linaro.org" target="_blank">richard.henderson@linaro.org</a>><br> ---<br> target/riscv/internals.h | 11 +++++++<br> target/riscv/fpu_helper.c | 64 ++++++++++++++++++++++++++++-----------<br> 2 files changed, 57 insertions(+), 18 deletions(-)<br> <br> diff --git a/target/riscv/internals.h b/target/riscv/internals.h<br> index 9f4ba7d617..f1a546dba6 100644<br> --- a/target/riscv/internals.h<br> +++ b/target/riscv/internals.h<br> @@ -43,4 +43,15 @@ static inline uint64_t nanbox_s(float32 f)<br> return f | MAKE_64BIT_MASK(32, 32);<br> }<br> <br> +static inline float32 check_nanbox_s(uint64_t f)<br> +{<br> + uint64_t mask = MAKE_64BIT_MASK(32, 32);<br> +<br> + if (likely((f & mask) == mask)) {<br> + return (uint32_t)f;<br> + } else {<br> + return 0x7fc00000u; /* default qnan */<br> + }<br> +}<br> +<br> #endif<br> diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c<br> index 72541958a7..bb346a8249 100644<br> --- a/target/riscv/fpu_helper.c<br> +++ b/target/riscv/fpu_helper.c<br> @@ -81,9 +81,12 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)<br> set_float_rounding_mode(softrm, &env->fp_status);<br> }<br> <br> -static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,<br> - uint64_t frs3, int flags)<br> +static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2,<br> + uint64_t rs3, int flags)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> + float32 frs2 = check_nanbox_s(rs2);<br> + float32 frs3 = check_nanbox_s(rs3);<br> return nanbox_s(float32_muladd(frs1, frs2, frs3, flags, &env->fp_status));<br> }<br> <br> @@ -139,74 +142,97 @@ uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,<br> float_muladd_negate_product, &env->fp_status);<br> }<br> <br> -uint64_t helper_fadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)<br> +uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> + float32 frs2 = check_nanbox_s(rs2);<br> return nanbox_s(float32_add(frs1, frs2, &env->fp_status));<br> }<br> <br> -uint64_t helper_fsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)<br> +uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> + float32 frs2 = check_nanbox_s(rs2);<br> return nanbox_s(float32_sub(frs1, frs2, &env->fp_status));<br> }<br> <br> -uint64_t helper_fmul_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)<br> +uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> + float32 frs2 = check_nanbox_s(rs2);<br> return nanbox_s(float32_mul(frs1, frs2, &env->fp_status));<br> }<br> <br> -uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)<br> +uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> + float32 frs2 = check_nanbox_s(rs2);<br> return nanbox_s(float32_div(frs1, frs2, &env->fp_status));<br> }<br> <br> -uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)<br> +uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> + float32 frs2 = check_nanbox_s(rs2);<br> return nanbox_s(float32_minnum(frs1, frs2, &env->fp_status));<br> }<br> <br> -uint64_t helper_fmax_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)<br> +uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> + float32 frs2 = check_nanbox_s(rs2);<br> return nanbox_s(float32_maxnum(frs1, frs2, &env->fp_status));<br> }<br> <br> -uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t frs1)<br> +uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> return nanbox_s(float32_sqrt(frs1, &env->fp_status));<br> }<br> <br> -target_ulong helper_fle_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)<br> +target_ulong helper_fle_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> + float32 frs2 = check_nanbox_s(rs2);<br> return float32_le(frs1, frs2, &env->fp_status);<br> }<br> <br> -target_ulong helper_flt_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)<br> +target_ulong helper_flt_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> + float32 frs2 = check_nanbox_s(rs2);<br> return float32_lt(frs1, frs2, &env->fp_status);<br> }<br> <br> -target_ulong helper_feq_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)<br> +target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> + float32 frs2 = check_nanbox_s(rs2);<br> return float32_eq_quiet(frs1, frs2, &env->fp_status);<br> }<br> <br> -target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t frs1)<br> +target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> return float32_to_int32(frs1, &env->fp_status);<br> }<br> <br> -target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t frs1)<br> +target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> return (int32_t)float32_to_uint32(frs1, &env->fp_status);<br> }<br> <br> #if defined(TARGET_RISCV64)<br> -uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t frs1)<br> +uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> return float32_to_int64(frs1, &env->fp_status);<br> }<br> <br> -uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t frs1)<br> +uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> return float32_to_uint64(frs1, &env->fp_status);<br> }<br> #endif<br> @@ -233,8 +259,9 @@ uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t rs1)<br> }<br> #endif<br> <br> -target_ulong helper_fclass_s(uint64_t frs1)<br> +target_ulong helper_fclass_s(uint64_t rs1)<br> {<br> + float32 frs1 = check_nanbox_s(rs1);<br> return fclass_s(frs1);<br> }<br> <br> @@ -275,7 +302,8 @@ uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)<br> <br> uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1)<br> {<br> - return float32_to_float64(rs1, &env->fp_status);<br> + float32 frs1 = check_nanbox_s(rs1);<br> + return float32_to_float64(frs1, &env->fp_status);<br> }<br> <br> uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)<br> -- <br> 2.25.1<br> <br> <br></blockquote><div><br></div><div>Reviewed-by: Chih-Min Chao <<a href="mailto:chihmin.chao@sifive.com">chihmin.chao@sifive.com</a>></div><div><br></div><div><div dir="ltr" class="gmail_signature"><div dir="ltr"><span style="color:rgb(136,136,136)">Chih-Min Chao</span><div style="color:rgb(136,136,136)"></div></div></div></div><div> </div></div></div>
diff --git a/target/riscv/internals.h b/target/riscv/internals.h index 9f4ba7d617..f1a546dba6 100644 --- a/target/riscv/internals.h +++ b/target/riscv/internals.h @@ -43,4 +43,15 @@ static inline uint64_t nanbox_s(float32 f) return f | MAKE_64BIT_MASK(32, 32); } +static inline float32 check_nanbox_s(uint64_t f) +{ + uint64_t mask = MAKE_64BIT_MASK(32, 32); + + if (likely((f & mask) == mask)) { + return (uint32_t)f; + } else { + return 0x7fc00000u; /* default qnan */ + } +} + #endif diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c index 72541958a7..bb346a8249 100644 --- a/target/riscv/fpu_helper.c +++ b/target/riscv/fpu_helper.c @@ -81,9 +81,12 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm) set_float_rounding_mode(softrm, &env->fp_status); } -static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, - uint64_t frs3, int flags) +static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2, + uint64_t rs3, int flags) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); + float32 frs3 = check_nanbox_s(rs3); return nanbox_s(float32_muladd(frs1, frs2, frs3, flags, &env->fp_status)); } @@ -139,74 +142,97 @@ uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, float_muladd_negate_product, &env->fp_status); } -uint64_t helper_fadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return nanbox_s(float32_add(frs1, frs2, &env->fp_status)); } -uint64_t helper_fsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return nanbox_s(float32_sub(frs1, frs2, &env->fp_status)); } -uint64_t helper_fmul_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return nanbox_s(float32_mul(frs1, frs2, &env->fp_status)); } -uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return nanbox_s(float32_div(frs1, frs2, &env->fp_status)); } -uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return nanbox_s(float32_minnum(frs1, frs2, &env->fp_status)); } -uint64_t helper_fmax_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return nanbox_s(float32_maxnum(frs1, frs2, &env->fp_status)); } -uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t frs1) +uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1) { + float32 frs1 = check_nanbox_s(rs1); return nanbox_s(float32_sqrt(frs1, &env->fp_status)); } -target_ulong helper_fle_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +target_ulong helper_fle_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return float32_le(frs1, frs2, &env->fp_status); } -target_ulong helper_flt_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +target_ulong helper_flt_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return float32_lt(frs1, frs2, &env->fp_status); } -target_ulong helper_feq_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2) +target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) { + float32 frs1 = check_nanbox_s(rs1); + float32 frs2 = check_nanbox_s(rs2); return float32_eq_quiet(frs1, frs2, &env->fp_status); } -target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t frs1) +target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1) { + float32 frs1 = check_nanbox_s(rs1); return float32_to_int32(frs1, &env->fp_status); } -target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t frs1) +target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1) { + float32 frs1 = check_nanbox_s(rs1); return (int32_t)float32_to_uint32(frs1, &env->fp_status); } #if defined(TARGET_RISCV64) -uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t frs1) +uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1) { + float32 frs1 = check_nanbox_s(rs1); return float32_to_int64(frs1, &env->fp_status); } -uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t frs1) +uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1) { + float32 frs1 = check_nanbox_s(rs1); return float32_to_uint64(frs1, &env->fp_status); } #endif @@ -233,8 +259,9 @@ uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t rs1) } #endif -target_ulong helper_fclass_s(uint64_t frs1) +target_ulong helper_fclass_s(uint64_t rs1) { + float32 frs1 = check_nanbox_s(rs1); return fclass_s(frs1); } @@ -275,7 +302,8 @@ uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1) uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1) { - return float32_to_float64(rs1, &env->fp_status); + float32 frs1 = check_nanbox_s(rs1); + return float32_to_float64(frs1, &env->fp_status); } uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)
If a 32-bit input is not properly nanboxed, then the input is replaced with the default qnan. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/riscv/internals.h | 11 +++++++ target/riscv/fpu_helper.c | 64 ++++++++++++++++++++++++++++----------- 2 files changed, 57 insertions(+), 18 deletions(-) -- 2.25.1