diff options
author | Weiwei Li <liweiwei@iscas.ac.cn> | 2023-03-07 16:13:59 +0800 |
---|---|---|
committer | Alistair Francis <alistair.francis@wdc.com> | 2023-05-05 10:49:50 +1000 |
commit | 193eb522e4083d8e84c3fae443fd98bc300b95d0 (patch) | |
tree | 4ed4a127f94712c691fdf276b75674896839ed96 /target/riscv/insn_trans | |
parent | e0a3054f18e20602768d328b0cb7d5910253a327 (diff) | |
download | qemu-193eb522e4083d8e84c3fae443fd98bc300b95d0.zip qemu-193eb522e4083d8e84c3fae443fd98bc300b95d0.tar.gz qemu-193eb522e4083d8e84c3fae443fd98bc300b95d0.tar.bz2 |
target/riscv: add support for Zcmp extension
Add encode, trans* functions for Zcmp instructions.
Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn>
Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20230307081403.61950-7-liweiwei@iscas.ac.cn>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'target/riscv/insn_trans')
-rw-r--r-- | target/riscv/insn_trans/trans_rvzce.c.inc | 187 |
1 files changed, 186 insertions, 1 deletions
diff --git a/target/riscv/insn_trans/trans_rvzce.c.inc b/target/riscv/insn_trans/trans_rvzce.c.inc index de96c4a..a47959e 100644 --- a/target/riscv/insn_trans/trans_rvzce.c.inc +++ b/target/riscv/insn_trans/trans_rvzce.c.inc @@ -1,5 +1,5 @@ /* - * RISC-V translation routines for the Zcb Standard Extension. + * RISC-V translation routines for the Zc[b,mp] Standard Extensions. * * Copyright (c) 2021-2022 PLCT Lab * @@ -21,6 +21,11 @@ return false; \ } while (0) +#define REQUIRE_ZCMP(ctx) do { \ + if (!ctx->cfg_ptr->ext_zcmp) \ + return false; \ +} while (0) + static bool trans_c_zext_b(DisasContext *ctx, arg_c_zext_b *a) { REQUIRE_ZCB(ctx); @@ -98,3 +103,183 @@ static bool trans_c_sh(DisasContext *ctx, arg_c_sh *a) REQUIRE_ZCB(ctx); return gen_store(ctx, a, MO_UW); } + +#define X_S0 8 +#define X_S1 9 +#define X_Sn 16 + +static uint32_t decode_push_pop_list(DisasContext *ctx, target_ulong rlist) +{ + uint32_t reg_bitmap = 0; + + if (ctx->cfg_ptr->ext_e && rlist > 6) { + return 0; + } + + switch (rlist) { + case 15: + reg_bitmap |= 1 << (X_Sn + 11) ; + reg_bitmap |= 1 << (X_Sn + 10) ; + /* FALL THROUGH */ + case 14: + reg_bitmap |= 1 << (X_Sn + 9) ; + /* FALL THROUGH */ + case 13: + reg_bitmap |= 1 << (X_Sn + 8) ; + /* FALL THROUGH */ + case 12: + reg_bitmap |= 1 << (X_Sn + 7) ; + /* FALL THROUGH */ + case 11: + reg_bitmap |= 1 << (X_Sn + 6) ; + /* FALL THROUGH */ + case 10: + reg_bitmap |= 1 << (X_Sn + 5) ; + /* FALL THROUGH */ + case 9: + reg_bitmap |= 1 << (X_Sn + 4) ; + /* FALL THROUGH */ + case 8: + reg_bitmap |= 1 << (X_Sn + 3) ; + /* FALL THROUGH */ + case 7: + reg_bitmap |= 1 << (X_Sn + 2) ; + /* FALL THROUGH */ + case 6: + reg_bitmap |= 1 << X_S1 ; + /* FALL THROUGH */ + case 5: + reg_bitmap |= 1 << X_S0; + /* FALL THROUGH */ + case 4: + reg_bitmap |= 1 << xRA; + break; + default: + break; + } + + return reg_bitmap; +} + +static bool gen_pop(DisasContext *ctx, arg_cmpp *a, bool ret, bool ret_val) +{ + REQUIRE_ZCMP(ctx); + + uint32_t reg_bitmap = decode_push_pop_list(ctx, a->urlist); + if (reg_bitmap == 0) { + return false; + } + + MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_TEUL : MO_TEUQ; + int reg_size = memop_size(memop); + target_ulong stack_adj = ROUND_UP(ctpop32(reg_bitmap) * reg_size, 16) + + a->spimm; + TCGv sp = dest_gpr(ctx, xSP); + TCGv addr = tcg_temp_new(); + int i; + + tcg_gen_addi_tl(addr, sp, stack_adj - reg_size); + + for (i = X_Sn + 11; i >= 0; i--) { + if (reg_bitmap & (1 << i)) { + TCGv dest = dest_gpr(ctx, i); + tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, memop); + gen_set_gpr(ctx, i, dest); + tcg_gen_subi_tl(addr, addr, reg_size); + } + } + + tcg_gen_addi_tl(sp, sp, stack_adj); + gen_set_gpr(ctx, xSP, sp); + + if (ret_val) { + gen_set_gpr(ctx, xA0, ctx->zero); + } + + if (ret) { + TCGv ret_addr = get_gpr(ctx, xRA, EXT_NONE); + gen_set_pc(ctx, ret_addr); + tcg_gen_lookup_and_goto_ptr(); + ctx->base.is_jmp = DISAS_NORETURN; + } + + return true; +} + +static bool trans_cm_push(DisasContext *ctx, arg_cm_push *a) +{ + REQUIRE_ZCMP(ctx); + + uint32_t reg_bitmap = decode_push_pop_list(ctx, a->urlist); + if (reg_bitmap == 0) { + return false; + } + + MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_TEUL : MO_TEUQ; + int reg_size = memop_size(memop); + target_ulong stack_adj = ROUND_UP(ctpop32(reg_bitmap) * reg_size, 16) + + a->spimm; + TCGv sp = dest_gpr(ctx, xSP); + TCGv addr = tcg_temp_new(); + int i; + + tcg_gen_subi_tl(addr, sp, reg_size); + + for (i = X_Sn + 11; i >= 0; i--) { + if (reg_bitmap & (1 << i)) { + TCGv val = get_gpr(ctx, i, EXT_NONE); + tcg_gen_qemu_st_tl(val, addr, ctx->mem_idx, memop); + tcg_gen_subi_tl(addr, addr, reg_size); + } + } + + tcg_gen_subi_tl(sp, sp, stack_adj); + gen_set_gpr(ctx, xSP, sp); + + return true; +} + +static bool trans_cm_pop(DisasContext *ctx, arg_cm_pop *a) +{ + return gen_pop(ctx, a, false, false); +} + +static bool trans_cm_popret(DisasContext *ctx, arg_cm_popret *a) +{ + return gen_pop(ctx, a, true, false); +} + +static bool trans_cm_popretz(DisasContext *ctx, arg_cm_popret *a) +{ + return gen_pop(ctx, a, true, true); +} + +static bool trans_cm_mva01s(DisasContext *ctx, arg_cm_mva01s *a) +{ + REQUIRE_ZCMP(ctx); + + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); + + gen_set_gpr(ctx, xA0, src1); + gen_set_gpr(ctx, xA1, src2); + + return true; +} + +static bool trans_cm_mvsa01(DisasContext *ctx, arg_cm_mvsa01 *a) +{ + REQUIRE_ZCMP(ctx); + + if (a->rs1 == a->rs2) { + return false; + } + + TCGv a0 = get_gpr(ctx, xA0, EXT_NONE); + TCGv a1 = get_gpr(ctx, xA1, EXT_NONE); + + gen_set_gpr(ctx, a->rs1, a0); + gen_set_gpr(ctx, a->rs2, a1); + + return true; +} |