Signed-off-by: Richard Henderson
---
target/arm/tcg/a64.decode | 10 +++
target/arm/tcg/translate-a64.c | 144 ++---
2 files changed, 51 insertions(+), 103 deletions(-)
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index 16e9675335..9aa4fb9bd0 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -797,6 +797,11 @@ 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
+FMLAL_v 0.00 1110 001 . 11101 1 . . @qrrr_h
+FMLSL_v 0.00 1110 101 . 11101 1 . . @qrrr_h
+FMLAL2_v0.10 1110 001 . 11001 1 . . @qrrr_h
+FMLSL2_v0.10 1110 101 . 11001 1 . . @qrrr_h
+
FCMEQ_v 0.00 1110 010 . 00100 1 . . @qrrr_h
FCMEQ_v 0.00 1110 0.1 . 11100 1 . . @qrrr_sd
@@ -877,3 +882,8 @@ 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
+
+FMLAL_vi0.00 10 .. . 0 . . @qrrx_h
+FMLSL_vi0.00 10 .. 0100 . 0 . . @qrrx_h
+FMLAL2_vi 0.10 10 .. 1000 . 0 . . @qrrx_h
+FMLSL2_vi 0.10 10 .. 1100 . 0 . . @qrrx_h
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index be63f46247..a082ce8441 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -5257,6 +5257,24 @@ static gen_helper_gvec_3_ptr * const f_vector_fminnmp[3]
= {
};
TRANS(FMINNMP_v, do_fp3_vector, a, f_vector_fminnmp)
+static bool do_fmlal(DisasContext *s, arg_qrrr_e *a, bool is_s, bool is_2)
+{
+if (fp_access_check(s)) {
+int data = (is_2 << 1) | is_s;
+tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
+ vec_full_reg_offset(s, a->rn),
+ vec_full_reg_offset(s, a->rm), tcg_env,
+ a->q ? 16 : 8, vec_full_reg_size(s),
+ data, gen_helper_gvec_fmlal_a64);
+}
+return true;
+}
+
+TRANS_FEAT(FMLAL_v, aa64_fhm, do_fmlal, a, false, false)
+TRANS_FEAT(FMLSL_v, aa64_fhm, do_fmlal, a, true, false)
+TRANS_FEAT(FMLAL2_v, aa64_fhm, do_fmlal, a, false, true)
+TRANS_FEAT(FMLSL2_v, aa64_fhm, do_fmlal, a, true, true)
+
TRANS(ADDP_v, do_gvec_fn3, a, gen_gvec_addp)
TRANS(SMAXP_v, do_gvec_fn3_no64, a, gen_gvec_smaxp)
TRANS(SMINP_v, do_gvec_fn3_no64, a, gen_gvec_sminp)
@@ -5448,6 +5466,24 @@ static bool do_fmla_vector_idx(DisasContext *s,
arg_qrrx_e *a, bool neg)
TRANS(FMLA_vi, do_fmla_vector_idx, a, false)
TRANS(FMLS_vi, do_fmla_vector_idx, a, true)
+static bool do_fmlal_idx(DisasContext *s, arg_qrrx_e *a, bool is_s, bool is_2)
+{
+if (fp_access_check(s)) {
+int data = (a->idx << 2) | (is_2 << 1) | is_s;
+tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, a->rd),
+ vec_full_reg_offset(s, a->rn),
+ vec_full_reg_offset(s, a->rm), tcg_env,
+ a->q ? 16 : 8, vec_full_reg_size(s),
+ data, gen_helper_gvec_fmlal_idx_a64);
+}
+return true;
+}
+
+TRANS_FEAT(FMLAL_vi, aa64_fhm, do_fmlal_idx, a, false, false)
+TRANS_FEAT(FMLSL_vi, aa64_fhm, do_fmlal_idx, a, true, false)
+TRANS_FEAT(FMLAL2_vi, aa64_fhm, do_fmlal_idx, a, false, true)
+TRANS_FEAT(FMLSL2_vi, aa64_fhm, do_fmlal_idx, a, true, true)
+
/*
* Advanced SIMD scalar pairwise
*/
@@ -10905,78 +10941,6 @@ static void disas_simd_3same_logic(DisasContext *s,
uint32_t insn)
}
}
-/* Floating point op subgroup of C3.6.16. */
-static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
-{
-/* For floating point ops, the U, size[1] and opcode bits
- * together indicate the operation. size[0] indicates single
- * or double.
- */
-int fpopcode = extract32(insn, 11, 5)
-| (extract32(insn, 23, 1) << 5)
-| (extract32(insn, 29, 1) << 6);
-int is_q = extract32(insn, 30, 1);
-int size = extract32(insn, 22, 1);
-int rm = extract32(insn, 16, 5);
-int rn = extract32(insn, 5, 5);
-int rd = extract32(insn, 0, 5);
-
-if (size == 1 && !is_q) {
-unallocated_encoding(s);
-return;
-}
-
-switch (fpopcode) {
-case 0x1d: /* FMLAL */
-case 0x3d: /* FMLSL */
-case 0x59: /* FMLAL2 */
-case 0x79: /* FMLSL2 */
-if (size & 1 || !dc_isar_feature(aa64_fhm, s)) {
-unallocated_encoding(s);
-return;
-}
-if (fp_access_check(s)) {
-int is_s = extract32(insn, 23, 1);
-int is_2 = extract32(insn, 29, 1);
-int data = (is_2 << 1)