Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/arm/cpu.h | 5 ++++ target/arm/translate-a64.c | 49 +++++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 47238e4245..15085a94ff 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3305,6 +3305,11 @@ static inline bool isar_feature_aa64_dp(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0; } +static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0; +} + static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0; diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index e002251ac6..d2ee811489 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -10891,9 +10891,26 @@ static void disas_simd_3same_float(DisasContext *s, uint32_t insn) if (!fp_access_check(s)) { return; } - handle_3same_float(s, size, elements, fpopcode, rd, rn, rm); return; + + 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)) { + gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, + extract32(insn, 29, 1), + extract32(insn, 23, 1) + ? gen_helper_gvec_fmlsl_h + : gen_helper_gvec_fmlal_h); + } + return; + default: unallocated_encoding(s); return; @@ -12724,6 +12741,17 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) } is_fp = 2; break; + case 0x00: /* FMLAL */ + case 0x04: /* FMLSL */ + case 0x18: /* FMLAL2 */ + case 0x1c: /* FMLSL2 */ + if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_fhm, s)) { + unallocated_encoding(s); + return; + } + size = MO_16; + is_fp = 3; + break; default: unallocated_encoding(s); return; @@ -12765,6 +12793,9 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) } break; + case 3: /* other fp, size already set and verified. */ + break; + default: /* integer */ switch (size) { case MO_8: @@ -12834,6 +12865,22 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) tcg_temp_free_ptr(fpst); } return; + + case 0x00: /* FMLAL */ + case 0x04: /* FMLSL */ + case 0x18: /* FMLAL2 */ + case 0x1c: /* FMLSL2 */ + { + int data = (index << 1) | u; + tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), fpst, + is_q ? 16 : 8, vec_full_reg_size(s), data, + opcode & 4 ? gen_helper_gvec_fmlsl_idx_h + : gen_helper_gvec_fmlal_idx_h); + tcg_temp_free_ptr(fpst); + } + return; } if (size == 3) { -- 2.17.2