mirror of https://github.com/xemu-project/xemu.git
target/arm: Implement VFMAL and VFMSL for aarch32
Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190219222952.22183-4-richard.henderson@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
0caa5af802
commit
87732318c5
|
@ -3296,6 +3296,11 @@ static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
|
|||
return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -8383,15 +8383,9 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
|
|||
gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
|
||||
int rd, rn, rm, opr_sz;
|
||||
int data = 0;
|
||||
bool q;
|
||||
|
||||
q = extract32(insn, 6, 1);
|
||||
VFP_DREG_D(rd, insn);
|
||||
VFP_DREG_N(rn, insn);
|
||||
VFP_DREG_M(rm, insn);
|
||||
if ((rd | rn | rm) & q) {
|
||||
return 1;
|
||||
}
|
||||
int off_rn, off_rm;
|
||||
bool is_long = false, q = extract32(insn, 6, 1);
|
||||
bool ptr_is_env = false;
|
||||
|
||||
if ((insn & 0xfe200f10) == 0xfc200800) {
|
||||
/* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
|
||||
|
@ -8418,10 +8412,39 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
|
|||
return 1;
|
||||
}
|
||||
fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
|
||||
} else if ((insn & 0xff300f10) == 0xfc200810) {
|
||||
/* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
|
||||
int is_s = extract32(insn, 23, 1);
|
||||
if (!dc_isar_feature(aa32_fhm, s)) {
|
||||
return 1;
|
||||
}
|
||||
is_long = true;
|
||||
data = is_s; /* is_2 == 0 */
|
||||
fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
|
||||
ptr_is_env = true;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
VFP_DREG_D(rd, insn);
|
||||
if (rd & q) {
|
||||
return 1;
|
||||
}
|
||||
if (q || !is_long) {
|
||||
VFP_DREG_N(rn, insn);
|
||||
VFP_DREG_M(rm, insn);
|
||||
if ((rn | rm) & q & !is_long) {
|
||||
return 1;
|
||||
}
|
||||
off_rn = vfp_reg_offset(1, rn);
|
||||
off_rm = vfp_reg_offset(1, rm);
|
||||
} else {
|
||||
rn = VFP_SREG_N(insn);
|
||||
rm = VFP_SREG_M(insn);
|
||||
off_rn = vfp_reg_offset(0, rn);
|
||||
off_rm = vfp_reg_offset(0, rm);
|
||||
}
|
||||
|
||||
if (s->fp_excp_el) {
|
||||
gen_exception_insn(s, 4, EXCP_UDEF,
|
||||
syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
|
||||
|
@ -8433,16 +8456,19 @@ static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
|
|||
|
||||
opr_sz = (1 + q) * 8;
|
||||
if (fn_gvec_ptr) {
|
||||
TCGv_ptr fpst = get_fpstatus_ptr(1);
|
||||
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
|
||||
vfp_reg_offset(1, rn),
|
||||
vfp_reg_offset(1, rm), fpst,
|
||||
TCGv_ptr ptr;
|
||||
if (ptr_is_env) {
|
||||
ptr = cpu_env;
|
||||
} else {
|
||||
ptr = get_fpstatus_ptr(1);
|
||||
}
|
||||
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
|
||||
opr_sz, opr_sz, data, fn_gvec_ptr);
|
||||
tcg_temp_free_ptr(fpst);
|
||||
if (!ptr_is_env) {
|
||||
tcg_temp_free_ptr(ptr);
|
||||
}
|
||||
} else {
|
||||
tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
|
||||
vfp_reg_offset(1, rn),
|
||||
vfp_reg_offset(1, rm),
|
||||
tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
|
||||
opr_sz, opr_sz, data, fn_gvec);
|
||||
}
|
||||
return 0;
|
||||
|
@ -8461,14 +8487,9 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
|
|||
gen_helper_gvec_3 *fn_gvec = NULL;
|
||||
gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
|
||||
int rd, rn, rm, opr_sz, data;
|
||||
bool q;
|
||||
|
||||
q = extract32(insn, 6, 1);
|
||||
VFP_DREG_D(rd, insn);
|
||||
VFP_DREG_N(rn, insn);
|
||||
if ((rd | rn) & q) {
|
||||
return 1;
|
||||
}
|
||||
int off_rn, off_rm;
|
||||
bool is_long = false, q = extract32(insn, 6, 1);
|
||||
bool ptr_is_env = false;
|
||||
|
||||
if ((insn & 0xff000f10) == 0xfe000800) {
|
||||
/* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
|
||||
|
@ -8497,6 +8518,7 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
|
|||
} else if ((insn & 0xffb00f00) == 0xfe200d00) {
|
||||
/* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
|
||||
int u = extract32(insn, 4, 1);
|
||||
|
||||
if (!dc_isar_feature(aa32_dp, s)) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -8504,10 +8526,48 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
|
|||
/* rm is just Vm, and index is M. */
|
||||
data = extract32(insn, 5, 1); /* index */
|
||||
rm = extract32(insn, 0, 4);
|
||||
} else if ((insn & 0xffa00f10) == 0xfe000810) {
|
||||
/* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
|
||||
int is_s = extract32(insn, 20, 1);
|
||||
int vm20 = extract32(insn, 0, 3);
|
||||
int vm3 = extract32(insn, 3, 1);
|
||||
int m = extract32(insn, 5, 1);
|
||||
int index;
|
||||
|
||||
if (!dc_isar_feature(aa32_fhm, s)) {
|
||||
return 1;
|
||||
}
|
||||
if (q) {
|
||||
rm = vm20;
|
||||
index = m * 2 + vm3;
|
||||
} else {
|
||||
rm = vm20 * 2 + m;
|
||||
index = vm3;
|
||||
}
|
||||
is_long = true;
|
||||
data = (index << 2) | is_s; /* is_2 == 0 */
|
||||
fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
|
||||
ptr_is_env = true;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
VFP_DREG_D(rd, insn);
|
||||
if (rd & q) {
|
||||
return 1;
|
||||
}
|
||||
if (q || !is_long) {
|
||||
VFP_DREG_N(rn, insn);
|
||||
if (rn & q & !is_long) {
|
||||
return 1;
|
||||
}
|
||||
off_rn = vfp_reg_offset(1, rn);
|
||||
off_rm = vfp_reg_offset(1, rm);
|
||||
} else {
|
||||
rn = VFP_SREG_N(insn);
|
||||
off_rn = vfp_reg_offset(0, rn);
|
||||
off_rm = vfp_reg_offset(0, rm);
|
||||
}
|
||||
if (s->fp_excp_el) {
|
||||
gen_exception_insn(s, 4, EXCP_UDEF,
|
||||
syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
|
||||
|
@ -8519,16 +8579,19 @@ static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
|
|||
|
||||
opr_sz = (1 + q) * 8;
|
||||
if (fn_gvec_ptr) {
|
||||
TCGv_ptr fpst = get_fpstatus_ptr(1);
|
||||
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
|
||||
vfp_reg_offset(1, rn),
|
||||
vfp_reg_offset(1, rm), fpst,
|
||||
TCGv_ptr ptr;
|
||||
if (ptr_is_env) {
|
||||
ptr = cpu_env;
|
||||
} else {
|
||||
ptr = get_fpstatus_ptr(1);
|
||||
}
|
||||
tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
|
||||
opr_sz, opr_sz, data, fn_gvec_ptr);
|
||||
tcg_temp_free_ptr(fpst);
|
||||
if (!ptr_is_env) {
|
||||
tcg_temp_free_ptr(ptr);
|
||||
}
|
||||
} else {
|
||||
tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
|
||||
vfp_reg_offset(1, rn),
|
||||
vfp_reg_offset(1, rm),
|
||||
tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
|
||||
opr_sz, opr_sz, data, fn_gvec);
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue