mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 08:43:55 -06:00
target/riscv: vector integer add-with-carry / subtract-with-borrow instructions
Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20200701152549.1218-13-zhiwei_liu@c-sky.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
8fcdf77630
commit
3a6f8f68ad
4 changed files with 294 additions and 0 deletions
|
@ -1249,3 +1249,116 @@ GEN_OPIWX_WIDEN_TRANS(vwaddu_wx)
|
|||
GEN_OPIWX_WIDEN_TRANS(vwadd_wx)
|
||||
GEN_OPIWX_WIDEN_TRANS(vwsubu_wx)
|
||||
GEN_OPIWX_WIDEN_TRANS(vwsub_wx)
|
||||
|
||||
/* Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions */
|
||||
/* OPIVV without GVEC IR */
|
||||
#define GEN_OPIVV_TRANS(NAME, CHECK) \
|
||||
static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
||||
{ \
|
||||
if (CHECK(s, a)) { \
|
||||
uint32_t data = 0; \
|
||||
static gen_helper_gvec_4_ptr * const fns[4] = { \
|
||||
gen_helper_##NAME##_b, gen_helper_##NAME##_h, \
|
||||
gen_helper_##NAME##_w, gen_helper_##NAME##_d, \
|
||||
}; \
|
||||
TCGLabel *over = gen_new_label(); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
|
||||
\
|
||||
data = FIELD_DP32(data, VDATA, MLEN, s->mlen); \
|
||||
data = FIELD_DP32(data, VDATA, VM, a->vm); \
|
||||
data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \
|
||||
tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \
|
||||
vreg_ofs(s, a->rs1), \
|
||||
vreg_ofs(s, a->rs2), cpu_env, 0, \
|
||||
s->vlen / 8, data, fns[s->sew]); \
|
||||
gen_set_label(over); \
|
||||
return true; \
|
||||
} \
|
||||
return false; \
|
||||
}
|
||||
|
||||
/*
|
||||
* For vadc and vsbc, an illegal instruction exception is raised if the
|
||||
* destination vector register is v0 and LMUL > 1. (Section 12.3)
|
||||
*/
|
||||
static bool opivv_vadc_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return (vext_check_isa_ill(s) &&
|
||||
vext_check_reg(s, a->rd, false) &&
|
||||
vext_check_reg(s, a->rs2, false) &&
|
||||
vext_check_reg(s, a->rs1, false) &&
|
||||
((a->rd != 0) || (s->lmul == 0)));
|
||||
}
|
||||
|
||||
GEN_OPIVV_TRANS(vadc_vvm, opivv_vadc_check)
|
||||
GEN_OPIVV_TRANS(vsbc_vvm, opivv_vadc_check)
|
||||
|
||||
/*
|
||||
* For vmadc and vmsbc, an illegal instruction exception is raised if the
|
||||
* destination vector register overlaps a source vector register group.
|
||||
*/
|
||||
static bool opivv_vmadc_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return (vext_check_isa_ill(s) &&
|
||||
vext_check_reg(s, a->rs2, false) &&
|
||||
vext_check_reg(s, a->rs1, false) &&
|
||||
vext_check_overlap_group(a->rd, 1, a->rs1, 1 << s->lmul) &&
|
||||
vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul));
|
||||
}
|
||||
|
||||
GEN_OPIVV_TRANS(vmadc_vvm, opivv_vmadc_check)
|
||||
GEN_OPIVV_TRANS(vmsbc_vvm, opivv_vmadc_check)
|
||||
|
||||
static bool opivx_vadc_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return (vext_check_isa_ill(s) &&
|
||||
vext_check_reg(s, a->rd, false) &&
|
||||
vext_check_reg(s, a->rs2, false) &&
|
||||
((a->rd != 0) || (s->lmul == 0)));
|
||||
}
|
||||
|
||||
/* OPIVX without GVEC IR */
|
||||
#define GEN_OPIVX_TRANS(NAME, CHECK) \
|
||||
static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
||||
{ \
|
||||
if (CHECK(s, a)) { \
|
||||
static gen_helper_opivx * const fns[4] = { \
|
||||
gen_helper_##NAME##_b, gen_helper_##NAME##_h, \
|
||||
gen_helper_##NAME##_w, gen_helper_##NAME##_d, \
|
||||
}; \
|
||||
\
|
||||
return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\
|
||||
} \
|
||||
return false; \
|
||||
}
|
||||
|
||||
GEN_OPIVX_TRANS(vadc_vxm, opivx_vadc_check)
|
||||
GEN_OPIVX_TRANS(vsbc_vxm, opivx_vadc_check)
|
||||
|
||||
static bool opivx_vmadc_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return (vext_check_isa_ill(s) &&
|
||||
vext_check_reg(s, a->rs2, false) &&
|
||||
vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul));
|
||||
}
|
||||
|
||||
GEN_OPIVX_TRANS(vmadc_vxm, opivx_vmadc_check)
|
||||
GEN_OPIVX_TRANS(vmsbc_vxm, opivx_vmadc_check)
|
||||
|
||||
/* OPIVI without GVEC IR */
|
||||
#define GEN_OPIVI_TRANS(NAME, ZX, OPIVX, CHECK) \
|
||||
static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
||||
{ \
|
||||
if (CHECK(s, a)) { \
|
||||
static gen_helper_opivx * const fns[4] = { \
|
||||
gen_helper_##OPIVX##_b, gen_helper_##OPIVX##_h, \
|
||||
gen_helper_##OPIVX##_w, gen_helper_##OPIVX##_d, \
|
||||
}; \
|
||||
return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, \
|
||||
fns[s->sew], s, ZX); \
|
||||
} \
|
||||
return false; \
|
||||
}
|
||||
|
||||
GEN_OPIVI_TRANS(vadc_vim, 0, vadc_vxm, opivx_vadc_check)
|
||||
GEN_OPIVI_TRANS(vmadc_vim, 0, vmadc_vxm, opivx_vmadc_check)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue