diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2018-03-02 10:45:42 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-03-02 11:03:45 +0000 |
commit | e7186d822955c351e4aac504380f82217c670321 (patch) | |
tree | 0ce6d0554356968d9caedb13dd12561a47afd687 /target/arm/translate-a64.c | |
parent | d9061ec3d27eb940402a7eafee3fb77ce1146ad4 (diff) | |
download | qemu-e7186d822955c351e4aac504380f82217c670321.tar.gz |
target/arm: Decode aa64 armv8.1 three same extra
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20180228193125.20577-6-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/translate-a64.c')
-rw-r--r-- | target/arm/translate-a64.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 746ab0e63a..ae16313eb0 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -701,6 +701,18 @@ static void gen_gvec_op3(DisasContext *s, bool is_q, int rd, vec_full_reg_size(s), gvec_op); } +/* Expand a 3-operand + env pointer operation using + * an out-of-line helper. + */ +static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd, + int rn, int rm, gen_helper_gvec_3_ptr *fn) +{ + tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd), + vec_full_reg_offset(s, rn), + vec_full_reg_offset(s, rm), cpu_env, + is_q ? 16 : 8, vec_full_reg_size(s), 0, fn); +} + /* Set ZF and NF based on a 64 bit result. This is alas fiddlier * than the 32 bit equivalent. */ @@ -10789,6 +10801,76 @@ static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn) clear_vec_high(s, is_q, rd); } +/* AdvSIMD three same extra + * 31 30 29 28 24 23 22 21 20 16 15 14 11 10 9 5 4 0 + * +---+---+---+-----------+------+---+------+---+--------+---+----+----+ + * | 0 | Q | U | 0 1 1 1 0 | size | 0 | Rm | 1 | opcode | 1 | Rn | Rd | + * +---+---+---+-----------+------+---+------+---+--------+---+----+----+ + */ +static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn) +{ + int rd = extract32(insn, 0, 5); + int rn = extract32(insn, 5, 5); + int opcode = extract32(insn, 11, 4); + int rm = extract32(insn, 16, 5); + int size = extract32(insn, 22, 2); + bool u = extract32(insn, 29, 1); + bool is_q = extract32(insn, 30, 1); + int feature; + + switch (u * 16 + opcode) { + case 0x10: /* SQRDMLAH (vector) */ + case 0x11: /* SQRDMLSH (vector) */ + if (size != 1 && size != 2) { + unallocated_encoding(s); + return; + } + feature = ARM_FEATURE_V8_RDM; + break; + default: + unallocated_encoding(s); + return; + } + if (!arm_dc_feature(s, feature)) { + unallocated_encoding(s); + return; + } + if (!fp_access_check(s)) { + return; + } + + switch (opcode) { + case 0x0: /* SQRDMLAH (vector) */ + switch (size) { + case 1: + gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16); + break; + case 2: + gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32); + break; + default: + g_assert_not_reached(); + } + return; + + case 0x1: /* SQRDMLSH (vector) */ + switch (size) { + case 1: + gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16); + break; + case 2: + gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32); + break; + default: + g_assert_not_reached(); + } + return; + + default: + g_assert_not_reached(); + } +} + static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q, int size, int rn, int rd) { @@ -12869,6 +12951,7 @@ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn) static const AArch64DecodeTable data_proc_simd[] = { /* pattern , mask , fn */ { 0x0e200400, 0x9f200400, disas_simd_three_reg_same }, + { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra }, { 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff }, { 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc }, { 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes }, |