Re: [PATCH v10 70/77] target/riscv: rvv-1.0: floating-point reciprocal estimate instruction
On Mon, Nov 29, 2021 at 1:58 PM wrote: > > From: Frank Chang > > Implement the floating-point reciprocal estimate to 7 bits instruction. > > Signed-off-by: Frank Chang Acked-by: Alistair Francis Alistair > --- > target/riscv/helper.h | 4 + > target/riscv/insn32.decode | 1 + > target/riscv/insn_trans/trans_rvv.c.inc | 1 + > target/riscv/vector_helper.c| 191 > 4 files changed, 197 insertions(+) > > diff --git a/target/riscv/helper.h b/target/riscv/helper.h > index bdf06dfb24d..ab283d12b79 100644 > --- a/target/riscv/helper.h > +++ b/target/riscv/helper.h > @@ -845,6 +845,10 @@ DEF_HELPER_5(vfrsqrt7_v_h, void, ptr, ptr, ptr, env, i32) > DEF_HELPER_5(vfrsqrt7_v_w, void, ptr, ptr, ptr, env, i32) > DEF_HELPER_5(vfrsqrt7_v_d, void, ptr, ptr, ptr, env, i32) > > +DEF_HELPER_5(vfrec7_v_h, void, ptr, ptr, ptr, env, i32) > +DEF_HELPER_5(vfrec7_v_w, void, ptr, ptr, ptr, env, i32) > +DEF_HELPER_5(vfrec7_v_d, void, ptr, ptr, ptr, env, i32) > + > DEF_HELPER_6(vfmin_vv_h, void, ptr, ptr, ptr, ptr, env, i32) > DEF_HELPER_6(vfmin_vv_w, void, ptr, ptr, ptr, ptr, env, i32) > DEF_HELPER_6(vfmin_vv_d, void, ptr, ptr, ptr, ptr, env, i32) > diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode > index 6e5f288943a..952768f8ded 100644 > --- a/target/riscv/insn32.decode > +++ b/target/riscv/insn32.decode > @@ -561,6 +561,7 @@ vfwnmsac_vv 11 . . . 001 . 1010111 > @r_vm > vfwnmsac_vf 11 . . . 101 . 1010111 @r_vm > vfsqrt_v010011 . . 0 001 . 1010111 @r2_vm > vfrsqrt7_v 010011 . . 00100 001 . 1010111 @r2_vm > +vfrec7_v010011 . . 00101 001 . 1010111 @r2_vm > vfmin_vv000100 . . . 001 . 1010111 @r_vm > vfmin_vf000100 . . . 101 . 1010111 @r_vm > vfmax_vv000110 . . . 001 . 1010111 @r_vm > diff --git a/target/riscv/insn_trans/trans_rvv.c.inc > b/target/riscv/insn_trans/trans_rvv.c.inc > index 8fe718610a9..ff8f6df8f7b 100644 > --- a/target/riscv/insn_trans/trans_rvv.c.inc > +++ b/target/riscv/insn_trans/trans_rvv.c.inc > @@ -2408,6 +2408,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ > > GEN_OPFV_TRANS(vfsqrt_v, opfv_check, RISCV_FRM_DYN) > GEN_OPFV_TRANS(vfrsqrt7_v, opfv_check, RISCV_FRM_DYN) > +GEN_OPFV_TRANS(vfrec7_v, opfv_check, RISCV_FRM_DYN) > > /* Vector Floating-Point MIN/MAX Instructions */ > GEN_OPFVV_TRANS(vfmin_vv, opfvv_check) > diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c > index d5f3229bcb4..946dca53ffd 100644 > --- a/target/riscv/vector_helper.c > +++ b/target/riscv/vector_helper.c > @@ -3587,6 +3587,197 @@ GEN_VEXT_V_ENV(vfrsqrt7_v_h, 2, 2) > GEN_VEXT_V_ENV(vfrsqrt7_v_w, 4, 4) > GEN_VEXT_V_ENV(vfrsqrt7_v_d, 8, 8) > > +/* > + * Vector Floating-Point Reciprocal Estimate Instruction > + * > + * Adapted from riscv-v-spec recip.c: > + * https://github.com/riscv/riscv-v-spec/blob/master/recip.c > + */ > +static uint64_t frec7(uint64_t f, int exp_size, int frac_size, > + float_status *s) > +{ > +uint64_t sign = extract64(f, frac_size + exp_size, 1); > +uint64_t exp = extract64(f, frac_size, exp_size); > +uint64_t frac = extract64(f, 0, frac_size); > + > +const uint8_t lookup_table[] = { > +127, 125, 123, 121, 119, 117, 116, 114, > +112, 110, 109, 107, 105, 104, 102, 100, > +99, 97, 96, 94, 93, 91, 90, 88, > +87, 85, 84, 83, 81, 80, 79, 77, > +76, 75, 74, 72, 71, 70, 69, 68, > +66, 65, 64, 63, 62, 61, 60, 59, > +58, 57, 56, 55, 54, 53, 52, 51, > +50, 49, 48, 47, 46, 45, 44, 43, > +42, 41, 40, 40, 39, 38, 37, 36, > +35, 35, 34, 33, 32, 31, 31, 30, > +29, 28, 28, 27, 26, 25, 25, 24, > +23, 23, 22, 21, 21, 20, 19, 19, > +18, 17, 17, 16, 15, 15, 14, 14, > +13, 12, 12, 11, 11, 10, 9, 9, > +8, 8, 7, 7, 6, 5, 5, 4, > +4, 3, 3, 2, 2, 1, 1, 0 > +}; > +const int precision = 7; > + > +if (exp == 0 && frac != 0) { /* subnormal */ > +/* Normalize the subnormal. */ > +while (extract64(frac, frac_size - 1, 1) == 0) { > +exp--; > +frac <<= 1; > +} > + > +frac = (frac << 1) & MAKE_64BIT_MASK(0, frac_size); > + > +if (exp != 0 && exp != UINT64_MAX) { > +/* > + * Overflow to inf or max value of same sign, > + * depending on sign and rounding mode. > + */ > +s->float_exception_flags |= (float_flag_inexact | > + float_flag_overflow); > + > +if ((s->float_rounding_mode == float_round_to_zero) || > +((s->float_rounding_mode == float_round_down) && !sign) || > +((s->float_rounding_mode == float_round_up) && sign)) { > +/* Return greatest/negative finite
[PATCH v10 70/77] target/riscv: rvv-1.0: floating-point reciprocal estimate instruction
From: Frank Chang Implement the floating-point reciprocal estimate to 7 bits instruction. Signed-off-by: Frank Chang --- target/riscv/helper.h | 4 + target/riscv/insn32.decode | 1 + target/riscv/insn_trans/trans_rvv.c.inc | 1 + target/riscv/vector_helper.c| 191 4 files changed, 197 insertions(+) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index bdf06dfb24d..ab283d12b79 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -845,6 +845,10 @@ DEF_HELPER_5(vfrsqrt7_v_h, void, ptr, ptr, ptr, env, i32) DEF_HELPER_5(vfrsqrt7_v_w, void, ptr, ptr, ptr, env, i32) DEF_HELPER_5(vfrsqrt7_v_d, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfrec7_v_h, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfrec7_v_w, void, ptr, ptr, ptr, env, i32) +DEF_HELPER_5(vfrec7_v_d, void, ptr, ptr, ptr, env, i32) + DEF_HELPER_6(vfmin_vv_h, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vfmin_vv_w, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vfmin_vv_d, void, ptr, ptr, ptr, ptr, env, i32) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 6e5f288943a..952768f8ded 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -561,6 +561,7 @@ vfwnmsac_vv 11 . . . 001 . 1010111 @r_vm vfwnmsac_vf 11 . . . 101 . 1010111 @r_vm vfsqrt_v010011 . . 0 001 . 1010111 @r2_vm vfrsqrt7_v 010011 . . 00100 001 . 1010111 @r2_vm +vfrec7_v010011 . . 00101 001 . 1010111 @r2_vm vfmin_vv000100 . . . 001 . 1010111 @r_vm vfmin_vf000100 . . . 101 . 1010111 @r_vm vfmax_vv000110 . . . 001 . 1010111 @r_vm diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 8fe718610a9..ff8f6df8f7b 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -2408,6 +2408,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ GEN_OPFV_TRANS(vfsqrt_v, opfv_check, RISCV_FRM_DYN) GEN_OPFV_TRANS(vfrsqrt7_v, opfv_check, RISCV_FRM_DYN) +GEN_OPFV_TRANS(vfrec7_v, opfv_check, RISCV_FRM_DYN) /* Vector Floating-Point MIN/MAX Instructions */ GEN_OPFVV_TRANS(vfmin_vv, opfvv_check) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index d5f3229bcb4..946dca53ffd 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -3587,6 +3587,197 @@ GEN_VEXT_V_ENV(vfrsqrt7_v_h, 2, 2) GEN_VEXT_V_ENV(vfrsqrt7_v_w, 4, 4) GEN_VEXT_V_ENV(vfrsqrt7_v_d, 8, 8) +/* + * Vector Floating-Point Reciprocal Estimate Instruction + * + * Adapted from riscv-v-spec recip.c: + * https://github.com/riscv/riscv-v-spec/blob/master/recip.c + */ +static uint64_t frec7(uint64_t f, int exp_size, int frac_size, + float_status *s) +{ +uint64_t sign = extract64(f, frac_size + exp_size, 1); +uint64_t exp = extract64(f, frac_size, exp_size); +uint64_t frac = extract64(f, 0, frac_size); + +const uint8_t lookup_table[] = { +127, 125, 123, 121, 119, 117, 116, 114, +112, 110, 109, 107, 105, 104, 102, 100, +99, 97, 96, 94, 93, 91, 90, 88, +87, 85, 84, 83, 81, 80, 79, 77, +76, 75, 74, 72, 71, 70, 69, 68, +66, 65, 64, 63, 62, 61, 60, 59, +58, 57, 56, 55, 54, 53, 52, 51, +50, 49, 48, 47, 46, 45, 44, 43, +42, 41, 40, 40, 39, 38, 37, 36, +35, 35, 34, 33, 32, 31, 31, 30, +29, 28, 28, 27, 26, 25, 25, 24, +23, 23, 22, 21, 21, 20, 19, 19, +18, 17, 17, 16, 15, 15, 14, 14, +13, 12, 12, 11, 11, 10, 9, 9, +8, 8, 7, 7, 6, 5, 5, 4, +4, 3, 3, 2, 2, 1, 1, 0 +}; +const int precision = 7; + +if (exp == 0 && frac != 0) { /* subnormal */ +/* Normalize the subnormal. */ +while (extract64(frac, frac_size - 1, 1) == 0) { +exp--; +frac <<= 1; +} + +frac = (frac << 1) & MAKE_64BIT_MASK(0, frac_size); + +if (exp != 0 && exp != UINT64_MAX) { +/* + * Overflow to inf or max value of same sign, + * depending on sign and rounding mode. + */ +s->float_exception_flags |= (float_flag_inexact | + float_flag_overflow); + +if ((s->float_rounding_mode == float_round_to_zero) || +((s->float_rounding_mode == float_round_down) && !sign) || +((s->float_rounding_mode == float_round_up) && sign)) { +/* Return greatest/negative finite value. */ +return (sign << (exp_size + frac_size)) | +(MAKE_64BIT_MASK(frac_size, exp_size) - 1); +} else { +/* Return +-inf. */ +return (sign << (exp_size + frac_size)) | +MAKE_64BIT_MASK(frac_size,