Signed-off-by: Richard Henderson
---
target/arm/helper.h| 2 +
target/arm/tcg/a64.decode | 22 +++
target/arm/tcg/translate-a64.c | 241 +
target/arm/tcg/vec_helper.c| 14 ++
4 files changed, 163 insertions(+), 116 deletions(-)
diff --git a/target/arm/helper.h b/target/arm/helper.h
index 0fd01c9c52..e021c18517 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -770,9 +770,11 @@ DEF_HELPER_FLAGS_5(gvec_fmls_s, TCG_CALL_NO_RWG, void,
ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(gvec_vfma_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(gvec_vfma_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_vfma_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(gvec_vfms_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(gvec_vfms_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_vfms_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, i32)
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index dbfdfd80f9..cb84a8685f 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -742,12 +742,26 @@ FMINNM_v0.00 1110 1.1 . 11000 1 . .
@qrrr_sd
FMULX_v 0.00 0111 010 . 00011 1 . . @qrrr_h
FMULX_v 0.00 1110 0.1 . 11011 1 . . @qrrr_sd
+FMLA_v 0.00 1110 010 . 1 1 . . @qrrr_h
+FMLA_v 0.00 1110 0.1 . 11001 1 . . @qrrr_sd
+
+FMLS_v 0.00 1110 110 . 1 1 . . @qrrr_h
+FMLS_v 0.00 1110 1.1 . 11001 1 . . @qrrr_sd
+
### Advanced SIMD scalar x indexed element
FMUL_si 0101 00 .. 1001 . 0 . . @rrx_h
FMUL_si 0101 10 . . 1001 . 0 . . @rrx_s
FMUL_si 0101 11 0 . 1001 . 0 . . @rrx_d
+FMLA_si 0101 00 .. 0001 . 0 . . @rrx_h
+FMLA_si 0101 10 .. 0001 . 0 . . @rrx_s
+FMLA_si 0101 11 0. 0001 . 0 . . @rrx_d
+
+FMLS_si 0101 00 .. 0101 . 0 . . @rrx_h
+FMLS_si 0101 10 .. 0101 . 0 . . @rrx_s
+FMLS_si 0101 11 0. 0101 . 0 . . @rrx_d
+
FMULX_si0111 00 .. 1001 . 0 . . @rrx_h
FMULX_si0111 10 . . 1001 . 0 . . @rrx_s
FMULX_si0111 11 0 . 1001 . 0 . . @rrx_d
@@ -758,6 +772,14 @@ FMUL_vi 0.00 00 .. 1001 . 0 . .
@qrrx_h
FMUL_vi 0.00 10 . . 1001 . 0 . . @qrrx_s
FMUL_vi 0.00 11 0 . 1001 . 0 . . @qrrx_d
+FMLA_vi 0.00 00 .. 0001 . 0 . . @qrrx_h
+FMLA_vi 0.00 10 . . 0001 . 0 . . @qrrx_s
+FMLA_vi 0.00 11 0 . 0001 . 0 . . @qrrx_d
+
+FMLS_vi 0.00 00 .. 0101 . 0 . . @qrrx_h
+FMLS_vi 0.00 10 . . 0101 . 0 . . @qrrx_s
+FMLS_vi 0.00 11 0 . 0101 . 0 . . @qrrx_d
+
FMULX_vi0.10 00 .. 1001 . 0 . . @qrrx_h
FMULX_vi0.10 10 . . 1001 . 0 . . @qrrx_s
FMULX_vi0.10 11 0 . 1001 . 0 . . @qrrx_d
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index caf4d8154d..36aae079da 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -5067,6 +5067,20 @@ static gen_helper_gvec_3_ptr * const f_vector_fmulx[3] =
{
};
TRANS(FMULX_v, do_fp3_vector, a, f_vector_fmulx)
+static gen_helper_gvec_3_ptr * const f_vector_fmla[3] = {
+gen_helper_gvec_vfma_h,
+gen_helper_gvec_vfma_s,
+gen_helper_gvec_vfma_d,
+};
+TRANS(FMLA_v, do_fp3_vector, a, f_vector_fmla)
+
+static gen_helper_gvec_3_ptr * const f_vector_fmls[3] = {
+gen_helper_gvec_vfms_h,
+gen_helper_gvec_vfms_s,
+gen_helper_gvec_vfms_d,
+};
+TRANS(FMLS_v, do_fp3_vector, a, f_vector_fmls)
+
/*
* Advanced SIMD scalar/vector x indexed element
*/
@@ -5116,6 +5130,64 @@ static bool do_fp3_scalar_idx(DisasContext *s, arg_rrx_e
*a, const FPScalar *f)
TRANS(FMUL_si, do_fp3_scalar_idx, a, _scalar_fmul)
TRANS(FMULX_si, do_fp3_scalar_idx, a, _scalar_fmulx)
+static bool do_fmla_scalar_idx(DisasContext *s, arg_rrx_e *a, bool neg)
+{
+switch (a->esz) {
+case MO_64:
+if (fp_access_check(s)) {
+TCGv_i64 t0 = read_fp_dreg(s, a->rd);
+TCGv_i64 t1 = read_fp_dreg(s, a->rn);
+TCGv_i64 t2 = tcg_temp_new_i64();
+
+read_vec_element(s, t2, a->rm, a->idx, MO_64);
+if (neg) {
+gen_vfp_negd(t1, t1);
+}
+gen_helper_vfp_muladdd(t0, t1, t2, t0,