On Fri, Nov 20, 2020 at 5:04 AM Richard Henderson <
richard.hender...@linaro.org> wrote:

> On 11/19/20 12:35 PM, Richard Henderson wrote:
> > On 11/18/20 12:29 AM, frank.ch...@sifive.com wrote:
> >> +static bool trans_sbset(DisasContext *ctx, arg_sbset *a)
> >> +{
> >> +    REQUIRE_EXT(ctx, RVB);
> >> +    return gen_arith(ctx, a, &gen_sbset);
> >> +}
> >> +
> >> +static bool trans_sbseti(DisasContext *ctx, arg_sbseti *a)
> >> +{
> >> +    REQUIRE_EXT(ctx, RVB);
> >> +    return gen_arith_shamt_tl(ctx, a, &gen_sbset);
> >> +}
> >> +
> >> +static bool trans_sbclr(DisasContext *ctx, arg_sbclr *a)
> >> +{
> >> +    REQUIRE_EXT(ctx, RVB);
> >> +    return gen_arith(ctx, a, &gen_sbclr);
> >> +}
> >
> > Coming back to my re-use of code thing, these should use gen_shift.  That
> > handles the truncate of source2 to the shift amount.
> >
> >> +static bool trans_sbclri(DisasContext *ctx, arg_sbclri *a)
> >> +{
> >> +    REQUIRE_EXT(ctx, RVB);
> >> +    return gen_arith_shamt_tl(ctx, a, &gen_sbclr);
> >> +}
> >> +
> >> +static bool trans_sbinv(DisasContext *ctx, arg_sbinv *a)
> >> +{
> >> +    REQUIRE_EXT(ctx, RVB);
> >> +    return gen_arith(ctx, a, &gen_sbinv);
> >> +}
> >> +
> >> +static bool trans_sbinvi(DisasContext *ctx, arg_sbinvi *a)
> >> +{
> >> +    REQUIRE_EXT(ctx, RVB);
> >> +    return gen_arith_shamt_tl(ctx, a, &gen_sbinv);
> >> +}
> >
> > I think there ought to be a gen_shifti for these.
>
> Hmm.  I just realized that gen_shifti would have a generator callback with
> a
> constant argument, a-la tcg_gen_shli_tl.
>
> I don't know if it's worth duplicating gen_sbclr et al for a constant
> argument.
>  And the sloi/sroi insns besides.  Perhaps a gen_shifti_var helper instead?
>
> Let me know what you think, but at the moment we're left with an
> incoherent set
> of helpers that seem split along lines that are less than ideal.
>
>
> r~
>

Thanks Richard and sorry for the late reply.....

If we can have gen_shift(), gen_shifti(), gen_shiftw() and gen_shiftiw(),
then we can eliminate the needs of:
gen_arith_shamt_tl(), gen_sbop_shamt(), gen_sbopw_shamt()
and gen_sbopw_common()
and most of the *w version generators can be removed, too.

For *w version, we just need to call gen_shiftw() or gen_shiftiw()
with the reused non-*w version generator.
For example:

  static bool trans_sbclrw(DisasContext *ctx, arg_sbclrw *a)
  {
      REQUIRE_EXT(ctx, RVB);
      return gen_shiftw(ctx, a, &gen_sbclr);
  }

  static bool trans_sbclriw(DisasContext *ctx, arg_sbclriw *a)
  {
      REQUIRE_EXT(ctx, RVB);
      return gen_shiftiw(ctx, a, &gen_sbclr);
  }

both of which can reuse gen_sbclr() generator:

  static void gen_sbclr(TCGv ret, TCGv arg1, TCGv shamt)
  {
      TCGv t = tcg_temp_new();
      tcg_gen_movi_tl(t, 1);
      tcg_gen_shl_tl(t, t, shamt);
      tcg_gen_andc_tl(ret, arg1, t);
      tcg_temp_free(t);
  }

The gen_shift*() I have now are as follow:

  static bool gen_shift(DisasContext *ctx, arg_r *a,
                          void(*func)(TCGv, TCGv, TCGv))
  {
      TCGv source1 = tcg_temp_new();
      TCGv source2 = tcg_temp_new();

      gen_get_gpr(source1, a->rs1);
      gen_get_gpr(source2, a->rs2);

      tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1);
      (*func)(source1, source1, source2);

      gen_set_gpr(a->rd, source1);
      tcg_temp_free(source1);
      tcg_temp_free(source2);
      return true;
  }

  static bool gen_shifti(DisasContext *ctx, arg_shift *a,
                          void(*func)(TCGv, TCGv, TCGv))
  {
      TCGv source1 = tcg_temp_new();
      TCGv source2 = tcg_temp_new();

     gen_get_gpr(source1, a->rs1);
     tcg_gen_movi_tl(source2, a->shamt);

      tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1);
      (*func)(source1, source1, source2);

      gen_set_gpr(a->rd, source1);
      tcg_temp_free(source1);
      tcg_temp_free(source2);
      return true;
  }

  static bool gen_shiftw(DisasContext *ctx, arg_r *a,
                          void(*func)(TCGv, TCGv, TCGv))
  {
      TCGv source1 = tcg_temp_new();
      TCGv source2 = tcg_temp_new();

      gen_get_gpr(source1, a->rs1);
      gen_get_gpr(source2, a->rs2);

      tcg_gen_andi_tl(source2, source2, 31);
      (*func)(source1, source1, source2);
      tcg_gen_ext32s_tl(source1, source1);

      gen_set_gpr(a->rd, source1);
      tcg_temp_free(source1);
      tcg_temp_free(source2);
      return true;
  }

  static bool gen_shiftiw(DisasContext *ctx, arg_shift *a,
                          void(*func)(TCGv, TCGv, TCGv))
  {
      TCGv source1 = tcg_temp_new();
      TCGv source2 = tcg_temp_new();

     gen_get_gpr(source1, a->rs1);
     tcg_gen_movi_tl(source2, a->shamt);

     tcg_gen_andi_tl(source2, source2, 31);
     (*func)(source1, source1, source2);
     tcg_gen_ext32s_tl(source1, source1);

      gen_set_gpr(a->rd, source1);
      tcg_temp_free(source1);
      tcg_temp_free(source2);
      return true;
  }

They may be further merged as most of them are duplicate with only the
differences of:
gen_get_gpr(source2, a->rs2); vs. tcg_gen_movi_tl(source2, a->shamt);
TARGET_LONG_BITS - 1 vs. 31, and
tcg_gen_ext32s_tl(); to sign-extend the 32-bit return value for *w
instructions

Any thoughts?

Frank Chang

Reply via email to