Re: [PATCH v2 4/7] target/riscv: Check nanboxed inputs to fp helpers
On Fri, Jul 24, 2020 at 8:29 AM Richard Henderson < richard.hender...@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 > --- > 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 0x7fc0u; /* 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, >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, > >fp_status)); > } > > @@ -139,74 +142,97 @@ uint64_t helper_fnmadd_d(CPURISCVState *env, > uint64_t frs1, uint64_t frs2, >float_muladd_negate_product, >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, >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, >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, >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, >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, >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, >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, >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, >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, >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, >fp_status); > } > > -target_ulong
Re: [PATCH v2 4/7] target/riscv: Check nanboxed inputs to fp helpers
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 >> --- >> 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 0x7fc0u; /* 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) ? 0x7fc0u : 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~
Re: [PATCH v2 4/7] target/riscv: Check nanboxed inputs to fp helpers
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 --- 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 0x7fc0u; /* 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) ? 0x7fc0u : 0x7e00u; /* default qnan */ +} +} + Reviewed-by: LIU Zhiwei 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, >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, >fp_status)); } @@ -139,74 +142,97 @@ uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, float_muladd_negate_product, >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, >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, >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, >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, >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, >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, >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, >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, >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, >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); +