All mult/div/rem instructions that work on double integers (suffixed 'd') can be tcg-generated in a few micro-ops, they are added here.
Signed-off-by: Frédéric Pétrot <frederic.pet...@univ-grenoble-alpes.fr> Co-authored-by: Fabien Portas <fabien.por...@grenoble-inp.org> --- target/riscv/insn32.decode | 7 ++ target/riscv/insn_trans/trans_rvm.c.inc | 112 +++++++++++++++++++++++- 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index be8d6aa85f..380604acee 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -198,6 +198,13 @@ divuw 0000001 ..... ..... 101 ..... 0111011 @r remw 0000001 ..... ..... 110 ..... 0111011 @r remuw 0000001 ..... ..... 111 ..... 0111011 @r +# *** RV128M Standard Extension (in addition to RV64M) *** +muld 0000001 ..... ..... 000 ..... 1111011 @r +divd 0000001 ..... ..... 100 ..... 1111011 @r +divud 0000001 ..... ..... 101 ..... 1111011 @r +remd 0000001 ..... ..... 110 ..... 1111011 @r +remud 0000001 ..... ..... 111 ..... 1111011 @r + # *** RV32A Standard Extension *** lr_w 00010 . . 00000 ..... 010 ..... 0101111 @atom_ld sc_w 00011 . . ..... ..... 010 ..... 0101111 @atom_st diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index d61c79450c..9ed9ba0f0f 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -390,13 +390,25 @@ static bool trans_mulw(DisasContext *ctx, arg_mulw *a) tcg_gen_mul_tl, tcg_gen_mul_tl, gen_mulw_i128); } +static void gen_divw_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_div(rdl, rs1l, rs2l); +} + static bool trans_divw(DisasContext *ctx, arg_divw *a) { REQUIRE_64_OR_128BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->w = true; return gen_arith(ctx, a, EXT_SIGN, - gen_div, gen_div, NULL); + gen_div, gen_div, gen_divw_i128); +} + +static void gen_divuw_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_divu(rdl, rs1l, rs2l); } static bool trans_divuw(DisasContext *ctx, arg_divuw *a) @@ -405,7 +417,13 @@ static bool trans_divuw(DisasContext *ctx, arg_divuw *a) REQUIRE_EXT(ctx, RVM); ctx->w = true; return gen_arith(ctx, a, EXT_ZERO, - gen_divu, gen_divu, NULL); + gen_divu, gen_divu, gen_divuw_i128); +} + +static void gen_remw_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_rem(rdl, rs1l, rs2l); } static bool trans_remw(DisasContext *ctx, arg_remw *a) @@ -414,7 +432,13 @@ static bool trans_remw(DisasContext *ctx, arg_remw *a) REQUIRE_EXT(ctx, RVM); ctx->w = true; return gen_arith(ctx, a, EXT_SIGN, - gen_rem, gen_rem, NULL); + gen_rem, gen_rem, gen_remw_i128); +} + +static void gen_remuw_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_remu(rdl, rs1l, rs2l); } static bool trans_remuw(DisasContext *ctx, arg_remuw *a) @@ -423,5 +447,85 @@ static bool trans_remuw(DisasContext *ctx, arg_remuw *a) REQUIRE_EXT(ctx, RVM); ctx->w = true; return gen_arith(ctx, a, EXT_ZERO, - gen_remu, gen_remu, NULL); + gen_remu, gen_remu, gen_remuw_i128); +} + +static void gen_muld_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + tcg_gen_mul_tl(rdl, rs1l, rs2l); +} + +static bool trans_muld(DisasContext *ctx, arg_muld *a) +{ + REQUIRE_128BIT(ctx); + REQUIRE_EXT(ctx, RVM); + ctx->d = true; + + return gen_arith(ctx, a, EXT_SIGN, + tcg_gen_mul_tl, tcg_gen_mul_tl, gen_muld_i128); +} + +static void gen_divd_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_div(rdl, rs1l, rs2l); +} + +static bool trans_divd(DisasContext *ctx, arg_divd *a) +{ + REQUIRE_128BIT(ctx); + REQUIRE_EXT(ctx, RVM); + ctx->d = true; + + return gen_arith(ctx, a, EXT_SIGN, + gen_div, gen_div, gen_divd_i128); +} + +static void gen_divud_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_divu(rdl, rs1l, rs2l); +} + +static bool trans_divud(DisasContext *ctx, arg_divud *a) +{ + REQUIRE_128BIT(ctx); + REQUIRE_EXT(ctx, RVM); + ctx->d = true; + + return gen_arith(ctx, a, EXT_ZERO, + gen_divu, gen_divu, gen_divud_i128); +} + +static void gen_remd_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_rem(rdl, rs1l, rs2l); +} + +static bool trans_remd(DisasContext *ctx, arg_remd *a) +{ + REQUIRE_128BIT(ctx); + REQUIRE_EXT(ctx, RVM); + ctx->d = true; + + return gen_arith(ctx, a, EXT_SIGN, + gen_rem, gen_rem, gen_remd_i128); +} + +static void gen_remud_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_remu(rdl, rs1l, rs2l); +} + +static bool trans_remud(DisasContext *ctx, arg_remud *a) +{ + REQUIRE_128BIT(ctx); + REQUIRE_EXT(ctx, RVM); + ctx->d = true; + + return gen_arith(ctx, a, EXT_ZERO, + gen_remu, gen_remu, gen_remud_i128); } -- 2.33.0