1
From b163e0bf39556ed5bb85495aa696f8efaf0f61d1 Mon Sep 17 00:00:00 2001
2
From: Michael Matz <matz@suse.de>
3
Date: Fri, 31 Jan 2014 14:47:31 +0000
4
Subject: [PATCH 117/158] target-arm: A64: Add SIMD ZIP/UZP/TRN
6
Add support for the SIMD ZIP/UZIP/TRN instruction group
9
Signed-off-by: Michael Matz <matz@suse.de>
10
[PMM: use new do_vec_get/set etc functions and generally update to new
11
codebase standards; refactor to pull per-element loop outside switch]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <rth@twiddle.net>
15
target-arm/translate-a64.c | 76 +++++++++++++++++++++++++++++++++++++++++++++-
16
1 file changed, 75 insertions(+), 1 deletion(-)
18
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
19
index 7a6b00a..59e2a85 100644
20
--- a/target-arm/translate-a64.c
21
+++ b/target-arm/translate-a64.c
22
@@ -4806,7 +4806,81 @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
24
static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
26
- unsupported_encoding(s, insn);
27
+ int rd = extract32(insn, 0, 5);
28
+ int rn = extract32(insn, 5, 5);
29
+ int rm = extract32(insn, 16, 5);
30
+ int size = extract32(insn, 22, 2);
31
+ /* opc field bits [1:0] indicate ZIP/UZP/TRN;
32
+ * bit 2 indicates 1 vs 2 variant of the insn.
34
+ int opcode = extract32(insn, 12, 2);
35
+ bool part = extract32(insn, 14, 1);
36
+ bool is_q = extract32(insn, 30, 1);
37
+ int esize = 8 << size;
39
+ int datasize = is_q ? 128 : 64;
40
+ int elements = datasize / esize;
41
+ TCGv_i64 tcg_res, tcg_resl, tcg_resh;
43
+ if (opcode == 0 || (size == 3 && !is_q)) {
44
+ unallocated_encoding(s);
48
+ tcg_resl = tcg_const_i64(0);
49
+ tcg_resh = tcg_const_i64(0);
50
+ tcg_res = tcg_temp_new_i64();
52
+ for (i = 0; i < elements; i++) {
54
+ case 1: /* UZP1/2 */
56
+ int midpoint = elements / 2;
58
+ read_vec_element(s, tcg_res, rn, 2 * i + part, size);
60
+ read_vec_element(s, tcg_res, rm,
61
+ 2 * (i - midpoint) + part, size);
65
+ case 2: /* TRN1/2 */
67
+ read_vec_element(s, tcg_res, rm, (i & ~1) + part, size);
69
+ read_vec_element(s, tcg_res, rn, (i & ~1) + part, size);
72
+ case 3: /* ZIP1/2 */
74
+ int base = part * elements / 2;
76
+ read_vec_element(s, tcg_res, rm, base + (i >> 1), size);
78
+ read_vec_element(s, tcg_res, rn, base + (i >> 1), size);
83
+ g_assert_not_reached();
88
+ tcg_gen_shli_i64(tcg_res, tcg_res, ofs);
89
+ tcg_gen_or_i64(tcg_resl, tcg_resl, tcg_res);
91
+ tcg_gen_shli_i64(tcg_res, tcg_res, ofs - 64);
92
+ tcg_gen_or_i64(tcg_resh, tcg_resh, tcg_res);
96
+ tcg_temp_free_i64(tcg_res);
98
+ write_vec_element(s, tcg_resl, rd, 0, MO_64);
99
+ tcg_temp_free_i64(tcg_resl);
100
+ write_vec_element(s, tcg_resh, rd, 1, MO_64);
101
+ tcg_temp_free_i64(tcg_resh);
104
/* C3.6.4 AdvSIMD across lanes