1
From 245abfd6f5482644b79602292326605d4e3817df Mon Sep 17 00:00:00 2001
2
From: Peter Maydell <peter.maydell@linaro.org>
3
Date: Sat, 8 Feb 2014 14:46:55 +0000
4
Subject: [PATCH 140/158] target-arm: A64: Implement SIMD 3-reg-same shift and
7
Implement the SIMD 3-reg-same instructions SQADD, UQADD,
8
SQSUB, UQSUB, SSHL, USHL, SQSHl, UQSHL, SRSHL, URSHL,
9
SQRSHL, UQRSHL; these are all simple calls to existing
10
Neon helpers. We also enable SSHL, USHL, SRSHL and URSHL
11
for the 3-reg-same-scalar category (but not the others
12
because they can have non-size-64 operands and the
13
scalar_3reg_same function doesn't support that yet.)
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <rth@twiddle.net>
18
target-arm/translate-a64.c | 134 +++++++++++++++++++++++++++++++++++++--------
19
1 file changed, 112 insertions(+), 22 deletions(-)
21
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
22
index 6c1ec1e..e67cdbb 100644
23
--- a/target-arm/translate-a64.c
24
+++ b/target-arm/translate-a64.c
25
@@ -74,6 +74,7 @@ typedef struct AArch64DecodeTable {
27
/* Function prototype for gen_ functions for calling Neon helpers */
28
typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
29
+typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
31
/* initialize TCG globals. */
32
void a64_translate_init(void)
33
@@ -5738,6 +5739,20 @@ static void handle_3same_64(DisasContext *s, int opcode, bool u,
37
+ case 0x1: /* SQADD */
39
+ gen_helper_neon_qadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
41
+ gen_helper_neon_qadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
44
+ case 0x5: /* SQSUB */
46
+ gen_helper_neon_qsub_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
48
+ gen_helper_neon_qsub_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
51
case 0x6: /* CMGT, CMHI */
52
/* 64 bit integer comparison, result = test ? (2^64 - 1) : 0.
53
* We implement this using setcond (test) and then negating.
54
@@ -5760,19 +5775,41 @@ static void handle_3same_64(DisasContext *s, int opcode, bool u,
55
tcg_gen_setcondi_i64(TCG_COND_NE, tcg_rd, tcg_rd, 0);
56
tcg_gen_neg_i64(tcg_rd, tcg_rd);
58
- case 0x10: /* ADD, SUB */
59
+ case 0x8: /* SSHL, USHL */
61
- tcg_gen_sub_i64(tcg_rd, tcg_rn, tcg_rm);
62
+ gen_helper_neon_shl_u64(tcg_rd, tcg_rn, tcg_rm);
64
- tcg_gen_add_i64(tcg_rd, tcg_rn, tcg_rm);
65
+ gen_helper_neon_shl_s64(tcg_rd, tcg_rn, tcg_rm);
68
- case 0x1: /* SQADD */
69
- case 0x5: /* SQSUB */
70
- case 0x8: /* SSHL, USHL */
71
case 0x9: /* SQSHL, UQSHL */
73
+ gen_helper_neon_qshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
75
+ gen_helper_neon_qshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
78
case 0xa: /* SRSHL, URSHL */
80
+ gen_helper_neon_rshl_u64(tcg_rd, tcg_rn, tcg_rm);
82
+ gen_helper_neon_rshl_s64(tcg_rd, tcg_rn, tcg_rm);
85
case 0xb: /* SQRSHL, UQRSHL */
87
+ gen_helper_neon_qrshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
89
+ gen_helper_neon_qrshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
92
+ case 0x10: /* ADD, SUB */
94
+ tcg_gen_sub_i64(tcg_rd, tcg_rn, tcg_rm);
96
+ tcg_gen_add_i64(tcg_rd, tcg_rn, tcg_rm);
100
g_assert_not_reached();
102
@@ -5949,10 +5986,10 @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
104
case 0x1: /* SQADD, UQADD */
105
case 0x5: /* SQSUB, UQSUB */
106
- case 0x8: /* SSHL, USHL */
107
- case 0xa: /* SRSHL, URSHL */
108
unsupported_encoding(s, insn);
110
+ case 0x8: /* SSHL, USHL */
111
+ case 0xa: /* SRSHL, URSHL */
112
case 0x6: /* CMGT, CMHI */
113
case 0x7: /* CMGE, CMHS */
114
case 0x11: /* CMTST, CMEQ */
115
@@ -6621,18 +6658,6 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
117
unsupported_encoding(s, insn);
119
- case 0x1: /* SQADD */
120
- case 0x5: /* SQSUB */
121
- case 0x8: /* SSHL, USHL */
122
- case 0x9: /* SQSHL, UQSHL */
123
- case 0xa: /* SRSHL, URSHL */
124
- case 0xb: /* SQRSHL, UQRSHL */
125
- if (size == 3 && !is_q) {
126
- unallocated_encoding(s);
129
- unsupported_encoding(s, insn);
131
case 0x16: /* SQDMULH, SQRDMULH */
132
if (size == 0 || size == 3) {
133
unallocated_encoding(s);
134
@@ -6670,12 +6695,33 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
135
TCGv_i32 tcg_op1 = tcg_temp_new_i32();
136
TCGv_i32 tcg_op2 = tcg_temp_new_i32();
137
TCGv_i32 tcg_res = tcg_temp_new_i32();
138
- NeonGenTwoOpFn *genfn;
139
+ NeonGenTwoOpFn *genfn = NULL;
140
+ NeonGenTwoOpEnvFn *genenvfn = NULL;
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 0x1: /* SQADD, UQADD */
148
+ static NeonGenTwoOpEnvFn * const fns[3][2] = {
149
+ { gen_helper_neon_qadd_s8, gen_helper_neon_qadd_u8 },
150
+ { gen_helper_neon_qadd_s16, gen_helper_neon_qadd_u16 },
151
+ { gen_helper_neon_qadd_s32, gen_helper_neon_qadd_u32 },
153
+ genenvfn = fns[size][u];
156
+ case 0x5: /* SQSUB, UQSUB */
158
+ static NeonGenTwoOpEnvFn * const fns[3][2] = {
159
+ { gen_helper_neon_qsub_s8, gen_helper_neon_qsub_u8 },
160
+ { gen_helper_neon_qsub_s16, gen_helper_neon_qsub_u16 },
161
+ { gen_helper_neon_qsub_s32, gen_helper_neon_qsub_u32 },
163
+ genenvfn = fns[size][u];
166
case 0x6: /* CMGT, CMHI */
168
static NeonGenTwoOpFn * const fns[3][2] = {
169
@@ -6696,6 +6742,46 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
170
genfn = fns[size][u];
173
+ case 0x8: /* SSHL, USHL */
175
+ static NeonGenTwoOpFn * const fns[3][2] = {
176
+ { gen_helper_neon_shl_s8, gen_helper_neon_shl_u8 },
177
+ { gen_helper_neon_shl_s16, gen_helper_neon_shl_u16 },
178
+ { gen_helper_neon_shl_s32, gen_helper_neon_shl_u32 },
180
+ genfn = fns[size][u];
183
+ case 0x9: /* SQSHL, UQSHL */
185
+ static NeonGenTwoOpEnvFn * const fns[3][2] = {
186
+ { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
187
+ { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
188
+ { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
190
+ genenvfn = fns[size][u];
193
+ case 0xa: /* SRSHL, URSHL */
195
+ static NeonGenTwoOpFn * const fns[3][2] = {
196
+ { gen_helper_neon_rshl_s8, gen_helper_neon_rshl_u8 },
197
+ { gen_helper_neon_rshl_s16, gen_helper_neon_rshl_u16 },
198
+ { gen_helper_neon_rshl_s32, gen_helper_neon_rshl_u32 },
200
+ genfn = fns[size][u];
203
+ case 0xb: /* SQRSHL, UQRSHL */
205
+ static NeonGenTwoOpEnvFn * const fns[3][2] = {
206
+ { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
207
+ { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
208
+ { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
210
+ genenvfn = fns[size][u];
213
case 0x10: /* ADD, SUB */
215
static NeonGenTwoOpFn * const fns[3][2] = {
216
@@ -6720,7 +6806,11 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
217
g_assert_not_reached();
220
- genfn(tcg_res, tcg_op1, tcg_op2);
222
+ genenvfn(tcg_res, cpu_env, tcg_op1, tcg_op2);
224
+ genfn(tcg_res, tcg_op1, tcg_op2);
227
write_vec_element_i32(s, tcg_res, rd, pass, MO_32);