1
From 63eb4e807f53c966897628cf93a4fa977d649226 Mon Sep 17 00:00:00 2001
2
From: Peter Maydell <peter.maydell@linaro.org>
3
Date: Fri, 31 Jan 2014 14:47:37 +0000
4
Subject: [PATCH 137/158] target-arm: A64: Add integer ops from SIMD 3-same
7
Add some of the integer operations in the SIMD 3-same group:
8
specifically, the comparisons, addition and subtraction.
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <rth@twiddle.net>
13
target-arm/translate-a64.c | 165 ++++++++++++++++++++++++++++++++++++++++++++-
14
1 file changed, 164 insertions(+), 1 deletion(-)
16
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
17
index aa53ddc..9e7401c 100644
18
--- a/target-arm/translate-a64.c
19
+++ b/target-arm/translate-a64.c
20
@@ -72,6 +72,9 @@ typedef struct AArch64DecodeTable {
21
AArch64DecodeFn *disas_fn;
24
+/* Function prototype for gen_ functions for calling Neon helpers */
25
+typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
27
/* initialize TCG globals. */
28
void a64_translate_init(void)
30
@@ -787,6 +790,25 @@ static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
34
+static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
35
+ int destidx, int element, TCGMemOp memop)
37
+ int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
40
+ tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);
43
+ tcg_gen_st16_i32(tcg_src, cpu_env, vect_off);
46
+ tcg_gen_st_i32(tcg_src, cpu_env, vect_off);
49
+ g_assert_not_reached();
53
/* Clear the high 64 bits of a 128 bit vector (in general non-quad
54
* vector ops all need to do this).
56
@@ -6012,7 +6034,148 @@ static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
57
/* Integer op subgroup of C3.6.16. */
58
static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
60
- unsupported_encoding(s, insn);
61
+ int is_q = extract32(insn, 30, 1);
62
+ int u = extract32(insn, 29, 1);
63
+ int size = extract32(insn, 22, 2);
64
+ int opcode = extract32(insn, 11, 5);
65
+ int rm = extract32(insn, 16, 5);
66
+ int rn = extract32(insn, 5, 5);
67
+ int rd = extract32(insn, 0, 5);
71
+ case 0x13: /* MUL, PMUL */
72
+ if (u && size != 0) {
73
+ unallocated_encoding(s);
77
+ case 0x0: /* SHADD, UHADD */
78
+ case 0x2: /* SRHADD, URHADD */
79
+ case 0x4: /* SHSUB, UHSUB */
80
+ case 0xc: /* SMAX, UMAX */
81
+ case 0xd: /* SMIN, UMIN */
82
+ case 0xe: /* SABD, UABD */
83
+ case 0xf: /* SABA, UABA */
84
+ case 0x12: /* MLA, MLS */
86
+ unallocated_encoding(s);
89
+ unsupported_encoding(s, insn);
91
+ case 0x1: /* SQADD */
92
+ case 0x5: /* SQSUB */
93
+ case 0x8: /* SSHL, USHL */
94
+ case 0x9: /* SQSHL, UQSHL */
95
+ case 0xa: /* SRSHL, URSHL */
96
+ case 0xb: /* SQRSHL, UQRSHL */
97
+ if (size == 3 && !is_q) {
98
+ unallocated_encoding(s);
101
+ unsupported_encoding(s, insn);
103
+ case 0x16: /* SQDMULH, SQRDMULH */
104
+ if (size == 0 || size == 3) {
105
+ unallocated_encoding(s);
108
+ unsupported_encoding(s, insn);
111
+ if (size == 3 && !is_q) {
112
+ unallocated_encoding(s);
119
+ for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
120
+ TCGv_i64 tcg_op1 = tcg_temp_new_i64();
121
+ TCGv_i64 tcg_op2 = tcg_temp_new_i64();
122
+ TCGv_i64 tcg_res = tcg_temp_new_i64();
124
+ read_vec_element(s, tcg_op1, rn, pass, MO_64);
125
+ read_vec_element(s, tcg_op2, rm, pass, MO_64);
127
+ handle_3same_64(s, opcode, u, tcg_res, tcg_op1, tcg_op2);
129
+ write_vec_element(s, tcg_res, rd, pass, MO_64);
131
+ tcg_temp_free_i64(tcg_res);
132
+ tcg_temp_free_i64(tcg_op1);
133
+ tcg_temp_free_i64(tcg_op2);
136
+ for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
137
+ TCGv_i32 tcg_op1 = tcg_temp_new_i32();
138
+ TCGv_i32 tcg_op2 = tcg_temp_new_i32();
139
+ TCGv_i32 tcg_res = tcg_temp_new_i32();
140
+ NeonGenTwoOpFn *genfn;
142
+ read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
143
+ read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
146
+ case 0x6: /* CMGT, CMHI */
148
+ static NeonGenTwoOpFn * const fns[3][2] = {
149
+ { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_u8 },
150
+ { gen_helper_neon_cgt_s16, gen_helper_neon_cgt_u16 },
151
+ { gen_helper_neon_cgt_s32, gen_helper_neon_cgt_u32 },
153
+ genfn = fns[size][u];
156
+ case 0x7: /* CMGE, CMHS */
158
+ static NeonGenTwoOpFn * const fns[3][2] = {
159
+ { gen_helper_neon_cge_s8, gen_helper_neon_cge_u8 },
160
+ { gen_helper_neon_cge_s16, gen_helper_neon_cge_u16 },
161
+ { gen_helper_neon_cge_s32, gen_helper_neon_cge_u32 },
163
+ genfn = fns[size][u];
166
+ case 0x10: /* ADD, SUB */
168
+ static NeonGenTwoOpFn * const fns[3][2] = {
169
+ { gen_helper_neon_add_u8, gen_helper_neon_sub_u8 },
170
+ { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
171
+ { tcg_gen_add_i32, tcg_gen_sub_i32 },
173
+ genfn = fns[size][u];
176
+ case 0x11: /* CMTST, CMEQ */
178
+ static NeonGenTwoOpFn * const fns[3][2] = {
179
+ { gen_helper_neon_tst_u8, gen_helper_neon_ceq_u8 },
180
+ { gen_helper_neon_tst_u16, gen_helper_neon_ceq_u16 },
181
+ { gen_helper_neon_tst_u32, gen_helper_neon_ceq_u32 },
183
+ genfn = fns[size][u];
187
+ g_assert_not_reached();
190
+ genfn(tcg_res, tcg_op1, tcg_op2);
192
+ write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
194
+ tcg_temp_free_i32(tcg_res);
195
+ tcg_temp_free_i32(tcg_op1);
196
+ tcg_temp_free_i32(tcg_op2);
201
+ clear_vec_high(s, rd);
205
/* C3.6.16 AdvSIMD three same