]> git.proxmox.com Git - mirror_qemu.git/blame - target-arm/translate.c
Merge remote-tracking branch 'sstabellini/tags/xen-20161122-tag' into staging
[mirror_qemu.git] / target-arm / translate.c
CommitLineData
2c0262af
FB
1/*
2 * ARM translation
5fafdf24 3 *
2c0262af 4 * Copyright (c) 2003 Fabrice Bellard
9ee6e8bb 5 * Copyright (c) 2005-2007 CodeSourcery
18c9b560 6 * Copyright (c) 2007 OpenedHand, Ltd.
2c0262af
FB
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
8167ee88 19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2c0262af 20 */
74c21bd0 21#include "qemu/osdep.h"
2c0262af
FB
22
23#include "cpu.h"
ccd38087 24#include "internals.h"
76cad711 25#include "disas/disas.h"
63c91552 26#include "exec/exec-all.h"
57fec1fe 27#include "tcg-op.h"
1de7afc9 28#include "qemu/log.h"
534df156 29#include "qemu/bitops.h"
1d854765 30#include "arm_ldst.h"
19a6e31c 31#include "exec/semihost.h"
1497c961 32
2ef6175a
RH
33#include "exec/helper-proto.h"
34#include "exec/helper-gen.h"
2c0262af 35
a7e30d84 36#include "trace-tcg.h"
508127e2 37#include "exec/log.h"
a7e30d84
LV
38
39
2b51668f
PM
40#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
41#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
be5e7a76 42/* currently all emulated v5 cores are also v5TE, so don't bother */
2b51668f 43#define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
9ee6e8bb 44#define ENABLE_ARCH_5J 0
2b51668f
PM
45#define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
46#define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
47#define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
48#define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
49#define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
b5ff1b31 50
86753403 51#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
b5ff1b31 52
f570c61e 53#include "translate.h"
e12ce78d 54
b5ff1b31
FB
55#if defined(CONFIG_USER_ONLY)
56#define IS_USER(s) 1
57#else
58#define IS_USER(s) (s->user)
59#endif
60
1bcea73e 61TCGv_env cpu_env;
ad69471c 62/* We reuse the same 64-bit temporaries for efficiency. */
a7812ae4 63static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
155c3eac 64static TCGv_i32 cpu_R[16];
78bcaa3e
RH
65TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
66TCGv_i64 cpu_exclusive_addr;
67TCGv_i64 cpu_exclusive_val;
ad69471c 68
b26eefb6 69/* FIXME: These should be removed. */
39d5492a 70static TCGv_i32 cpu_F0s, cpu_F1s;
a7812ae4 71static TCGv_i64 cpu_F0d, cpu_F1d;
b26eefb6 72
022c62cb 73#include "exec/gen-icount.h"
2e70f6ef 74
155c3eac
FN
75static const char *regnames[] =
76 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
77 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
78
b26eefb6
PB
79/* initialize TCG globals. */
80void arm_translate_init(void)
81{
155c3eac
FN
82 int i;
83
a7812ae4 84 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
7c255043 85 tcg_ctx.tcg_env = cpu_env;
a7812ae4 86
155c3eac 87 for (i = 0; i < 16; i++) {
e1ccc054 88 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
0ecb72a5 89 offsetof(CPUARMState, regs[i]),
155c3eac
FN
90 regnames[i]);
91 }
e1ccc054
RH
92 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
93 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
94 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
95 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
66c374de 96
e1ccc054 97 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 98 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
e1ccc054 99 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 100 offsetof(CPUARMState, exclusive_val), "exclusive_val");
155c3eac 101
14ade10f 102 a64_translate_init();
b26eefb6
PB
103}
104
579d21cc
PM
105static inline ARMMMUIdx get_a32_user_mem_index(DisasContext *s)
106{
107 /* Return the mmu_idx to use for A32/T32 "unprivileged load/store"
108 * insns:
109 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
110 * otherwise, access as if at PL0.
111 */
112 switch (s->mmu_idx) {
113 case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
114 case ARMMMUIdx_S12NSE0:
115 case ARMMMUIdx_S12NSE1:
116 return ARMMMUIdx_S12NSE0;
117 case ARMMMUIdx_S1E3:
118 case ARMMMUIdx_S1SE0:
119 case ARMMMUIdx_S1SE1:
120 return ARMMMUIdx_S1SE0;
121 case ARMMMUIdx_S2NS:
122 default:
123 g_assert_not_reached();
124 }
125}
126
39d5492a 127static inline TCGv_i32 load_cpu_offset(int offset)
d9ba4830 128{
39d5492a 129 TCGv_i32 tmp = tcg_temp_new_i32();
d9ba4830
PB
130 tcg_gen_ld_i32(tmp, cpu_env, offset);
131 return tmp;
132}
133
0ecb72a5 134#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
d9ba4830 135
39d5492a 136static inline void store_cpu_offset(TCGv_i32 var, int offset)
d9ba4830
PB
137{
138 tcg_gen_st_i32(var, cpu_env, offset);
7d1b0095 139 tcg_temp_free_i32(var);
d9ba4830
PB
140}
141
142#define store_cpu_field(var, name) \
0ecb72a5 143 store_cpu_offset(var, offsetof(CPUARMState, name))
d9ba4830 144
b26eefb6 145/* Set a variable to the value of a CPU register. */
39d5492a 146static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
b26eefb6
PB
147{
148 if (reg == 15) {
149 uint32_t addr;
b90372ad 150 /* normally, since we updated PC, we need only to add one insn */
b26eefb6
PB
151 if (s->thumb)
152 addr = (long)s->pc + 2;
153 else
154 addr = (long)s->pc + 4;
155 tcg_gen_movi_i32(var, addr);
156 } else {
155c3eac 157 tcg_gen_mov_i32(var, cpu_R[reg]);
b26eefb6
PB
158 }
159}
160
161/* Create a new temporary and set it to the value of a CPU register. */
39d5492a 162static inline TCGv_i32 load_reg(DisasContext *s, int reg)
b26eefb6 163{
39d5492a 164 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
165 load_reg_var(s, tmp, reg);
166 return tmp;
167}
168
169/* Set a CPU register. The source must be a temporary and will be
170 marked as dead. */
39d5492a 171static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
b26eefb6
PB
172{
173 if (reg == 15) {
9b6a3ea7
PM
174 /* In Thumb mode, we must ignore bit 0.
175 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
176 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
177 * We choose to ignore [1:0] in ARM mode for all architecture versions.
178 */
179 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
b26eefb6
PB
180 s->is_jmp = DISAS_JUMP;
181 }
155c3eac 182 tcg_gen_mov_i32(cpu_R[reg], var);
7d1b0095 183 tcg_temp_free_i32(var);
b26eefb6
PB
184}
185
b26eefb6 186/* Value extensions. */
86831435
PB
187#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
188#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
b26eefb6
PB
189#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
190#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
191
1497c961
PB
192#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
193#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
8f01245e 194
b26eefb6 195
39d5492a 196static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
b75263d6 197{
39d5492a 198 TCGv_i32 tmp_mask = tcg_const_i32(mask);
1ce94f81 199 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
b75263d6
JR
200 tcg_temp_free_i32(tmp_mask);
201}
d9ba4830
PB
202/* Set NZCV flags from the high 4 bits of var. */
203#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
204
d4a2dc67 205static void gen_exception_internal(int excp)
d9ba4830 206{
d4a2dc67
PM
207 TCGv_i32 tcg_excp = tcg_const_i32(excp);
208
209 assert(excp_is_internal(excp));
210 gen_helper_exception_internal(cpu_env, tcg_excp);
211 tcg_temp_free_i32(tcg_excp);
212}
213
73710361 214static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
d4a2dc67
PM
215{
216 TCGv_i32 tcg_excp = tcg_const_i32(excp);
217 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
73710361 218 TCGv_i32 tcg_el = tcg_const_i32(target_el);
d4a2dc67 219
73710361
GB
220 gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
221 tcg_syn, tcg_el);
222
223 tcg_temp_free_i32(tcg_el);
d4a2dc67
PM
224 tcg_temp_free_i32(tcg_syn);
225 tcg_temp_free_i32(tcg_excp);
d9ba4830
PB
226}
227
50225ad0
PM
228static void gen_ss_advance(DisasContext *s)
229{
230 /* If the singlestep state is Active-not-pending, advance to
231 * Active-pending.
232 */
233 if (s->ss_active) {
234 s->pstate_ss = 0;
235 gen_helper_clear_pstate_ss(cpu_env);
236 }
237}
238
239static void gen_step_complete_exception(DisasContext *s)
240{
241 /* We just completed step of an insn. Move from Active-not-pending
242 * to Active-pending, and then also take the swstep exception.
243 * This corresponds to making the (IMPDEF) choice to prioritize
244 * swstep exceptions over asynchronous exceptions taken to an exception
245 * level where debug is disabled. This choice has the advantage that
246 * we do not need to maintain internal state corresponding to the
247 * ISV/EX syndrome bits between completion of the step and generation
248 * of the exception, and our syndrome information is always correct.
249 */
250 gen_ss_advance(s);
73710361
GB
251 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
252 default_exception_el(s));
50225ad0
PM
253 s->is_jmp = DISAS_EXC;
254}
255
39d5492a 256static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
3670669c 257{
39d5492a
PM
258 TCGv_i32 tmp1 = tcg_temp_new_i32();
259 TCGv_i32 tmp2 = tcg_temp_new_i32();
22478e79
AZ
260 tcg_gen_ext16s_i32(tmp1, a);
261 tcg_gen_ext16s_i32(tmp2, b);
3670669c 262 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
7d1b0095 263 tcg_temp_free_i32(tmp2);
3670669c
PB
264 tcg_gen_sari_i32(a, a, 16);
265 tcg_gen_sari_i32(b, b, 16);
266 tcg_gen_mul_i32(b, b, a);
267 tcg_gen_mov_i32(a, tmp1);
7d1b0095 268 tcg_temp_free_i32(tmp1);
3670669c
PB
269}
270
271/* Byteswap each halfword. */
39d5492a 272static void gen_rev16(TCGv_i32 var)
3670669c 273{
39d5492a 274 TCGv_i32 tmp = tcg_temp_new_i32();
3670669c
PB
275 tcg_gen_shri_i32(tmp, var, 8);
276 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
277 tcg_gen_shli_i32(var, var, 8);
278 tcg_gen_andi_i32(var, var, 0xff00ff00);
279 tcg_gen_or_i32(var, var, tmp);
7d1b0095 280 tcg_temp_free_i32(tmp);
3670669c
PB
281}
282
283/* Byteswap low halfword and sign extend. */
39d5492a 284static void gen_revsh(TCGv_i32 var)
3670669c 285{
1a855029
AJ
286 tcg_gen_ext16u_i32(var, var);
287 tcg_gen_bswap16_i32(var, var);
288 tcg_gen_ext16s_i32(var, var);
3670669c
PB
289}
290
291/* Unsigned bitfield extract. */
39d5492a 292static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask)
3670669c
PB
293{
294 if (shift)
295 tcg_gen_shri_i32(var, var, shift);
296 tcg_gen_andi_i32(var, var, mask);
297}
298
299/* Signed bitfield extract. */
39d5492a 300static void gen_sbfx(TCGv_i32 var, int shift, int width)
3670669c
PB
301{
302 uint32_t signbit;
303
304 if (shift)
305 tcg_gen_sari_i32(var, var, shift);
306 if (shift + width < 32) {
307 signbit = 1u << (width - 1);
308 tcg_gen_andi_i32(var, var, (1u << width) - 1);
309 tcg_gen_xori_i32(var, var, signbit);
310 tcg_gen_subi_i32(var, var, signbit);
311 }
312}
313
838fa72d 314/* Return (b << 32) + a. Mark inputs as dead */
39d5492a 315static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
3670669c 316{
838fa72d
AJ
317 TCGv_i64 tmp64 = tcg_temp_new_i64();
318
319 tcg_gen_extu_i32_i64(tmp64, b);
7d1b0095 320 tcg_temp_free_i32(b);
838fa72d
AJ
321 tcg_gen_shli_i64(tmp64, tmp64, 32);
322 tcg_gen_add_i64(a, tmp64, a);
323
324 tcg_temp_free_i64(tmp64);
325 return a;
326}
327
328/* Return (b << 32) - a. Mark inputs as dead. */
39d5492a 329static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
838fa72d
AJ
330{
331 TCGv_i64 tmp64 = tcg_temp_new_i64();
332
333 tcg_gen_extu_i32_i64(tmp64, b);
7d1b0095 334 tcg_temp_free_i32(b);
838fa72d
AJ
335 tcg_gen_shli_i64(tmp64, tmp64, 32);
336 tcg_gen_sub_i64(a, tmp64, a);
337
338 tcg_temp_free_i64(tmp64);
339 return a;
3670669c
PB
340}
341
5e3f878a 342/* 32x32->64 multiply. Marks inputs as dead. */
39d5492a 343static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 344{
39d5492a
PM
345 TCGv_i32 lo = tcg_temp_new_i32();
346 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 347 TCGv_i64 ret;
5e3f878a 348
831d7fe8 349 tcg_gen_mulu2_i32(lo, hi, a, b);
7d1b0095 350 tcg_temp_free_i32(a);
7d1b0095 351 tcg_temp_free_i32(b);
831d7fe8
RH
352
353 ret = tcg_temp_new_i64();
354 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
355 tcg_temp_free_i32(lo);
356 tcg_temp_free_i32(hi);
831d7fe8
RH
357
358 return ret;
5e3f878a
PB
359}
360
39d5492a 361static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 362{
39d5492a
PM
363 TCGv_i32 lo = tcg_temp_new_i32();
364 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 365 TCGv_i64 ret;
5e3f878a 366
831d7fe8 367 tcg_gen_muls2_i32(lo, hi, a, b);
7d1b0095 368 tcg_temp_free_i32(a);
7d1b0095 369 tcg_temp_free_i32(b);
831d7fe8
RH
370
371 ret = tcg_temp_new_i64();
372 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
373 tcg_temp_free_i32(lo);
374 tcg_temp_free_i32(hi);
831d7fe8
RH
375
376 return ret;
5e3f878a
PB
377}
378
8f01245e 379/* Swap low and high halfwords. */
39d5492a 380static void gen_swap_half(TCGv_i32 var)
8f01245e 381{
39d5492a 382 TCGv_i32 tmp = tcg_temp_new_i32();
8f01245e
PB
383 tcg_gen_shri_i32(tmp, var, 16);
384 tcg_gen_shli_i32(var, var, 16);
385 tcg_gen_or_i32(var, var, tmp);
7d1b0095 386 tcg_temp_free_i32(tmp);
8f01245e
PB
387}
388
b26eefb6
PB
389/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
390 tmp = (t0 ^ t1) & 0x8000;
391 t0 &= ~0x8000;
392 t1 &= ~0x8000;
393 t0 = (t0 + t1) ^ tmp;
394 */
395
39d5492a 396static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 397{
39d5492a 398 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
399 tcg_gen_xor_i32(tmp, t0, t1);
400 tcg_gen_andi_i32(tmp, tmp, 0x8000);
401 tcg_gen_andi_i32(t0, t0, ~0x8000);
402 tcg_gen_andi_i32(t1, t1, ~0x8000);
403 tcg_gen_add_i32(t0, t0, t1);
404 tcg_gen_xor_i32(t0, t0, tmp);
7d1b0095
PM
405 tcg_temp_free_i32(tmp);
406 tcg_temp_free_i32(t1);
b26eefb6
PB
407}
408
409/* Set CF to the top bit of var. */
39d5492a 410static void gen_set_CF_bit31(TCGv_i32 var)
b26eefb6 411{
66c374de 412 tcg_gen_shri_i32(cpu_CF, var, 31);
b26eefb6
PB
413}
414
415/* Set N and Z flags from var. */
39d5492a 416static inline void gen_logic_CC(TCGv_i32 var)
b26eefb6 417{
66c374de
AJ
418 tcg_gen_mov_i32(cpu_NF, var);
419 tcg_gen_mov_i32(cpu_ZF, var);
b26eefb6
PB
420}
421
422/* T0 += T1 + CF. */
39d5492a 423static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 424{
396e467c 425 tcg_gen_add_i32(t0, t0, t1);
66c374de 426 tcg_gen_add_i32(t0, t0, cpu_CF);
b26eefb6
PB
427}
428
e9bb4aa9 429/* dest = T0 + T1 + CF. */
39d5492a 430static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
e9bb4aa9 431{
e9bb4aa9 432 tcg_gen_add_i32(dest, t0, t1);
66c374de 433 tcg_gen_add_i32(dest, dest, cpu_CF);
e9bb4aa9
JR
434}
435
3670669c 436/* dest = T0 - T1 + CF - 1. */
39d5492a 437static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
3670669c 438{
3670669c 439 tcg_gen_sub_i32(dest, t0, t1);
66c374de 440 tcg_gen_add_i32(dest, dest, cpu_CF);
3670669c 441 tcg_gen_subi_i32(dest, dest, 1);
3670669c
PB
442}
443
72485ec4 444/* dest = T0 + T1. Compute C, N, V and Z flags */
39d5492a 445static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 446{
39d5492a 447 TCGv_i32 tmp = tcg_temp_new_i32();
e3482cb8
RH
448 tcg_gen_movi_i32(tmp, 0);
449 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
72485ec4 450 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
72485ec4 451 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
72485ec4
AJ
452 tcg_gen_xor_i32(tmp, t0, t1);
453 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
454 tcg_temp_free_i32(tmp);
455 tcg_gen_mov_i32(dest, cpu_NF);
456}
457
49b4c31e 458/* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
39d5492a 459static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
49b4c31e 460{
39d5492a 461 TCGv_i32 tmp = tcg_temp_new_i32();
49b4c31e
RH
462 if (TCG_TARGET_HAS_add2_i32) {
463 tcg_gen_movi_i32(tmp, 0);
464 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
8c3ac601 465 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
49b4c31e
RH
466 } else {
467 TCGv_i64 q0 = tcg_temp_new_i64();
468 TCGv_i64 q1 = tcg_temp_new_i64();
469 tcg_gen_extu_i32_i64(q0, t0);
470 tcg_gen_extu_i32_i64(q1, t1);
471 tcg_gen_add_i64(q0, q0, q1);
472 tcg_gen_extu_i32_i64(q1, cpu_CF);
473 tcg_gen_add_i64(q0, q0, q1);
474 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
475 tcg_temp_free_i64(q0);
476 tcg_temp_free_i64(q1);
477 }
478 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
479 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
480 tcg_gen_xor_i32(tmp, t0, t1);
481 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
482 tcg_temp_free_i32(tmp);
483 tcg_gen_mov_i32(dest, cpu_NF);
484}
485
72485ec4 486/* dest = T0 - T1. Compute C, N, V and Z flags */
39d5492a 487static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 488{
39d5492a 489 TCGv_i32 tmp;
72485ec4
AJ
490 tcg_gen_sub_i32(cpu_NF, t0, t1);
491 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
492 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
493 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
494 tmp = tcg_temp_new_i32();
495 tcg_gen_xor_i32(tmp, t0, t1);
496 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
497 tcg_temp_free_i32(tmp);
498 tcg_gen_mov_i32(dest, cpu_NF);
499}
500
e77f0832 501/* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
39d5492a 502static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
2de68a49 503{
39d5492a 504 TCGv_i32 tmp = tcg_temp_new_i32();
e77f0832
RH
505 tcg_gen_not_i32(tmp, t1);
506 gen_adc_CC(dest, t0, tmp);
39d5492a 507 tcg_temp_free_i32(tmp);
2de68a49
RH
508}
509
365af80e 510#define GEN_SHIFT(name) \
39d5492a 511static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
365af80e 512{ \
39d5492a 513 TCGv_i32 tmp1, tmp2, tmp3; \
365af80e
AJ
514 tmp1 = tcg_temp_new_i32(); \
515 tcg_gen_andi_i32(tmp1, t1, 0xff); \
516 tmp2 = tcg_const_i32(0); \
517 tmp3 = tcg_const_i32(0x1f); \
518 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
519 tcg_temp_free_i32(tmp3); \
520 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
521 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
522 tcg_temp_free_i32(tmp2); \
523 tcg_temp_free_i32(tmp1); \
524}
525GEN_SHIFT(shl)
526GEN_SHIFT(shr)
527#undef GEN_SHIFT
528
39d5492a 529static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
365af80e 530{
39d5492a 531 TCGv_i32 tmp1, tmp2;
365af80e
AJ
532 tmp1 = tcg_temp_new_i32();
533 tcg_gen_andi_i32(tmp1, t1, 0xff);
534 tmp2 = tcg_const_i32(0x1f);
535 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
536 tcg_temp_free_i32(tmp2);
537 tcg_gen_sar_i32(dest, t0, tmp1);
538 tcg_temp_free_i32(tmp1);
539}
540
39d5492a 541static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
36c91fd1 542{
39d5492a
PM
543 TCGv_i32 c0 = tcg_const_i32(0);
544 TCGv_i32 tmp = tcg_temp_new_i32();
36c91fd1
PM
545 tcg_gen_neg_i32(tmp, src);
546 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
547 tcg_temp_free_i32(c0);
548 tcg_temp_free_i32(tmp);
549}
ad69471c 550
39d5492a 551static void shifter_out_im(TCGv_i32 var, int shift)
b26eefb6 552{
9a119ff6 553 if (shift == 0) {
66c374de 554 tcg_gen_andi_i32(cpu_CF, var, 1);
b26eefb6 555 } else {
66c374de
AJ
556 tcg_gen_shri_i32(cpu_CF, var, shift);
557 if (shift != 31) {
558 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
559 }
9a119ff6 560 }
9a119ff6 561}
b26eefb6 562
9a119ff6 563/* Shift by immediate. Includes special handling for shift == 0. */
39d5492a
PM
564static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
565 int shift, int flags)
9a119ff6
PB
566{
567 switch (shiftop) {
568 case 0: /* LSL */
569 if (shift != 0) {
570 if (flags)
571 shifter_out_im(var, 32 - shift);
572 tcg_gen_shli_i32(var, var, shift);
573 }
574 break;
575 case 1: /* LSR */
576 if (shift == 0) {
577 if (flags) {
66c374de 578 tcg_gen_shri_i32(cpu_CF, var, 31);
9a119ff6
PB
579 }
580 tcg_gen_movi_i32(var, 0);
581 } else {
582 if (flags)
583 shifter_out_im(var, shift - 1);
584 tcg_gen_shri_i32(var, var, shift);
585 }
586 break;
587 case 2: /* ASR */
588 if (shift == 0)
589 shift = 32;
590 if (flags)
591 shifter_out_im(var, shift - 1);
592 if (shift == 32)
593 shift = 31;
594 tcg_gen_sari_i32(var, var, shift);
595 break;
596 case 3: /* ROR/RRX */
597 if (shift != 0) {
598 if (flags)
599 shifter_out_im(var, shift - 1);
f669df27 600 tcg_gen_rotri_i32(var, var, shift); break;
9a119ff6 601 } else {
39d5492a 602 TCGv_i32 tmp = tcg_temp_new_i32();
b6348f29 603 tcg_gen_shli_i32(tmp, cpu_CF, 31);
9a119ff6
PB
604 if (flags)
605 shifter_out_im(var, 0);
606 tcg_gen_shri_i32(var, var, 1);
b26eefb6 607 tcg_gen_or_i32(var, var, tmp);
7d1b0095 608 tcg_temp_free_i32(tmp);
b26eefb6
PB
609 }
610 }
611};
612
39d5492a
PM
613static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
614 TCGv_i32 shift, int flags)
8984bd2e
PB
615{
616 if (flags) {
617 switch (shiftop) {
9ef39277
BS
618 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
619 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
620 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
621 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
8984bd2e
PB
622 }
623 } else {
624 switch (shiftop) {
365af80e
AJ
625 case 0:
626 gen_shl(var, var, shift);
627 break;
628 case 1:
629 gen_shr(var, var, shift);
630 break;
631 case 2:
632 gen_sar(var, var, shift);
633 break;
f669df27
AJ
634 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
635 tcg_gen_rotr_i32(var, var, shift); break;
8984bd2e
PB
636 }
637 }
7d1b0095 638 tcg_temp_free_i32(shift);
8984bd2e
PB
639}
640
6ddbc6e4
PB
641#define PAS_OP(pfx) \
642 switch (op2) { \
643 case 0: gen_pas_helper(glue(pfx,add16)); break; \
644 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
645 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
646 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
647 case 4: gen_pas_helper(glue(pfx,add8)); break; \
648 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
649 }
39d5492a 650static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 651{
a7812ae4 652 TCGv_ptr tmp;
6ddbc6e4
PB
653
654 switch (op1) {
655#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
656 case 1:
a7812ae4 657 tmp = tcg_temp_new_ptr();
0ecb72a5 658 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 659 PAS_OP(s)
b75263d6 660 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
661 break;
662 case 5:
a7812ae4 663 tmp = tcg_temp_new_ptr();
0ecb72a5 664 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 665 PAS_OP(u)
b75263d6 666 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
667 break;
668#undef gen_pas_helper
669#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
670 case 2:
671 PAS_OP(q);
672 break;
673 case 3:
674 PAS_OP(sh);
675 break;
676 case 6:
677 PAS_OP(uq);
678 break;
679 case 7:
680 PAS_OP(uh);
681 break;
682#undef gen_pas_helper
683 }
684}
9ee6e8bb
PB
685#undef PAS_OP
686
6ddbc6e4
PB
687/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
688#define PAS_OP(pfx) \
ed89a2f1 689 switch (op1) { \
6ddbc6e4
PB
690 case 0: gen_pas_helper(glue(pfx,add8)); break; \
691 case 1: gen_pas_helper(glue(pfx,add16)); break; \
692 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
693 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
694 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
695 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
696 }
39d5492a 697static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 698{
a7812ae4 699 TCGv_ptr tmp;
6ddbc6e4 700
ed89a2f1 701 switch (op2) {
6ddbc6e4
PB
702#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
703 case 0:
a7812ae4 704 tmp = tcg_temp_new_ptr();
0ecb72a5 705 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 706 PAS_OP(s)
b75263d6 707 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
708 break;
709 case 4:
a7812ae4 710 tmp = tcg_temp_new_ptr();
0ecb72a5 711 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 712 PAS_OP(u)
b75263d6 713 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
714 break;
715#undef gen_pas_helper
716#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
717 case 1:
718 PAS_OP(q);
719 break;
720 case 2:
721 PAS_OP(sh);
722 break;
723 case 5:
724 PAS_OP(uq);
725 break;
726 case 6:
727 PAS_OP(uh);
728 break;
729#undef gen_pas_helper
730 }
731}
9ee6e8bb
PB
732#undef PAS_OP
733
39fb730a 734/*
6c2c63d3 735 * Generate a conditional based on ARM condition code cc.
39fb730a
AG
736 * This is common between ARM and Aarch64 targets.
737 */
6c2c63d3 738void arm_test_cc(DisasCompare *cmp, int cc)
d9ba4830 739{
6c2c63d3
RH
740 TCGv_i32 value;
741 TCGCond cond;
742 bool global = true;
d9ba4830 743
d9ba4830
PB
744 switch (cc) {
745 case 0: /* eq: Z */
d9ba4830 746 case 1: /* ne: !Z */
6c2c63d3
RH
747 cond = TCG_COND_EQ;
748 value = cpu_ZF;
d9ba4830 749 break;
6c2c63d3 750
d9ba4830 751 case 2: /* cs: C */
d9ba4830 752 case 3: /* cc: !C */
6c2c63d3
RH
753 cond = TCG_COND_NE;
754 value = cpu_CF;
d9ba4830 755 break;
6c2c63d3 756
d9ba4830 757 case 4: /* mi: N */
d9ba4830 758 case 5: /* pl: !N */
6c2c63d3
RH
759 cond = TCG_COND_LT;
760 value = cpu_NF;
d9ba4830 761 break;
6c2c63d3 762
d9ba4830 763 case 6: /* vs: V */
d9ba4830 764 case 7: /* vc: !V */
6c2c63d3
RH
765 cond = TCG_COND_LT;
766 value = cpu_VF;
d9ba4830 767 break;
6c2c63d3 768
d9ba4830 769 case 8: /* hi: C && !Z */
6c2c63d3
RH
770 case 9: /* ls: !C || Z -> !(C && !Z) */
771 cond = TCG_COND_NE;
772 value = tcg_temp_new_i32();
773 global = false;
774 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
775 ZF is non-zero for !Z; so AND the two subexpressions. */
776 tcg_gen_neg_i32(value, cpu_CF);
777 tcg_gen_and_i32(value, value, cpu_ZF);
d9ba4830 778 break;
6c2c63d3 779
d9ba4830 780 case 10: /* ge: N == V -> N ^ V == 0 */
d9ba4830 781 case 11: /* lt: N != V -> N ^ V != 0 */
6c2c63d3
RH
782 /* Since we're only interested in the sign bit, == 0 is >= 0. */
783 cond = TCG_COND_GE;
784 value = tcg_temp_new_i32();
785 global = false;
786 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
d9ba4830 787 break;
6c2c63d3 788
d9ba4830 789 case 12: /* gt: !Z && N == V */
d9ba4830 790 case 13: /* le: Z || N != V */
6c2c63d3
RH
791 cond = TCG_COND_NE;
792 value = tcg_temp_new_i32();
793 global = false;
794 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
795 * the sign bit then AND with ZF to yield the result. */
796 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
797 tcg_gen_sari_i32(value, value, 31);
798 tcg_gen_andc_i32(value, cpu_ZF, value);
d9ba4830 799 break;
6c2c63d3 800
9305eac0
RH
801 case 14: /* always */
802 case 15: /* always */
803 /* Use the ALWAYS condition, which will fold early.
804 * It doesn't matter what we use for the value. */
805 cond = TCG_COND_ALWAYS;
806 value = cpu_ZF;
807 goto no_invert;
808
d9ba4830
PB
809 default:
810 fprintf(stderr, "Bad condition code 0x%x\n", cc);
811 abort();
812 }
6c2c63d3
RH
813
814 if (cc & 1) {
815 cond = tcg_invert_cond(cond);
816 }
817
9305eac0 818 no_invert:
6c2c63d3
RH
819 cmp->cond = cond;
820 cmp->value = value;
821 cmp->value_global = global;
822}
823
824void arm_free_cc(DisasCompare *cmp)
825{
826 if (!cmp->value_global) {
827 tcg_temp_free_i32(cmp->value);
828 }
829}
830
831void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
832{
833 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
834}
835
836void arm_gen_test_cc(int cc, TCGLabel *label)
837{
838 DisasCompare cmp;
839 arm_test_cc(&cmp, cc);
840 arm_jump_cc(&cmp, label);
841 arm_free_cc(&cmp);
d9ba4830 842}
2c0262af 843
b1d8e52e 844static const uint8_t table_logic_cc[16] = {
2c0262af
FB
845 1, /* and */
846 1, /* xor */
847 0, /* sub */
848 0, /* rsb */
849 0, /* add */
850 0, /* adc */
851 0, /* sbc */
852 0, /* rsc */
853 1, /* andl */
854 1, /* xorl */
855 0, /* cmp */
856 0, /* cmn */
857 1, /* orr */
858 1, /* mov */
859 1, /* bic */
860 1, /* mvn */
861};
3b46e624 862
d9ba4830
PB
863/* Set PC and Thumb state from an immediate address. */
864static inline void gen_bx_im(DisasContext *s, uint32_t addr)
99c475ab 865{
39d5492a 866 TCGv_i32 tmp;
99c475ab 867
577bf808 868 s->is_jmp = DISAS_JUMP;
d9ba4830 869 if (s->thumb != (addr & 1)) {
7d1b0095 870 tmp = tcg_temp_new_i32();
d9ba4830 871 tcg_gen_movi_i32(tmp, addr & 1);
0ecb72a5 872 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
7d1b0095 873 tcg_temp_free_i32(tmp);
d9ba4830 874 }
155c3eac 875 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
d9ba4830
PB
876}
877
878/* Set PC and Thumb state from var. var is marked as dead. */
39d5492a 879static inline void gen_bx(DisasContext *s, TCGv_i32 var)
d9ba4830 880{
577bf808 881 s->is_jmp = DISAS_JUMP;
155c3eac
FN
882 tcg_gen_andi_i32(cpu_R[15], var, ~1);
883 tcg_gen_andi_i32(var, var, 1);
884 store_cpu_field(var, thumb);
d9ba4830
PB
885}
886
21aeb343
JR
887/* Variant of store_reg which uses branch&exchange logic when storing
888 to r15 in ARM architecture v7 and above. The source must be a temporary
889 and will be marked as dead. */
7dcc1f89 890static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
21aeb343
JR
891{
892 if (reg == 15 && ENABLE_ARCH_7) {
893 gen_bx(s, var);
894 } else {
895 store_reg(s, reg, var);
896 }
897}
898
be5e7a76
DES
899/* Variant of store_reg which uses branch&exchange logic when storing
900 * to r15 in ARM architecture v5T and above. This is used for storing
901 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
902 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
7dcc1f89 903static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
be5e7a76
DES
904{
905 if (reg == 15 && ENABLE_ARCH_5) {
906 gen_bx(s, var);
907 } else {
908 store_reg(s, reg, var);
909 }
910}
911
e334bd31
PB
912#ifdef CONFIG_USER_ONLY
913#define IS_USER_ONLY 1
914#else
915#define IS_USER_ONLY 0
916#endif
917
08307563
PM
918/* Abstractions of "generate code to do a guest load/store for
919 * AArch32", where a vaddr is always 32 bits (and is zero
920 * extended if we're a 64 bit core) and data is also
921 * 32 bits unless specifically doing a 64 bit access.
922 * These functions work like tcg_gen_qemu_{ld,st}* except
09f78135 923 * that the address argument is TCGv_i32 rather than TCGv.
08307563 924 */
08307563 925
7f5616f5 926static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op)
08307563 927{
7f5616f5
RH
928 TCGv addr = tcg_temp_new();
929 tcg_gen_extu_i32_tl(addr, a32);
930
e334bd31 931 /* Not needed for user-mode BE32, where we use MO_BE instead. */
7f5616f5
RH
932 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
933 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
e334bd31 934 }
7f5616f5 935 return addr;
08307563
PM
936}
937
7f5616f5
RH
938static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
939 int index, TCGMemOp opc)
08307563 940{
7f5616f5
RH
941 TCGv addr = gen_aa32_addr(s, a32, opc);
942 tcg_gen_qemu_ld_i32(val, addr, index, opc);
943 tcg_temp_free(addr);
08307563
PM
944}
945
7f5616f5
RH
946static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
947 int index, TCGMemOp opc)
948{
949 TCGv addr = gen_aa32_addr(s, a32, opc);
950 tcg_gen_qemu_st_i32(val, addr, index, opc);
951 tcg_temp_free(addr);
952}
08307563 953
7f5616f5 954#define DO_GEN_LD(SUFF, OPC) \
12dcc321 955static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 956 TCGv_i32 a32, int index) \
08307563 957{ \
7f5616f5 958 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
08307563
PM
959}
960
7f5616f5 961#define DO_GEN_ST(SUFF, OPC) \
12dcc321 962static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 963 TCGv_i32 a32, int index) \
08307563 964{ \
7f5616f5 965 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
08307563
PM
966}
967
7f5616f5 968static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
08307563 969{
e334bd31
PB
970 /* Not needed for user-mode BE32, where we use MO_BE instead. */
971 if (!IS_USER_ONLY && s->sctlr_b) {
972 tcg_gen_rotri_i64(val, val, 32);
973 }
08307563
PM
974}
975
7f5616f5
RH
976static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
977 int index, TCGMemOp opc)
08307563 978{
7f5616f5
RH
979 TCGv addr = gen_aa32_addr(s, a32, opc);
980 tcg_gen_qemu_ld_i64(val, addr, index, opc);
981 gen_aa32_frob64(s, val);
982 tcg_temp_free(addr);
983}
984
985static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
986 TCGv_i32 a32, int index)
987{
988 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
989}
990
991static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
992 int index, TCGMemOp opc)
993{
994 TCGv addr = gen_aa32_addr(s, a32, opc);
e334bd31
PB
995
996 /* Not needed for user-mode BE32, where we use MO_BE instead. */
997 if (!IS_USER_ONLY && s->sctlr_b) {
7f5616f5 998 TCGv_i64 tmp = tcg_temp_new_i64();
e334bd31 999 tcg_gen_rotri_i64(tmp, val, 32);
7f5616f5
RH
1000 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1001 tcg_temp_free_i64(tmp);
e334bd31 1002 } else {
7f5616f5 1003 tcg_gen_qemu_st_i64(val, addr, index, opc);
e334bd31 1004 }
7f5616f5 1005 tcg_temp_free(addr);
08307563
PM
1006}
1007
7f5616f5
RH
1008static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1009 TCGv_i32 a32, int index)
1010{
1011 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1012}
08307563 1013
7f5616f5
RH
1014DO_GEN_LD(8s, MO_SB)
1015DO_GEN_LD(8u, MO_UB)
1016DO_GEN_LD(16s, MO_SW)
1017DO_GEN_LD(16u, MO_UW)
1018DO_GEN_LD(32u, MO_UL)
7f5616f5
RH
1019DO_GEN_ST(8, MO_UB)
1020DO_GEN_ST(16, MO_UW)
1021DO_GEN_ST(32, MO_UL)
08307563 1022
eaed129d 1023static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
5e3f878a 1024{
40f860cd 1025 tcg_gen_movi_i32(cpu_R[15], val);
5e3f878a
PB
1026}
1027
37e6456e
PM
1028static inline void gen_hvc(DisasContext *s, int imm16)
1029{
1030 /* The pre HVC helper handles cases when HVC gets trapped
1031 * as an undefined insn by runtime configuration (ie before
1032 * the insn really executes).
1033 */
1034 gen_set_pc_im(s, s->pc - 4);
1035 gen_helper_pre_hvc(cpu_env);
1036 /* Otherwise we will treat this as a real exception which
1037 * happens after execution of the insn. (The distinction matters
1038 * for the PC value reported to the exception handler and also
1039 * for single stepping.)
1040 */
1041 s->svc_imm = imm16;
1042 gen_set_pc_im(s, s->pc);
1043 s->is_jmp = DISAS_HVC;
1044}
1045
1046static inline void gen_smc(DisasContext *s)
1047{
1048 /* As with HVC, we may take an exception either before or after
1049 * the insn executes.
1050 */
1051 TCGv_i32 tmp;
1052
1053 gen_set_pc_im(s, s->pc - 4);
1054 tmp = tcg_const_i32(syn_aa32_smc());
1055 gen_helper_pre_smc(cpu_env, tmp);
1056 tcg_temp_free_i32(tmp);
1057 gen_set_pc_im(s, s->pc);
1058 s->is_jmp = DISAS_SMC;
1059}
1060
d4a2dc67
PM
1061static inline void
1062gen_set_condexec (DisasContext *s)
1063{
1064 if (s->condexec_mask) {
1065 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
1066 TCGv_i32 tmp = tcg_temp_new_i32();
1067 tcg_gen_movi_i32(tmp, val);
1068 store_cpu_field(tmp, condexec_bits);
1069 }
1070}
1071
1072static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
1073{
1074 gen_set_condexec(s);
1075 gen_set_pc_im(s, s->pc - offset);
1076 gen_exception_internal(excp);
1077 s->is_jmp = DISAS_JUMP;
1078}
1079
73710361
GB
1080static void gen_exception_insn(DisasContext *s, int offset, int excp,
1081 int syn, uint32_t target_el)
d4a2dc67
PM
1082{
1083 gen_set_condexec(s);
1084 gen_set_pc_im(s, s->pc - offset);
73710361 1085 gen_exception(excp, syn, target_el);
d4a2dc67
PM
1086 s->is_jmp = DISAS_JUMP;
1087}
1088
b5ff1b31
FB
1089/* Force a TB lookup after an instruction that changes the CPU state. */
1090static inline void gen_lookup_tb(DisasContext *s)
1091{
a6445c52 1092 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
577bf808 1093 s->is_jmp = DISAS_JUMP;
b5ff1b31
FB
1094}
1095
19a6e31c
PM
1096static inline void gen_hlt(DisasContext *s, int imm)
1097{
1098 /* HLT. This has two purposes.
1099 * Architecturally, it is an external halting debug instruction.
1100 * Since QEMU doesn't implement external debug, we treat this as
1101 * it is required for halting debug disabled: it will UNDEF.
1102 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1103 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1104 * must trigger semihosting even for ARMv7 and earlier, where
1105 * HLT was an undefined encoding.
1106 * In system mode, we don't allow userspace access to
1107 * semihosting, to provide some semblance of security
1108 * (and for consistency with our 32-bit semihosting).
1109 */
1110 if (semihosting_enabled() &&
1111#ifndef CONFIG_USER_ONLY
1112 s->current_el != 0 &&
1113#endif
1114 (imm == (s->thumb ? 0x3c : 0xf000))) {
1115 gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
1116 return;
1117 }
1118
1119 gen_exception_insn(s, s->thumb ? 2 : 4, EXCP_UDEF, syn_uncategorized(),
1120 default_exception_el(s));
1121}
1122
b0109805 1123static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
39d5492a 1124 TCGv_i32 var)
2c0262af 1125{
1e8d4eec 1126 int val, rm, shift, shiftop;
39d5492a 1127 TCGv_i32 offset;
2c0262af
FB
1128
1129 if (!(insn & (1 << 25))) {
1130 /* immediate */
1131 val = insn & 0xfff;
1132 if (!(insn & (1 << 23)))
1133 val = -val;
537730b9 1134 if (val != 0)
b0109805 1135 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1136 } else {
1137 /* shift/register */
1138 rm = (insn) & 0xf;
1139 shift = (insn >> 7) & 0x1f;
1e8d4eec 1140 shiftop = (insn >> 5) & 3;
b26eefb6 1141 offset = load_reg(s, rm);
9a119ff6 1142 gen_arm_shift_im(offset, shiftop, shift, 0);
2c0262af 1143 if (!(insn & (1 << 23)))
b0109805 1144 tcg_gen_sub_i32(var, var, offset);
2c0262af 1145 else
b0109805 1146 tcg_gen_add_i32(var, var, offset);
7d1b0095 1147 tcg_temp_free_i32(offset);
2c0262af
FB
1148 }
1149}
1150
191f9a93 1151static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
39d5492a 1152 int extra, TCGv_i32 var)
2c0262af
FB
1153{
1154 int val, rm;
39d5492a 1155 TCGv_i32 offset;
3b46e624 1156
2c0262af
FB
1157 if (insn & (1 << 22)) {
1158 /* immediate */
1159 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1160 if (!(insn & (1 << 23)))
1161 val = -val;
18acad92 1162 val += extra;
537730b9 1163 if (val != 0)
b0109805 1164 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1165 } else {
1166 /* register */
191f9a93 1167 if (extra)
b0109805 1168 tcg_gen_addi_i32(var, var, extra);
2c0262af 1169 rm = (insn) & 0xf;
b26eefb6 1170 offset = load_reg(s, rm);
2c0262af 1171 if (!(insn & (1 << 23)))
b0109805 1172 tcg_gen_sub_i32(var, var, offset);
2c0262af 1173 else
b0109805 1174 tcg_gen_add_i32(var, var, offset);
7d1b0095 1175 tcg_temp_free_i32(offset);
2c0262af
FB
1176 }
1177}
1178
5aaebd13
PM
1179static TCGv_ptr get_fpstatus_ptr(int neon)
1180{
1181 TCGv_ptr statusptr = tcg_temp_new_ptr();
1182 int offset;
1183 if (neon) {
0ecb72a5 1184 offset = offsetof(CPUARMState, vfp.standard_fp_status);
5aaebd13 1185 } else {
0ecb72a5 1186 offset = offsetof(CPUARMState, vfp.fp_status);
5aaebd13
PM
1187 }
1188 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1189 return statusptr;
1190}
1191
4373f3ce
PB
1192#define VFP_OP2(name) \
1193static inline void gen_vfp_##name(int dp) \
1194{ \
ae1857ec
PM
1195 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1196 if (dp) { \
1197 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1198 } else { \
1199 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1200 } \
1201 tcg_temp_free_ptr(fpst); \
b7bcbe95
FB
1202}
1203
4373f3ce
PB
1204VFP_OP2(add)
1205VFP_OP2(sub)
1206VFP_OP2(mul)
1207VFP_OP2(div)
1208
1209#undef VFP_OP2
1210
605a6aed
PM
1211static inline void gen_vfp_F1_mul(int dp)
1212{
1213 /* Like gen_vfp_mul() but put result in F1 */
ae1857ec 1214 TCGv_ptr fpst = get_fpstatus_ptr(0);
605a6aed 1215 if (dp) {
ae1857ec 1216 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
605a6aed 1217 } else {
ae1857ec 1218 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
605a6aed 1219 }
ae1857ec 1220 tcg_temp_free_ptr(fpst);
605a6aed
PM
1221}
1222
1223static inline void gen_vfp_F1_neg(int dp)
1224{
1225 /* Like gen_vfp_neg() but put result in F1 */
1226 if (dp) {
1227 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1228 } else {
1229 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1230 }
1231}
1232
4373f3ce
PB
1233static inline void gen_vfp_abs(int dp)
1234{
1235 if (dp)
1236 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1237 else
1238 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1239}
1240
1241static inline void gen_vfp_neg(int dp)
1242{
1243 if (dp)
1244 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1245 else
1246 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1247}
1248
1249static inline void gen_vfp_sqrt(int dp)
1250{
1251 if (dp)
1252 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1253 else
1254 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1255}
1256
1257static inline void gen_vfp_cmp(int dp)
1258{
1259 if (dp)
1260 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1261 else
1262 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1263}
1264
1265static inline void gen_vfp_cmpe(int dp)
1266{
1267 if (dp)
1268 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1269 else
1270 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1271}
1272
1273static inline void gen_vfp_F1_ld0(int dp)
1274{
1275 if (dp)
5b340b51 1276 tcg_gen_movi_i64(cpu_F1d, 0);
4373f3ce 1277 else
5b340b51 1278 tcg_gen_movi_i32(cpu_F1s, 0);
4373f3ce
PB
1279}
1280
5500b06c
PM
1281#define VFP_GEN_ITOF(name) \
1282static inline void gen_vfp_##name(int dp, int neon) \
1283{ \
5aaebd13 1284 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c
PM
1285 if (dp) { \
1286 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1287 } else { \
1288 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1289 } \
b7fa9214 1290 tcg_temp_free_ptr(statusptr); \
4373f3ce
PB
1291}
1292
5500b06c
PM
1293VFP_GEN_ITOF(uito)
1294VFP_GEN_ITOF(sito)
1295#undef VFP_GEN_ITOF
4373f3ce 1296
5500b06c
PM
1297#define VFP_GEN_FTOI(name) \
1298static inline void gen_vfp_##name(int dp, int neon) \
1299{ \
5aaebd13 1300 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c
PM
1301 if (dp) { \
1302 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1303 } else { \
1304 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1305 } \
b7fa9214 1306 tcg_temp_free_ptr(statusptr); \
4373f3ce
PB
1307}
1308
5500b06c
PM
1309VFP_GEN_FTOI(toui)
1310VFP_GEN_FTOI(touiz)
1311VFP_GEN_FTOI(tosi)
1312VFP_GEN_FTOI(tosiz)
1313#undef VFP_GEN_FTOI
4373f3ce 1314
16d5b3ca 1315#define VFP_GEN_FIX(name, round) \
5500b06c 1316static inline void gen_vfp_##name(int dp, int shift, int neon) \
4373f3ce 1317{ \
39d5492a 1318 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
5aaebd13 1319 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c 1320 if (dp) { \
16d5b3ca
WN
1321 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1322 statusptr); \
5500b06c 1323 } else { \
16d5b3ca
WN
1324 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1325 statusptr); \
5500b06c 1326 } \
b75263d6 1327 tcg_temp_free_i32(tmp_shift); \
b7fa9214 1328 tcg_temp_free_ptr(statusptr); \
9ee6e8bb 1329}
16d5b3ca
WN
1330VFP_GEN_FIX(tosh, _round_to_zero)
1331VFP_GEN_FIX(tosl, _round_to_zero)
1332VFP_GEN_FIX(touh, _round_to_zero)
1333VFP_GEN_FIX(toul, _round_to_zero)
1334VFP_GEN_FIX(shto, )
1335VFP_GEN_FIX(slto, )
1336VFP_GEN_FIX(uhto, )
1337VFP_GEN_FIX(ulto, )
4373f3ce 1338#undef VFP_GEN_FIX
9ee6e8bb 1339
39d5492a 1340static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
b5ff1b31 1341{
08307563 1342 if (dp) {
12dcc321 1343 gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
08307563 1344 } else {
12dcc321 1345 gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
08307563 1346 }
b5ff1b31
FB
1347}
1348
39d5492a 1349static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
b5ff1b31 1350{
08307563 1351 if (dp) {
12dcc321 1352 gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
08307563 1353 } else {
12dcc321 1354 gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
08307563 1355 }
b5ff1b31
FB
1356}
1357
8e96005d
FB
1358static inline long
1359vfp_reg_offset (int dp, int reg)
1360{
1361 if (dp)
1362 return offsetof(CPUARMState, vfp.regs[reg]);
1363 else if (reg & 1) {
1364 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1365 + offsetof(CPU_DoubleU, l.upper);
1366 } else {
1367 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1368 + offsetof(CPU_DoubleU, l.lower);
1369 }
1370}
9ee6e8bb
PB
1371
1372/* Return the offset of a 32-bit piece of a NEON register.
1373 zero is the least significant end of the register. */
1374static inline long
1375neon_reg_offset (int reg, int n)
1376{
1377 int sreg;
1378 sreg = reg * 2 + n;
1379 return vfp_reg_offset(0, sreg);
1380}
1381
39d5492a 1382static TCGv_i32 neon_load_reg(int reg, int pass)
8f8e3aa4 1383{
39d5492a 1384 TCGv_i32 tmp = tcg_temp_new_i32();
8f8e3aa4
PB
1385 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1386 return tmp;
1387}
1388
39d5492a 1389static void neon_store_reg(int reg, int pass, TCGv_i32 var)
8f8e3aa4
PB
1390{
1391 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
7d1b0095 1392 tcg_temp_free_i32(var);
8f8e3aa4
PB
1393}
1394
a7812ae4 1395static inline void neon_load_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1396{
1397 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1398}
1399
a7812ae4 1400static inline void neon_store_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1401{
1402 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1403}
1404
4373f3ce
PB
1405#define tcg_gen_ld_f32 tcg_gen_ld_i32
1406#define tcg_gen_ld_f64 tcg_gen_ld_i64
1407#define tcg_gen_st_f32 tcg_gen_st_i32
1408#define tcg_gen_st_f64 tcg_gen_st_i64
1409
b7bcbe95
FB
1410static inline void gen_mov_F0_vreg(int dp, int reg)
1411{
1412 if (dp)
4373f3ce 1413 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1414 else
4373f3ce 1415 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1416}
1417
1418static inline void gen_mov_F1_vreg(int dp, int reg)
1419{
1420 if (dp)
4373f3ce 1421 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1422 else
4373f3ce 1423 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1424}
1425
1426static inline void gen_mov_vreg_F0(int dp, int reg)
1427{
1428 if (dp)
4373f3ce 1429 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1430 else
4373f3ce 1431 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1432}
1433
18c9b560
AZ
1434#define ARM_CP_RW_BIT (1 << 20)
1435
a7812ae4 1436static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
e677137d 1437{
0ecb72a5 1438 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1439}
1440
a7812ae4 1441static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
e677137d 1442{
0ecb72a5 1443 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1444}
1445
39d5492a 1446static inline TCGv_i32 iwmmxt_load_creg(int reg)
e677137d 1447{
39d5492a 1448 TCGv_i32 var = tcg_temp_new_i32();
0ecb72a5 1449 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
da6b5335 1450 return var;
e677137d
PB
1451}
1452
39d5492a 1453static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
e677137d 1454{
0ecb72a5 1455 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
7d1b0095 1456 tcg_temp_free_i32(var);
e677137d
PB
1457}
1458
1459static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1460{
1461 iwmmxt_store_reg(cpu_M0, rn);
1462}
1463
1464static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1465{
1466 iwmmxt_load_reg(cpu_M0, rn);
1467}
1468
1469static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1470{
1471 iwmmxt_load_reg(cpu_V1, rn);
1472 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1473}
1474
1475static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1476{
1477 iwmmxt_load_reg(cpu_V1, rn);
1478 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1479}
1480
1481static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1482{
1483 iwmmxt_load_reg(cpu_V1, rn);
1484 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1485}
1486
1487#define IWMMXT_OP(name) \
1488static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1489{ \
1490 iwmmxt_load_reg(cpu_V1, rn); \
1491 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1492}
1493
477955bd
PM
1494#define IWMMXT_OP_ENV(name) \
1495static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1496{ \
1497 iwmmxt_load_reg(cpu_V1, rn); \
1498 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1499}
1500
1501#define IWMMXT_OP_ENV_SIZE(name) \
1502IWMMXT_OP_ENV(name##b) \
1503IWMMXT_OP_ENV(name##w) \
1504IWMMXT_OP_ENV(name##l)
e677137d 1505
477955bd 1506#define IWMMXT_OP_ENV1(name) \
e677137d
PB
1507static inline void gen_op_iwmmxt_##name##_M0(void) \
1508{ \
477955bd 1509 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
e677137d
PB
1510}
1511
1512IWMMXT_OP(maddsq)
1513IWMMXT_OP(madduq)
1514IWMMXT_OP(sadb)
1515IWMMXT_OP(sadw)
1516IWMMXT_OP(mulslw)
1517IWMMXT_OP(mulshw)
1518IWMMXT_OP(mululw)
1519IWMMXT_OP(muluhw)
1520IWMMXT_OP(macsw)
1521IWMMXT_OP(macuw)
1522
477955bd
PM
1523IWMMXT_OP_ENV_SIZE(unpackl)
1524IWMMXT_OP_ENV_SIZE(unpackh)
1525
1526IWMMXT_OP_ENV1(unpacklub)
1527IWMMXT_OP_ENV1(unpackluw)
1528IWMMXT_OP_ENV1(unpacklul)
1529IWMMXT_OP_ENV1(unpackhub)
1530IWMMXT_OP_ENV1(unpackhuw)
1531IWMMXT_OP_ENV1(unpackhul)
1532IWMMXT_OP_ENV1(unpacklsb)
1533IWMMXT_OP_ENV1(unpacklsw)
1534IWMMXT_OP_ENV1(unpacklsl)
1535IWMMXT_OP_ENV1(unpackhsb)
1536IWMMXT_OP_ENV1(unpackhsw)
1537IWMMXT_OP_ENV1(unpackhsl)
1538
1539IWMMXT_OP_ENV_SIZE(cmpeq)
1540IWMMXT_OP_ENV_SIZE(cmpgtu)
1541IWMMXT_OP_ENV_SIZE(cmpgts)
1542
1543IWMMXT_OP_ENV_SIZE(mins)
1544IWMMXT_OP_ENV_SIZE(minu)
1545IWMMXT_OP_ENV_SIZE(maxs)
1546IWMMXT_OP_ENV_SIZE(maxu)
1547
1548IWMMXT_OP_ENV_SIZE(subn)
1549IWMMXT_OP_ENV_SIZE(addn)
1550IWMMXT_OP_ENV_SIZE(subu)
1551IWMMXT_OP_ENV_SIZE(addu)
1552IWMMXT_OP_ENV_SIZE(subs)
1553IWMMXT_OP_ENV_SIZE(adds)
1554
1555IWMMXT_OP_ENV(avgb0)
1556IWMMXT_OP_ENV(avgb1)
1557IWMMXT_OP_ENV(avgw0)
1558IWMMXT_OP_ENV(avgw1)
e677137d 1559
477955bd
PM
1560IWMMXT_OP_ENV(packuw)
1561IWMMXT_OP_ENV(packul)
1562IWMMXT_OP_ENV(packuq)
1563IWMMXT_OP_ENV(packsw)
1564IWMMXT_OP_ENV(packsl)
1565IWMMXT_OP_ENV(packsq)
e677137d 1566
e677137d
PB
1567static void gen_op_iwmmxt_set_mup(void)
1568{
39d5492a 1569 TCGv_i32 tmp;
e677137d
PB
1570 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1571 tcg_gen_ori_i32(tmp, tmp, 2);
1572 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1573}
1574
1575static void gen_op_iwmmxt_set_cup(void)
1576{
39d5492a 1577 TCGv_i32 tmp;
e677137d
PB
1578 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1579 tcg_gen_ori_i32(tmp, tmp, 1);
1580 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1581}
1582
1583static void gen_op_iwmmxt_setpsr_nz(void)
1584{
39d5492a 1585 TCGv_i32 tmp = tcg_temp_new_i32();
e677137d
PB
1586 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1587 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1588}
1589
1590static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1591{
1592 iwmmxt_load_reg(cpu_V1, rn);
86831435 1593 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
e677137d
PB
1594 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1595}
1596
39d5492a
PM
1597static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1598 TCGv_i32 dest)
18c9b560
AZ
1599{
1600 int rd;
1601 uint32_t offset;
39d5492a 1602 TCGv_i32 tmp;
18c9b560
AZ
1603
1604 rd = (insn >> 16) & 0xf;
da6b5335 1605 tmp = load_reg(s, rd);
18c9b560
AZ
1606
1607 offset = (insn & 0xff) << ((insn >> 7) & 2);
1608 if (insn & (1 << 24)) {
1609 /* Pre indexed */
1610 if (insn & (1 << 23))
da6b5335 1611 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1612 else
da6b5335
FN
1613 tcg_gen_addi_i32(tmp, tmp, -offset);
1614 tcg_gen_mov_i32(dest, tmp);
18c9b560 1615 if (insn & (1 << 21))
da6b5335
FN
1616 store_reg(s, rd, tmp);
1617 else
7d1b0095 1618 tcg_temp_free_i32(tmp);
18c9b560
AZ
1619 } else if (insn & (1 << 21)) {
1620 /* Post indexed */
da6b5335 1621 tcg_gen_mov_i32(dest, tmp);
18c9b560 1622 if (insn & (1 << 23))
da6b5335 1623 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1624 else
da6b5335
FN
1625 tcg_gen_addi_i32(tmp, tmp, -offset);
1626 store_reg(s, rd, tmp);
18c9b560
AZ
1627 } else if (!(insn & (1 << 23)))
1628 return 1;
1629 return 0;
1630}
1631
39d5492a 1632static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
18c9b560
AZ
1633{
1634 int rd = (insn >> 0) & 0xf;
39d5492a 1635 TCGv_i32 tmp;
18c9b560 1636
da6b5335
FN
1637 if (insn & (1 << 8)) {
1638 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
18c9b560 1639 return 1;
da6b5335
FN
1640 } else {
1641 tmp = iwmmxt_load_creg(rd);
1642 }
1643 } else {
7d1b0095 1644 tmp = tcg_temp_new_i32();
da6b5335 1645 iwmmxt_load_reg(cpu_V0, rd);
ecc7b3aa 1646 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
da6b5335
FN
1647 }
1648 tcg_gen_andi_i32(tmp, tmp, mask);
1649 tcg_gen_mov_i32(dest, tmp);
7d1b0095 1650 tcg_temp_free_i32(tmp);
18c9b560
AZ
1651 return 0;
1652}
1653
a1c7273b 1654/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
18c9b560 1655 (ie. an undefined instruction). */
7dcc1f89 1656static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
1657{
1658 int rd, wrd;
1659 int rdhi, rdlo, rd0, rd1, i;
39d5492a
PM
1660 TCGv_i32 addr;
1661 TCGv_i32 tmp, tmp2, tmp3;
18c9b560
AZ
1662
1663 if ((insn & 0x0e000e00) == 0x0c000000) {
1664 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1665 wrd = insn & 0xf;
1666 rdlo = (insn >> 12) & 0xf;
1667 rdhi = (insn >> 16) & 0xf;
1668 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
da6b5335 1669 iwmmxt_load_reg(cpu_V0, wrd);
ecc7b3aa 1670 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
da6b5335 1671 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 1672 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
18c9b560 1673 } else { /* TMCRR */
da6b5335
FN
1674 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1675 iwmmxt_store_reg(cpu_V0, wrd);
18c9b560
AZ
1676 gen_op_iwmmxt_set_mup();
1677 }
1678 return 0;
1679 }
1680
1681 wrd = (insn >> 12) & 0xf;
7d1b0095 1682 addr = tcg_temp_new_i32();
da6b5335 1683 if (gen_iwmmxt_address(s, insn, addr)) {
7d1b0095 1684 tcg_temp_free_i32(addr);
18c9b560 1685 return 1;
da6b5335 1686 }
18c9b560
AZ
1687 if (insn & ARM_CP_RW_BIT) {
1688 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
7d1b0095 1689 tmp = tcg_temp_new_i32();
12dcc321 1690 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
da6b5335 1691 iwmmxt_store_creg(wrd, tmp);
18c9b560 1692 } else {
e677137d
PB
1693 i = 1;
1694 if (insn & (1 << 8)) {
1695 if (insn & (1 << 22)) { /* WLDRD */
12dcc321 1696 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
e677137d
PB
1697 i = 0;
1698 } else { /* WLDRW wRd */
29531141 1699 tmp = tcg_temp_new_i32();
12dcc321 1700 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1701 }
1702 } else {
29531141 1703 tmp = tcg_temp_new_i32();
e677137d 1704 if (insn & (1 << 22)) { /* WLDRH */
12dcc321 1705 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
e677137d 1706 } else { /* WLDRB */
12dcc321 1707 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1708 }
1709 }
1710 if (i) {
1711 tcg_gen_extu_i32_i64(cpu_M0, tmp);
7d1b0095 1712 tcg_temp_free_i32(tmp);
e677137d 1713 }
18c9b560
AZ
1714 gen_op_iwmmxt_movq_wRn_M0(wrd);
1715 }
1716 } else {
1717 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
da6b5335 1718 tmp = iwmmxt_load_creg(wrd);
12dcc321 1719 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
18c9b560
AZ
1720 } else {
1721 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 1722 tmp = tcg_temp_new_i32();
e677137d
PB
1723 if (insn & (1 << 8)) {
1724 if (insn & (1 << 22)) { /* WSTRD */
12dcc321 1725 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
e677137d 1726 } else { /* WSTRW wRd */
ecc7b3aa 1727 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1728 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e677137d
PB
1729 }
1730 } else {
1731 if (insn & (1 << 22)) { /* WSTRH */
ecc7b3aa 1732 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1733 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
e677137d 1734 } else { /* WSTRB */
ecc7b3aa 1735 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1736 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
e677137d
PB
1737 }
1738 }
18c9b560 1739 }
29531141 1740 tcg_temp_free_i32(tmp);
18c9b560 1741 }
7d1b0095 1742 tcg_temp_free_i32(addr);
18c9b560
AZ
1743 return 0;
1744 }
1745
1746 if ((insn & 0x0f000000) != 0x0e000000)
1747 return 1;
1748
1749 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1750 case 0x000: /* WOR */
1751 wrd = (insn >> 12) & 0xf;
1752 rd0 = (insn >> 0) & 0xf;
1753 rd1 = (insn >> 16) & 0xf;
1754 gen_op_iwmmxt_movq_M0_wRn(rd0);
1755 gen_op_iwmmxt_orq_M0_wRn(rd1);
1756 gen_op_iwmmxt_setpsr_nz();
1757 gen_op_iwmmxt_movq_wRn_M0(wrd);
1758 gen_op_iwmmxt_set_mup();
1759 gen_op_iwmmxt_set_cup();
1760 break;
1761 case 0x011: /* TMCR */
1762 if (insn & 0xf)
1763 return 1;
1764 rd = (insn >> 12) & 0xf;
1765 wrd = (insn >> 16) & 0xf;
1766 switch (wrd) {
1767 case ARM_IWMMXT_wCID:
1768 case ARM_IWMMXT_wCASF:
1769 break;
1770 case ARM_IWMMXT_wCon:
1771 gen_op_iwmmxt_set_cup();
1772 /* Fall through. */
1773 case ARM_IWMMXT_wCSSF:
da6b5335
FN
1774 tmp = iwmmxt_load_creg(wrd);
1775 tmp2 = load_reg(s, rd);
f669df27 1776 tcg_gen_andc_i32(tmp, tmp, tmp2);
7d1b0095 1777 tcg_temp_free_i32(tmp2);
da6b5335 1778 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1779 break;
1780 case ARM_IWMMXT_wCGR0:
1781 case ARM_IWMMXT_wCGR1:
1782 case ARM_IWMMXT_wCGR2:
1783 case ARM_IWMMXT_wCGR3:
1784 gen_op_iwmmxt_set_cup();
da6b5335
FN
1785 tmp = load_reg(s, rd);
1786 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1787 break;
1788 default:
1789 return 1;
1790 }
1791 break;
1792 case 0x100: /* WXOR */
1793 wrd = (insn >> 12) & 0xf;
1794 rd0 = (insn >> 0) & 0xf;
1795 rd1 = (insn >> 16) & 0xf;
1796 gen_op_iwmmxt_movq_M0_wRn(rd0);
1797 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1798 gen_op_iwmmxt_setpsr_nz();
1799 gen_op_iwmmxt_movq_wRn_M0(wrd);
1800 gen_op_iwmmxt_set_mup();
1801 gen_op_iwmmxt_set_cup();
1802 break;
1803 case 0x111: /* TMRC */
1804 if (insn & 0xf)
1805 return 1;
1806 rd = (insn >> 12) & 0xf;
1807 wrd = (insn >> 16) & 0xf;
da6b5335
FN
1808 tmp = iwmmxt_load_creg(wrd);
1809 store_reg(s, rd, tmp);
18c9b560
AZ
1810 break;
1811 case 0x300: /* WANDN */
1812 wrd = (insn >> 12) & 0xf;
1813 rd0 = (insn >> 0) & 0xf;
1814 rd1 = (insn >> 16) & 0xf;
1815 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d 1816 tcg_gen_neg_i64(cpu_M0, cpu_M0);
18c9b560
AZ
1817 gen_op_iwmmxt_andq_M0_wRn(rd1);
1818 gen_op_iwmmxt_setpsr_nz();
1819 gen_op_iwmmxt_movq_wRn_M0(wrd);
1820 gen_op_iwmmxt_set_mup();
1821 gen_op_iwmmxt_set_cup();
1822 break;
1823 case 0x200: /* WAND */
1824 wrd = (insn >> 12) & 0xf;
1825 rd0 = (insn >> 0) & 0xf;
1826 rd1 = (insn >> 16) & 0xf;
1827 gen_op_iwmmxt_movq_M0_wRn(rd0);
1828 gen_op_iwmmxt_andq_M0_wRn(rd1);
1829 gen_op_iwmmxt_setpsr_nz();
1830 gen_op_iwmmxt_movq_wRn_M0(wrd);
1831 gen_op_iwmmxt_set_mup();
1832 gen_op_iwmmxt_set_cup();
1833 break;
1834 case 0x810: case 0xa10: /* WMADD */
1835 wrd = (insn >> 12) & 0xf;
1836 rd0 = (insn >> 0) & 0xf;
1837 rd1 = (insn >> 16) & 0xf;
1838 gen_op_iwmmxt_movq_M0_wRn(rd0);
1839 if (insn & (1 << 21))
1840 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1841 else
1842 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1843 gen_op_iwmmxt_movq_wRn_M0(wrd);
1844 gen_op_iwmmxt_set_mup();
1845 break;
1846 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1847 wrd = (insn >> 12) & 0xf;
1848 rd0 = (insn >> 16) & 0xf;
1849 rd1 = (insn >> 0) & 0xf;
1850 gen_op_iwmmxt_movq_M0_wRn(rd0);
1851 switch ((insn >> 22) & 3) {
1852 case 0:
1853 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1854 break;
1855 case 1:
1856 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1857 break;
1858 case 2:
1859 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1860 break;
1861 case 3:
1862 return 1;
1863 }
1864 gen_op_iwmmxt_movq_wRn_M0(wrd);
1865 gen_op_iwmmxt_set_mup();
1866 gen_op_iwmmxt_set_cup();
1867 break;
1868 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1869 wrd = (insn >> 12) & 0xf;
1870 rd0 = (insn >> 16) & 0xf;
1871 rd1 = (insn >> 0) & 0xf;
1872 gen_op_iwmmxt_movq_M0_wRn(rd0);
1873 switch ((insn >> 22) & 3) {
1874 case 0:
1875 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1876 break;
1877 case 1:
1878 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1879 break;
1880 case 2:
1881 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1882 break;
1883 case 3:
1884 return 1;
1885 }
1886 gen_op_iwmmxt_movq_wRn_M0(wrd);
1887 gen_op_iwmmxt_set_mup();
1888 gen_op_iwmmxt_set_cup();
1889 break;
1890 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1891 wrd = (insn >> 12) & 0xf;
1892 rd0 = (insn >> 16) & 0xf;
1893 rd1 = (insn >> 0) & 0xf;
1894 gen_op_iwmmxt_movq_M0_wRn(rd0);
1895 if (insn & (1 << 22))
1896 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1897 else
1898 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1899 if (!(insn & (1 << 20)))
1900 gen_op_iwmmxt_addl_M0_wRn(wrd);
1901 gen_op_iwmmxt_movq_wRn_M0(wrd);
1902 gen_op_iwmmxt_set_mup();
1903 break;
1904 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1905 wrd = (insn >> 12) & 0xf;
1906 rd0 = (insn >> 16) & 0xf;
1907 rd1 = (insn >> 0) & 0xf;
1908 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
1909 if (insn & (1 << 21)) {
1910 if (insn & (1 << 20))
1911 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1912 else
1913 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1914 } else {
1915 if (insn & (1 << 20))
1916 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1917 else
1918 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1919 }
18c9b560
AZ
1920 gen_op_iwmmxt_movq_wRn_M0(wrd);
1921 gen_op_iwmmxt_set_mup();
1922 break;
1923 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1924 wrd = (insn >> 12) & 0xf;
1925 rd0 = (insn >> 16) & 0xf;
1926 rd1 = (insn >> 0) & 0xf;
1927 gen_op_iwmmxt_movq_M0_wRn(rd0);
1928 if (insn & (1 << 21))
1929 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1930 else
1931 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1932 if (!(insn & (1 << 20))) {
e677137d
PB
1933 iwmmxt_load_reg(cpu_V1, wrd);
1934 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
18c9b560
AZ
1935 }
1936 gen_op_iwmmxt_movq_wRn_M0(wrd);
1937 gen_op_iwmmxt_set_mup();
1938 break;
1939 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1940 wrd = (insn >> 12) & 0xf;
1941 rd0 = (insn >> 16) & 0xf;
1942 rd1 = (insn >> 0) & 0xf;
1943 gen_op_iwmmxt_movq_M0_wRn(rd0);
1944 switch ((insn >> 22) & 3) {
1945 case 0:
1946 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1947 break;
1948 case 1:
1949 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1950 break;
1951 case 2:
1952 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1953 break;
1954 case 3:
1955 return 1;
1956 }
1957 gen_op_iwmmxt_movq_wRn_M0(wrd);
1958 gen_op_iwmmxt_set_mup();
1959 gen_op_iwmmxt_set_cup();
1960 break;
1961 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1962 wrd = (insn >> 12) & 0xf;
1963 rd0 = (insn >> 16) & 0xf;
1964 rd1 = (insn >> 0) & 0xf;
1965 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
1966 if (insn & (1 << 22)) {
1967 if (insn & (1 << 20))
1968 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1969 else
1970 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1971 } else {
1972 if (insn & (1 << 20))
1973 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1974 else
1975 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1976 }
18c9b560
AZ
1977 gen_op_iwmmxt_movq_wRn_M0(wrd);
1978 gen_op_iwmmxt_set_mup();
1979 gen_op_iwmmxt_set_cup();
1980 break;
1981 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1982 wrd = (insn >> 12) & 0xf;
1983 rd0 = (insn >> 16) & 0xf;
1984 rd1 = (insn >> 0) & 0xf;
1985 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
1986 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1987 tcg_gen_andi_i32(tmp, tmp, 7);
1988 iwmmxt_load_reg(cpu_V1, rd1);
1989 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
7d1b0095 1990 tcg_temp_free_i32(tmp);
18c9b560
AZ
1991 gen_op_iwmmxt_movq_wRn_M0(wrd);
1992 gen_op_iwmmxt_set_mup();
1993 break;
1994 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
da6b5335
FN
1995 if (((insn >> 6) & 3) == 3)
1996 return 1;
18c9b560
AZ
1997 rd = (insn >> 12) & 0xf;
1998 wrd = (insn >> 16) & 0xf;
da6b5335 1999 tmp = load_reg(s, rd);
18c9b560
AZ
2000 gen_op_iwmmxt_movq_M0_wRn(wrd);
2001 switch ((insn >> 6) & 3) {
2002 case 0:
da6b5335
FN
2003 tmp2 = tcg_const_i32(0xff);
2004 tmp3 = tcg_const_i32((insn & 7) << 3);
18c9b560
AZ
2005 break;
2006 case 1:
da6b5335
FN
2007 tmp2 = tcg_const_i32(0xffff);
2008 tmp3 = tcg_const_i32((insn & 3) << 4);
18c9b560
AZ
2009 break;
2010 case 2:
da6b5335
FN
2011 tmp2 = tcg_const_i32(0xffffffff);
2012 tmp3 = tcg_const_i32((insn & 1) << 5);
18c9b560 2013 break;
da6b5335 2014 default:
39d5492a
PM
2015 TCGV_UNUSED_I32(tmp2);
2016 TCGV_UNUSED_I32(tmp3);
18c9b560 2017 }
da6b5335 2018 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
39d5492a
PM
2019 tcg_temp_free_i32(tmp3);
2020 tcg_temp_free_i32(tmp2);
7d1b0095 2021 tcg_temp_free_i32(tmp);
18c9b560
AZ
2022 gen_op_iwmmxt_movq_wRn_M0(wrd);
2023 gen_op_iwmmxt_set_mup();
2024 break;
2025 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
2026 rd = (insn >> 12) & 0xf;
2027 wrd = (insn >> 16) & 0xf;
da6b5335 2028 if (rd == 15 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2029 return 1;
2030 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 2031 tmp = tcg_temp_new_i32();
18c9b560
AZ
2032 switch ((insn >> 22) & 3) {
2033 case 0:
da6b5335 2034 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
ecc7b3aa 2035 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
2036 if (insn & 8) {
2037 tcg_gen_ext8s_i32(tmp, tmp);
2038 } else {
2039 tcg_gen_andi_i32(tmp, tmp, 0xff);
18c9b560
AZ
2040 }
2041 break;
2042 case 1:
da6b5335 2043 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
ecc7b3aa 2044 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
2045 if (insn & 8) {
2046 tcg_gen_ext16s_i32(tmp, tmp);
2047 } else {
2048 tcg_gen_andi_i32(tmp, tmp, 0xffff);
18c9b560
AZ
2049 }
2050 break;
2051 case 2:
da6b5335 2052 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
ecc7b3aa 2053 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
18c9b560 2054 break;
18c9b560 2055 }
da6b5335 2056 store_reg(s, rd, tmp);
18c9b560
AZ
2057 break;
2058 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
da6b5335 2059 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2060 return 1;
da6b5335 2061 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18c9b560
AZ
2062 switch ((insn >> 22) & 3) {
2063 case 0:
da6b5335 2064 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
18c9b560
AZ
2065 break;
2066 case 1:
da6b5335 2067 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
18c9b560
AZ
2068 break;
2069 case 2:
da6b5335 2070 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
18c9b560 2071 break;
18c9b560 2072 }
da6b5335
FN
2073 tcg_gen_shli_i32(tmp, tmp, 28);
2074 gen_set_nzcv(tmp);
7d1b0095 2075 tcg_temp_free_i32(tmp);
18c9b560
AZ
2076 break;
2077 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
da6b5335
FN
2078 if (((insn >> 6) & 3) == 3)
2079 return 1;
18c9b560
AZ
2080 rd = (insn >> 12) & 0xf;
2081 wrd = (insn >> 16) & 0xf;
da6b5335 2082 tmp = load_reg(s, rd);
18c9b560
AZ
2083 switch ((insn >> 6) & 3) {
2084 case 0:
da6b5335 2085 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
18c9b560
AZ
2086 break;
2087 case 1:
da6b5335 2088 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
18c9b560
AZ
2089 break;
2090 case 2:
da6b5335 2091 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
18c9b560 2092 break;
18c9b560 2093 }
7d1b0095 2094 tcg_temp_free_i32(tmp);
18c9b560
AZ
2095 gen_op_iwmmxt_movq_wRn_M0(wrd);
2096 gen_op_iwmmxt_set_mup();
2097 break;
2098 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
da6b5335 2099 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2100 return 1;
da6b5335 2101 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2102 tmp2 = tcg_temp_new_i32();
da6b5335 2103 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2104 switch ((insn >> 22) & 3) {
2105 case 0:
2106 for (i = 0; i < 7; i ++) {
da6b5335
FN
2107 tcg_gen_shli_i32(tmp2, tmp2, 4);
2108 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2109 }
2110 break;
2111 case 1:
2112 for (i = 0; i < 3; i ++) {
da6b5335
FN
2113 tcg_gen_shli_i32(tmp2, tmp2, 8);
2114 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2115 }
2116 break;
2117 case 2:
da6b5335
FN
2118 tcg_gen_shli_i32(tmp2, tmp2, 16);
2119 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560 2120 break;
18c9b560 2121 }
da6b5335 2122 gen_set_nzcv(tmp);
7d1b0095
PM
2123 tcg_temp_free_i32(tmp2);
2124 tcg_temp_free_i32(tmp);
18c9b560
AZ
2125 break;
2126 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
2127 wrd = (insn >> 12) & 0xf;
2128 rd0 = (insn >> 16) & 0xf;
2129 gen_op_iwmmxt_movq_M0_wRn(rd0);
2130 switch ((insn >> 22) & 3) {
2131 case 0:
e677137d 2132 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
18c9b560
AZ
2133 break;
2134 case 1:
e677137d 2135 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
18c9b560
AZ
2136 break;
2137 case 2:
e677137d 2138 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
18c9b560
AZ
2139 break;
2140 case 3:
2141 return 1;
2142 }
2143 gen_op_iwmmxt_movq_wRn_M0(wrd);
2144 gen_op_iwmmxt_set_mup();
2145 break;
2146 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
da6b5335 2147 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2148 return 1;
da6b5335 2149 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2150 tmp2 = tcg_temp_new_i32();
da6b5335 2151 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2152 switch ((insn >> 22) & 3) {
2153 case 0:
2154 for (i = 0; i < 7; i ++) {
da6b5335
FN
2155 tcg_gen_shli_i32(tmp2, tmp2, 4);
2156 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2157 }
2158 break;
2159 case 1:
2160 for (i = 0; i < 3; i ++) {
da6b5335
FN
2161 tcg_gen_shli_i32(tmp2, tmp2, 8);
2162 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2163 }
2164 break;
2165 case 2:
da6b5335
FN
2166 tcg_gen_shli_i32(tmp2, tmp2, 16);
2167 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560 2168 break;
18c9b560 2169 }
da6b5335 2170 gen_set_nzcv(tmp);
7d1b0095
PM
2171 tcg_temp_free_i32(tmp2);
2172 tcg_temp_free_i32(tmp);
18c9b560
AZ
2173 break;
2174 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2175 rd = (insn >> 12) & 0xf;
2176 rd0 = (insn >> 16) & 0xf;
da6b5335 2177 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2178 return 1;
2179 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2180 tmp = tcg_temp_new_i32();
18c9b560
AZ
2181 switch ((insn >> 22) & 3) {
2182 case 0:
da6b5335 2183 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
18c9b560
AZ
2184 break;
2185 case 1:
da6b5335 2186 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
18c9b560
AZ
2187 break;
2188 case 2:
da6b5335 2189 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
18c9b560 2190 break;
18c9b560 2191 }
da6b5335 2192 store_reg(s, rd, tmp);
18c9b560
AZ
2193 break;
2194 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2195 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2196 wrd = (insn >> 12) & 0xf;
2197 rd0 = (insn >> 16) & 0xf;
2198 rd1 = (insn >> 0) & 0xf;
2199 gen_op_iwmmxt_movq_M0_wRn(rd0);
2200 switch ((insn >> 22) & 3) {
2201 case 0:
2202 if (insn & (1 << 21))
2203 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2204 else
2205 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2206 break;
2207 case 1:
2208 if (insn & (1 << 21))
2209 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2210 else
2211 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2212 break;
2213 case 2:
2214 if (insn & (1 << 21))
2215 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2216 else
2217 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2218 break;
2219 case 3:
2220 return 1;
2221 }
2222 gen_op_iwmmxt_movq_wRn_M0(wrd);
2223 gen_op_iwmmxt_set_mup();
2224 gen_op_iwmmxt_set_cup();
2225 break;
2226 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2227 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2228 wrd = (insn >> 12) & 0xf;
2229 rd0 = (insn >> 16) & 0xf;
2230 gen_op_iwmmxt_movq_M0_wRn(rd0);
2231 switch ((insn >> 22) & 3) {
2232 case 0:
2233 if (insn & (1 << 21))
2234 gen_op_iwmmxt_unpacklsb_M0();
2235 else
2236 gen_op_iwmmxt_unpacklub_M0();
2237 break;
2238 case 1:
2239 if (insn & (1 << 21))
2240 gen_op_iwmmxt_unpacklsw_M0();
2241 else
2242 gen_op_iwmmxt_unpackluw_M0();
2243 break;
2244 case 2:
2245 if (insn & (1 << 21))
2246 gen_op_iwmmxt_unpacklsl_M0();
2247 else
2248 gen_op_iwmmxt_unpacklul_M0();
2249 break;
2250 case 3:
2251 return 1;
2252 }
2253 gen_op_iwmmxt_movq_wRn_M0(wrd);
2254 gen_op_iwmmxt_set_mup();
2255 gen_op_iwmmxt_set_cup();
2256 break;
2257 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2258 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2259 wrd = (insn >> 12) & 0xf;
2260 rd0 = (insn >> 16) & 0xf;
2261 gen_op_iwmmxt_movq_M0_wRn(rd0);
2262 switch ((insn >> 22) & 3) {
2263 case 0:
2264 if (insn & (1 << 21))
2265 gen_op_iwmmxt_unpackhsb_M0();
2266 else
2267 gen_op_iwmmxt_unpackhub_M0();
2268 break;
2269 case 1:
2270 if (insn & (1 << 21))
2271 gen_op_iwmmxt_unpackhsw_M0();
2272 else
2273 gen_op_iwmmxt_unpackhuw_M0();
2274 break;
2275 case 2:
2276 if (insn & (1 << 21))
2277 gen_op_iwmmxt_unpackhsl_M0();
2278 else
2279 gen_op_iwmmxt_unpackhul_M0();
2280 break;
2281 case 3:
2282 return 1;
2283 }
2284 gen_op_iwmmxt_movq_wRn_M0(wrd);
2285 gen_op_iwmmxt_set_mup();
2286 gen_op_iwmmxt_set_cup();
2287 break;
2288 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2289 case 0x214: case 0x614: case 0xa14: case 0xe14:
da6b5335
FN
2290 if (((insn >> 22) & 3) == 0)
2291 return 1;
18c9b560
AZ
2292 wrd = (insn >> 12) & 0xf;
2293 rd0 = (insn >> 16) & 0xf;
2294 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2295 tmp = tcg_temp_new_i32();
da6b5335 2296 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2297 tcg_temp_free_i32(tmp);
18c9b560 2298 return 1;
da6b5335 2299 }
18c9b560 2300 switch ((insn >> 22) & 3) {
18c9b560 2301 case 1:
477955bd 2302 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2303 break;
2304 case 2:
477955bd 2305 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2306 break;
2307 case 3:
477955bd 2308 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2309 break;
2310 }
7d1b0095 2311 tcg_temp_free_i32(tmp);
18c9b560
AZ
2312 gen_op_iwmmxt_movq_wRn_M0(wrd);
2313 gen_op_iwmmxt_set_mup();
2314 gen_op_iwmmxt_set_cup();
2315 break;
2316 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2317 case 0x014: case 0x414: case 0x814: case 0xc14:
da6b5335
FN
2318 if (((insn >> 22) & 3) == 0)
2319 return 1;
18c9b560
AZ
2320 wrd = (insn >> 12) & 0xf;
2321 rd0 = (insn >> 16) & 0xf;
2322 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2323 tmp = tcg_temp_new_i32();
da6b5335 2324 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2325 tcg_temp_free_i32(tmp);
18c9b560 2326 return 1;
da6b5335 2327 }
18c9b560 2328 switch ((insn >> 22) & 3) {
18c9b560 2329 case 1:
477955bd 2330 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2331 break;
2332 case 2:
477955bd 2333 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2334 break;
2335 case 3:
477955bd 2336 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2337 break;
2338 }
7d1b0095 2339 tcg_temp_free_i32(tmp);
18c9b560
AZ
2340 gen_op_iwmmxt_movq_wRn_M0(wrd);
2341 gen_op_iwmmxt_set_mup();
2342 gen_op_iwmmxt_set_cup();
2343 break;
2344 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2345 case 0x114: case 0x514: case 0x914: case 0xd14:
da6b5335
FN
2346 if (((insn >> 22) & 3) == 0)
2347 return 1;
18c9b560
AZ
2348 wrd = (insn >> 12) & 0xf;
2349 rd0 = (insn >> 16) & 0xf;
2350 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2351 tmp = tcg_temp_new_i32();
da6b5335 2352 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2353 tcg_temp_free_i32(tmp);
18c9b560 2354 return 1;
da6b5335 2355 }
18c9b560 2356 switch ((insn >> 22) & 3) {
18c9b560 2357 case 1:
477955bd 2358 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2359 break;
2360 case 2:
477955bd 2361 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2362 break;
2363 case 3:
477955bd 2364 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2365 break;
2366 }
7d1b0095 2367 tcg_temp_free_i32(tmp);
18c9b560
AZ
2368 gen_op_iwmmxt_movq_wRn_M0(wrd);
2369 gen_op_iwmmxt_set_mup();
2370 gen_op_iwmmxt_set_cup();
2371 break;
2372 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2373 case 0x314: case 0x714: case 0xb14: case 0xf14:
da6b5335
FN
2374 if (((insn >> 22) & 3) == 0)
2375 return 1;
18c9b560
AZ
2376 wrd = (insn >> 12) & 0xf;
2377 rd0 = (insn >> 16) & 0xf;
2378 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2379 tmp = tcg_temp_new_i32();
18c9b560 2380 switch ((insn >> 22) & 3) {
18c9b560 2381 case 1:
da6b5335 2382 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
7d1b0095 2383 tcg_temp_free_i32(tmp);
18c9b560 2384 return 1;
da6b5335 2385 }
477955bd 2386 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2387 break;
2388 case 2:
da6b5335 2389 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
7d1b0095 2390 tcg_temp_free_i32(tmp);
18c9b560 2391 return 1;
da6b5335 2392 }
477955bd 2393 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2394 break;
2395 case 3:
da6b5335 2396 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
7d1b0095 2397 tcg_temp_free_i32(tmp);
18c9b560 2398 return 1;
da6b5335 2399 }
477955bd 2400 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2401 break;
2402 }
7d1b0095 2403 tcg_temp_free_i32(tmp);
18c9b560
AZ
2404 gen_op_iwmmxt_movq_wRn_M0(wrd);
2405 gen_op_iwmmxt_set_mup();
2406 gen_op_iwmmxt_set_cup();
2407 break;
2408 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2409 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2410 wrd = (insn >> 12) & 0xf;
2411 rd0 = (insn >> 16) & 0xf;
2412 rd1 = (insn >> 0) & 0xf;
2413 gen_op_iwmmxt_movq_M0_wRn(rd0);
2414 switch ((insn >> 22) & 3) {
2415 case 0:
2416 if (insn & (1 << 21))
2417 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2418 else
2419 gen_op_iwmmxt_minub_M0_wRn(rd1);
2420 break;
2421 case 1:
2422 if (insn & (1 << 21))
2423 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2424 else
2425 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2426 break;
2427 case 2:
2428 if (insn & (1 << 21))
2429 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2430 else
2431 gen_op_iwmmxt_minul_M0_wRn(rd1);
2432 break;
2433 case 3:
2434 return 1;
2435 }
2436 gen_op_iwmmxt_movq_wRn_M0(wrd);
2437 gen_op_iwmmxt_set_mup();
2438 break;
2439 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2440 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2441 wrd = (insn >> 12) & 0xf;
2442 rd0 = (insn >> 16) & 0xf;
2443 rd1 = (insn >> 0) & 0xf;
2444 gen_op_iwmmxt_movq_M0_wRn(rd0);
2445 switch ((insn >> 22) & 3) {
2446 case 0:
2447 if (insn & (1 << 21))
2448 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2449 else
2450 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2451 break;
2452 case 1:
2453 if (insn & (1 << 21))
2454 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2455 else
2456 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2457 break;
2458 case 2:
2459 if (insn & (1 << 21))
2460 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2461 else
2462 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2463 break;
2464 case 3:
2465 return 1;
2466 }
2467 gen_op_iwmmxt_movq_wRn_M0(wrd);
2468 gen_op_iwmmxt_set_mup();
2469 break;
2470 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2471 case 0x402: case 0x502: case 0x602: case 0x702:
2472 wrd = (insn >> 12) & 0xf;
2473 rd0 = (insn >> 16) & 0xf;
2474 rd1 = (insn >> 0) & 0xf;
2475 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2476 tmp = tcg_const_i32((insn >> 20) & 3);
2477 iwmmxt_load_reg(cpu_V1, rd1);
2478 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
39d5492a 2479 tcg_temp_free_i32(tmp);
18c9b560
AZ
2480 gen_op_iwmmxt_movq_wRn_M0(wrd);
2481 gen_op_iwmmxt_set_mup();
2482 break;
2483 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2484 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2485 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2486 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2487 wrd = (insn >> 12) & 0xf;
2488 rd0 = (insn >> 16) & 0xf;
2489 rd1 = (insn >> 0) & 0xf;
2490 gen_op_iwmmxt_movq_M0_wRn(rd0);
2491 switch ((insn >> 20) & 0xf) {
2492 case 0x0:
2493 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2494 break;
2495 case 0x1:
2496 gen_op_iwmmxt_subub_M0_wRn(rd1);
2497 break;
2498 case 0x3:
2499 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2500 break;
2501 case 0x4:
2502 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2503 break;
2504 case 0x5:
2505 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2506 break;
2507 case 0x7:
2508 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2509 break;
2510 case 0x8:
2511 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2512 break;
2513 case 0x9:
2514 gen_op_iwmmxt_subul_M0_wRn(rd1);
2515 break;
2516 case 0xb:
2517 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2518 break;
2519 default:
2520 return 1;
2521 }
2522 gen_op_iwmmxt_movq_wRn_M0(wrd);
2523 gen_op_iwmmxt_set_mup();
2524 gen_op_iwmmxt_set_cup();
2525 break;
2526 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2527 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2528 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2529 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2530 wrd = (insn >> 12) & 0xf;
2531 rd0 = (insn >> 16) & 0xf;
2532 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335 2533 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
477955bd 2534 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
39d5492a 2535 tcg_temp_free_i32(tmp);
18c9b560
AZ
2536 gen_op_iwmmxt_movq_wRn_M0(wrd);
2537 gen_op_iwmmxt_set_mup();
2538 gen_op_iwmmxt_set_cup();
2539 break;
2540 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2541 case 0x418: case 0x518: case 0x618: case 0x718:
2542 case 0x818: case 0x918: case 0xa18: case 0xb18:
2543 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2544 wrd = (insn >> 12) & 0xf;
2545 rd0 = (insn >> 16) & 0xf;
2546 rd1 = (insn >> 0) & 0xf;
2547 gen_op_iwmmxt_movq_M0_wRn(rd0);
2548 switch ((insn >> 20) & 0xf) {
2549 case 0x0:
2550 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2551 break;
2552 case 0x1:
2553 gen_op_iwmmxt_addub_M0_wRn(rd1);
2554 break;
2555 case 0x3:
2556 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2557 break;
2558 case 0x4:
2559 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2560 break;
2561 case 0x5:
2562 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2563 break;
2564 case 0x7:
2565 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2566 break;
2567 case 0x8:
2568 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2569 break;
2570 case 0x9:
2571 gen_op_iwmmxt_addul_M0_wRn(rd1);
2572 break;
2573 case 0xb:
2574 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2575 break;
2576 default:
2577 return 1;
2578 }
2579 gen_op_iwmmxt_movq_wRn_M0(wrd);
2580 gen_op_iwmmxt_set_mup();
2581 gen_op_iwmmxt_set_cup();
2582 break;
2583 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2584 case 0x408: case 0x508: case 0x608: case 0x708:
2585 case 0x808: case 0x908: case 0xa08: case 0xb08:
2586 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
da6b5335
FN
2587 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2588 return 1;
18c9b560
AZ
2589 wrd = (insn >> 12) & 0xf;
2590 rd0 = (insn >> 16) & 0xf;
2591 rd1 = (insn >> 0) & 0xf;
2592 gen_op_iwmmxt_movq_M0_wRn(rd0);
18c9b560 2593 switch ((insn >> 22) & 3) {
18c9b560
AZ
2594 case 1:
2595 if (insn & (1 << 21))
2596 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2597 else
2598 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2599 break;
2600 case 2:
2601 if (insn & (1 << 21))
2602 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2603 else
2604 gen_op_iwmmxt_packul_M0_wRn(rd1);
2605 break;
2606 case 3:
2607 if (insn & (1 << 21))
2608 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2609 else
2610 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2611 break;
2612 }
2613 gen_op_iwmmxt_movq_wRn_M0(wrd);
2614 gen_op_iwmmxt_set_mup();
2615 gen_op_iwmmxt_set_cup();
2616 break;
2617 case 0x201: case 0x203: case 0x205: case 0x207:
2618 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2619 case 0x211: case 0x213: case 0x215: case 0x217:
2620 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2621 wrd = (insn >> 5) & 0xf;
2622 rd0 = (insn >> 12) & 0xf;
2623 rd1 = (insn >> 0) & 0xf;
2624 if (rd0 == 0xf || rd1 == 0xf)
2625 return 1;
2626 gen_op_iwmmxt_movq_M0_wRn(wrd);
da6b5335
FN
2627 tmp = load_reg(s, rd0);
2628 tmp2 = load_reg(s, rd1);
18c9b560
AZ
2629 switch ((insn >> 16) & 0xf) {
2630 case 0x0: /* TMIA */
da6b5335 2631 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2632 break;
2633 case 0x8: /* TMIAPH */
da6b5335 2634 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2635 break;
2636 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
18c9b560 2637 if (insn & (1 << 16))
da6b5335 2638 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2639 if (insn & (1 << 17))
da6b5335
FN
2640 tcg_gen_shri_i32(tmp2, tmp2, 16);
2641 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2642 break;
2643 default:
7d1b0095
PM
2644 tcg_temp_free_i32(tmp2);
2645 tcg_temp_free_i32(tmp);
18c9b560
AZ
2646 return 1;
2647 }
7d1b0095
PM
2648 tcg_temp_free_i32(tmp2);
2649 tcg_temp_free_i32(tmp);
18c9b560
AZ
2650 gen_op_iwmmxt_movq_wRn_M0(wrd);
2651 gen_op_iwmmxt_set_mup();
2652 break;
2653 default:
2654 return 1;
2655 }
2656
2657 return 0;
2658}
2659
a1c7273b 2660/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
18c9b560 2661 (ie. an undefined instruction). */
7dcc1f89 2662static int disas_dsp_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
2663{
2664 int acc, rd0, rd1, rdhi, rdlo;
39d5492a 2665 TCGv_i32 tmp, tmp2;
18c9b560
AZ
2666
2667 if ((insn & 0x0ff00f10) == 0x0e200010) {
2668 /* Multiply with Internal Accumulate Format */
2669 rd0 = (insn >> 12) & 0xf;
2670 rd1 = insn & 0xf;
2671 acc = (insn >> 5) & 7;
2672
2673 if (acc != 0)
2674 return 1;
2675
3a554c0f
FN
2676 tmp = load_reg(s, rd0);
2677 tmp2 = load_reg(s, rd1);
18c9b560
AZ
2678 switch ((insn >> 16) & 0xf) {
2679 case 0x0: /* MIA */
3a554c0f 2680 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2681 break;
2682 case 0x8: /* MIAPH */
3a554c0f 2683 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2684 break;
2685 case 0xc: /* MIABB */
2686 case 0xd: /* MIABT */
2687 case 0xe: /* MIATB */
2688 case 0xf: /* MIATT */
18c9b560 2689 if (insn & (1 << 16))
3a554c0f 2690 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2691 if (insn & (1 << 17))
3a554c0f
FN
2692 tcg_gen_shri_i32(tmp2, tmp2, 16);
2693 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2694 break;
2695 default:
2696 return 1;
2697 }
7d1b0095
PM
2698 tcg_temp_free_i32(tmp2);
2699 tcg_temp_free_i32(tmp);
18c9b560
AZ
2700
2701 gen_op_iwmmxt_movq_wRn_M0(acc);
2702 return 0;
2703 }
2704
2705 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2706 /* Internal Accumulator Access Format */
2707 rdhi = (insn >> 16) & 0xf;
2708 rdlo = (insn >> 12) & 0xf;
2709 acc = insn & 7;
2710
2711 if (acc != 0)
2712 return 1;
2713
2714 if (insn & ARM_CP_RW_BIT) { /* MRA */
3a554c0f 2715 iwmmxt_load_reg(cpu_V0, acc);
ecc7b3aa 2716 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
3a554c0f 2717 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 2718 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
3a554c0f 2719 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
18c9b560 2720 } else { /* MAR */
3a554c0f
FN
2721 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2722 iwmmxt_store_reg(cpu_V0, acc);
18c9b560
AZ
2723 }
2724 return 0;
2725 }
2726
2727 return 1;
2728}
2729
9ee6e8bb
PB
2730#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2731#define VFP_SREG(insn, bigbit, smallbit) \
2732 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2733#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
d614a513 2734 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
9ee6e8bb
PB
2735 reg = (((insn) >> (bigbit)) & 0x0f) \
2736 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2737 } else { \
2738 if (insn & (1 << (smallbit))) \
2739 return 1; \
2740 reg = ((insn) >> (bigbit)) & 0x0f; \
2741 }} while (0)
2742
2743#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2744#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2745#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2746#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2747#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2748#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2749
4373f3ce 2750/* Move between integer and VFP cores. */
39d5492a 2751static TCGv_i32 gen_vfp_mrs(void)
4373f3ce 2752{
39d5492a 2753 TCGv_i32 tmp = tcg_temp_new_i32();
4373f3ce
PB
2754 tcg_gen_mov_i32(tmp, cpu_F0s);
2755 return tmp;
2756}
2757
39d5492a 2758static void gen_vfp_msr(TCGv_i32 tmp)
4373f3ce
PB
2759{
2760 tcg_gen_mov_i32(cpu_F0s, tmp);
7d1b0095 2761 tcg_temp_free_i32(tmp);
4373f3ce
PB
2762}
2763
39d5492a 2764static void gen_neon_dup_u8(TCGv_i32 var, int shift)
ad69471c 2765{
39d5492a 2766 TCGv_i32 tmp = tcg_temp_new_i32();
ad69471c
PB
2767 if (shift)
2768 tcg_gen_shri_i32(var, var, shift);
86831435 2769 tcg_gen_ext8u_i32(var, var);
ad69471c
PB
2770 tcg_gen_shli_i32(tmp, var, 8);
2771 tcg_gen_or_i32(var, var, tmp);
2772 tcg_gen_shli_i32(tmp, var, 16);
2773 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2774 tcg_temp_free_i32(tmp);
ad69471c
PB
2775}
2776
39d5492a 2777static void gen_neon_dup_low16(TCGv_i32 var)
ad69471c 2778{
39d5492a 2779 TCGv_i32 tmp = tcg_temp_new_i32();
86831435 2780 tcg_gen_ext16u_i32(var, var);
ad69471c
PB
2781 tcg_gen_shli_i32(tmp, var, 16);
2782 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2783 tcg_temp_free_i32(tmp);
ad69471c
PB
2784}
2785
39d5492a 2786static void gen_neon_dup_high16(TCGv_i32 var)
ad69471c 2787{
39d5492a 2788 TCGv_i32 tmp = tcg_temp_new_i32();
ad69471c
PB
2789 tcg_gen_andi_i32(var, var, 0xffff0000);
2790 tcg_gen_shri_i32(tmp, var, 16);
2791 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2792 tcg_temp_free_i32(tmp);
ad69471c
PB
2793}
2794
39d5492a 2795static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
8e18cde3
PM
2796{
2797 /* Load a single Neon element and replicate into a 32 bit TCG reg */
58ab8e96 2798 TCGv_i32 tmp = tcg_temp_new_i32();
8e18cde3
PM
2799 switch (size) {
2800 case 0:
12dcc321 2801 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
8e18cde3
PM
2802 gen_neon_dup_u8(tmp, 0);
2803 break;
2804 case 1:
12dcc321 2805 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
8e18cde3
PM
2806 gen_neon_dup_low16(tmp);
2807 break;
2808 case 2:
12dcc321 2809 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
8e18cde3
PM
2810 break;
2811 default: /* Avoid compiler warnings. */
2812 abort();
2813 }
2814 return tmp;
2815}
2816
04731fb5
WN
2817static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
2818 uint32_t dp)
2819{
2820 uint32_t cc = extract32(insn, 20, 2);
2821
2822 if (dp) {
2823 TCGv_i64 frn, frm, dest;
2824 TCGv_i64 tmp, zero, zf, nf, vf;
2825
2826 zero = tcg_const_i64(0);
2827
2828 frn = tcg_temp_new_i64();
2829 frm = tcg_temp_new_i64();
2830 dest = tcg_temp_new_i64();
2831
2832 zf = tcg_temp_new_i64();
2833 nf = tcg_temp_new_i64();
2834 vf = tcg_temp_new_i64();
2835
2836 tcg_gen_extu_i32_i64(zf, cpu_ZF);
2837 tcg_gen_ext_i32_i64(nf, cpu_NF);
2838 tcg_gen_ext_i32_i64(vf, cpu_VF);
2839
2840 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2841 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2842 switch (cc) {
2843 case 0: /* eq: Z */
2844 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
2845 frn, frm);
2846 break;
2847 case 1: /* vs: V */
2848 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
2849 frn, frm);
2850 break;
2851 case 2: /* ge: N == V -> N ^ V == 0 */
2852 tmp = tcg_temp_new_i64();
2853 tcg_gen_xor_i64(tmp, vf, nf);
2854 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2855 frn, frm);
2856 tcg_temp_free_i64(tmp);
2857 break;
2858 case 3: /* gt: !Z && N == V */
2859 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
2860 frn, frm);
2861 tmp = tcg_temp_new_i64();
2862 tcg_gen_xor_i64(tmp, vf, nf);
2863 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2864 dest, frm);
2865 tcg_temp_free_i64(tmp);
2866 break;
2867 }
2868 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2869 tcg_temp_free_i64(frn);
2870 tcg_temp_free_i64(frm);
2871 tcg_temp_free_i64(dest);
2872
2873 tcg_temp_free_i64(zf);
2874 tcg_temp_free_i64(nf);
2875 tcg_temp_free_i64(vf);
2876
2877 tcg_temp_free_i64(zero);
2878 } else {
2879 TCGv_i32 frn, frm, dest;
2880 TCGv_i32 tmp, zero;
2881
2882 zero = tcg_const_i32(0);
2883
2884 frn = tcg_temp_new_i32();
2885 frm = tcg_temp_new_i32();
2886 dest = tcg_temp_new_i32();
2887 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2888 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2889 switch (cc) {
2890 case 0: /* eq: Z */
2891 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
2892 frn, frm);
2893 break;
2894 case 1: /* vs: V */
2895 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
2896 frn, frm);
2897 break;
2898 case 2: /* ge: N == V -> N ^ V == 0 */
2899 tmp = tcg_temp_new_i32();
2900 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2901 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2902 frn, frm);
2903 tcg_temp_free_i32(tmp);
2904 break;
2905 case 3: /* gt: !Z && N == V */
2906 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
2907 frn, frm);
2908 tmp = tcg_temp_new_i32();
2909 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2910 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2911 dest, frm);
2912 tcg_temp_free_i32(tmp);
2913 break;
2914 }
2915 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2916 tcg_temp_free_i32(frn);
2917 tcg_temp_free_i32(frm);
2918 tcg_temp_free_i32(dest);
2919
2920 tcg_temp_free_i32(zero);
2921 }
2922
2923 return 0;
2924}
2925
40cfacdd
WN
2926static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
2927 uint32_t rm, uint32_t dp)
2928{
2929 uint32_t vmin = extract32(insn, 6, 1);
2930 TCGv_ptr fpst = get_fpstatus_ptr(0);
2931
2932 if (dp) {
2933 TCGv_i64 frn, frm, dest;
2934
2935 frn = tcg_temp_new_i64();
2936 frm = tcg_temp_new_i64();
2937 dest = tcg_temp_new_i64();
2938
2939 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2940 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2941 if (vmin) {
f71a2ae5 2942 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
40cfacdd 2943 } else {
f71a2ae5 2944 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
40cfacdd
WN
2945 }
2946 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2947 tcg_temp_free_i64(frn);
2948 tcg_temp_free_i64(frm);
2949 tcg_temp_free_i64(dest);
2950 } else {
2951 TCGv_i32 frn, frm, dest;
2952
2953 frn = tcg_temp_new_i32();
2954 frm = tcg_temp_new_i32();
2955 dest = tcg_temp_new_i32();
2956
2957 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2958 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2959 if (vmin) {
f71a2ae5 2960 gen_helper_vfp_minnums(dest, frn, frm, fpst);
40cfacdd 2961 } else {
f71a2ae5 2962 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
40cfacdd
WN
2963 }
2964 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2965 tcg_temp_free_i32(frn);
2966 tcg_temp_free_i32(frm);
2967 tcg_temp_free_i32(dest);
2968 }
2969
2970 tcg_temp_free_ptr(fpst);
2971 return 0;
2972}
2973
7655f39b
WN
2974static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2975 int rounding)
2976{
2977 TCGv_ptr fpst = get_fpstatus_ptr(0);
2978 TCGv_i32 tcg_rmode;
2979
2980 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2981 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2982
2983 if (dp) {
2984 TCGv_i64 tcg_op;
2985 TCGv_i64 tcg_res;
2986 tcg_op = tcg_temp_new_i64();
2987 tcg_res = tcg_temp_new_i64();
2988 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2989 gen_helper_rintd(tcg_res, tcg_op, fpst);
2990 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2991 tcg_temp_free_i64(tcg_op);
2992 tcg_temp_free_i64(tcg_res);
2993 } else {
2994 TCGv_i32 tcg_op;
2995 TCGv_i32 tcg_res;
2996 tcg_op = tcg_temp_new_i32();
2997 tcg_res = tcg_temp_new_i32();
2998 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2999 gen_helper_rints(tcg_res, tcg_op, fpst);
3000 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3001 tcg_temp_free_i32(tcg_op);
3002 tcg_temp_free_i32(tcg_res);
3003 }
3004
3005 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3006 tcg_temp_free_i32(tcg_rmode);
3007
3008 tcg_temp_free_ptr(fpst);
3009 return 0;
3010}
3011
c9975a83
WN
3012static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3013 int rounding)
3014{
3015 bool is_signed = extract32(insn, 7, 1);
3016 TCGv_ptr fpst = get_fpstatus_ptr(0);
3017 TCGv_i32 tcg_rmode, tcg_shift;
3018
3019 tcg_shift = tcg_const_i32(0);
3020
3021 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
3022 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3023
3024 if (dp) {
3025 TCGv_i64 tcg_double, tcg_res;
3026 TCGv_i32 tcg_tmp;
3027 /* Rd is encoded as a single precision register even when the source
3028 * is double precision.
3029 */
3030 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
3031 tcg_double = tcg_temp_new_i64();
3032 tcg_res = tcg_temp_new_i64();
3033 tcg_tmp = tcg_temp_new_i32();
3034 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
3035 if (is_signed) {
3036 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
3037 } else {
3038 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
3039 }
ecc7b3aa 3040 tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
c9975a83
WN
3041 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
3042 tcg_temp_free_i32(tcg_tmp);
3043 tcg_temp_free_i64(tcg_res);
3044 tcg_temp_free_i64(tcg_double);
3045 } else {
3046 TCGv_i32 tcg_single, tcg_res;
3047 tcg_single = tcg_temp_new_i32();
3048 tcg_res = tcg_temp_new_i32();
3049 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
3050 if (is_signed) {
3051 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
3052 } else {
3053 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
3054 }
3055 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
3056 tcg_temp_free_i32(tcg_res);
3057 tcg_temp_free_i32(tcg_single);
3058 }
3059
3060 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3061 tcg_temp_free_i32(tcg_rmode);
3062
3063 tcg_temp_free_i32(tcg_shift);
3064
3065 tcg_temp_free_ptr(fpst);
3066
3067 return 0;
3068}
7655f39b
WN
3069
3070/* Table for converting the most common AArch32 encoding of
3071 * rounding mode to arm_fprounding order (which matches the
3072 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
3073 */
3074static const uint8_t fp_decode_rm[] = {
3075 FPROUNDING_TIEAWAY,
3076 FPROUNDING_TIEEVEN,
3077 FPROUNDING_POSINF,
3078 FPROUNDING_NEGINF,
3079};
3080
7dcc1f89 3081static int disas_vfp_v8_insn(DisasContext *s, uint32_t insn)
04731fb5
WN
3082{
3083 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
3084
d614a513 3085 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
04731fb5
WN
3086 return 1;
3087 }
3088
3089 if (dp) {
3090 VFP_DREG_D(rd, insn);
3091 VFP_DREG_N(rn, insn);
3092 VFP_DREG_M(rm, insn);
3093 } else {
3094 rd = VFP_SREG_D(insn);
3095 rn = VFP_SREG_N(insn);
3096 rm = VFP_SREG_M(insn);
3097 }
3098
3099 if ((insn & 0x0f800e50) == 0x0e000a00) {
3100 return handle_vsel(insn, rd, rn, rm, dp);
40cfacdd
WN
3101 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
3102 return handle_vminmaxnm(insn, rd, rn, rm, dp);
7655f39b
WN
3103 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
3104 /* VRINTA, VRINTN, VRINTP, VRINTM */
3105 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3106 return handle_vrint(insn, rd, rm, dp, rounding);
c9975a83
WN
3107 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
3108 /* VCVTA, VCVTN, VCVTP, VCVTM */
3109 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3110 return handle_vcvt(insn, rd, rm, dp, rounding);
04731fb5
WN
3111 }
3112 return 1;
3113}
3114
a1c7273b 3115/* Disassemble a VFP instruction. Returns nonzero if an error occurred
b7bcbe95 3116 (ie. an undefined instruction). */
7dcc1f89 3117static int disas_vfp_insn(DisasContext *s, uint32_t insn)
b7bcbe95
FB
3118{
3119 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
3120 int dp, veclen;
39d5492a
PM
3121 TCGv_i32 addr;
3122 TCGv_i32 tmp;
3123 TCGv_i32 tmp2;
b7bcbe95 3124
d614a513 3125 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
40f137e1 3126 return 1;
d614a513 3127 }
40f137e1 3128
2c7ffc41
PM
3129 /* FIXME: this access check should not take precedence over UNDEF
3130 * for invalid encodings; we will generate incorrect syndrome information
3131 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3132 */
9dbbc748 3133 if (s->fp_excp_el) {
2c7ffc41 3134 gen_exception_insn(s, 4, EXCP_UDEF,
7d197d2d 3135 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
3136 return 0;
3137 }
3138
5df8bac1 3139 if (!s->vfp_enabled) {
9ee6e8bb 3140 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
40f137e1
PB
3141 if ((insn & 0x0fe00fff) != 0x0ee00a10)
3142 return 1;
3143 rn = (insn >> 16) & 0xf;
a50c0f51
PM
3144 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
3145 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
40f137e1 3146 return 1;
a50c0f51 3147 }
40f137e1 3148 }
6a57f3eb
WN
3149
3150 if (extract32(insn, 28, 4) == 0xf) {
3151 /* Encodings with T=1 (Thumb) or unconditional (ARM):
3152 * only used in v8 and above.
3153 */
7dcc1f89 3154 return disas_vfp_v8_insn(s, insn);
6a57f3eb
WN
3155 }
3156
b7bcbe95
FB
3157 dp = ((insn & 0xf00) == 0xb00);
3158 switch ((insn >> 24) & 0xf) {
3159 case 0xe:
3160 if (insn & (1 << 4)) {
3161 /* single register transfer */
b7bcbe95
FB
3162 rd = (insn >> 12) & 0xf;
3163 if (dp) {
9ee6e8bb
PB
3164 int size;
3165 int pass;
3166
3167 VFP_DREG_N(rn, insn);
3168 if (insn & 0xf)
b7bcbe95 3169 return 1;
9ee6e8bb 3170 if (insn & 0x00c00060
d614a513 3171 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 3172 return 1;
d614a513 3173 }
9ee6e8bb
PB
3174
3175 pass = (insn >> 21) & 1;
3176 if (insn & (1 << 22)) {
3177 size = 0;
3178 offset = ((insn >> 5) & 3) * 8;
3179 } else if (insn & (1 << 5)) {
3180 size = 1;
3181 offset = (insn & (1 << 6)) ? 16 : 0;
3182 } else {
3183 size = 2;
3184 offset = 0;
3185 }
18c9b560 3186 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 3187 /* vfp->arm */
ad69471c 3188 tmp = neon_load_reg(rn, pass);
9ee6e8bb
PB
3189 switch (size) {
3190 case 0:
9ee6e8bb 3191 if (offset)
ad69471c 3192 tcg_gen_shri_i32(tmp, tmp, offset);
9ee6e8bb 3193 if (insn & (1 << 23))
ad69471c 3194 gen_uxtb(tmp);
9ee6e8bb 3195 else
ad69471c 3196 gen_sxtb(tmp);
9ee6e8bb
PB
3197 break;
3198 case 1:
9ee6e8bb
PB
3199 if (insn & (1 << 23)) {
3200 if (offset) {
ad69471c 3201 tcg_gen_shri_i32(tmp, tmp, 16);
9ee6e8bb 3202 } else {
ad69471c 3203 gen_uxth(tmp);
9ee6e8bb
PB
3204 }
3205 } else {
3206 if (offset) {
ad69471c 3207 tcg_gen_sari_i32(tmp, tmp, 16);
9ee6e8bb 3208 } else {
ad69471c 3209 gen_sxth(tmp);
9ee6e8bb
PB
3210 }
3211 }
3212 break;
3213 case 2:
9ee6e8bb
PB
3214 break;
3215 }
ad69471c 3216 store_reg(s, rd, tmp);
b7bcbe95
FB
3217 } else {
3218 /* arm->vfp */
ad69471c 3219 tmp = load_reg(s, rd);
9ee6e8bb
PB
3220 if (insn & (1 << 23)) {
3221 /* VDUP */
3222 if (size == 0) {
ad69471c 3223 gen_neon_dup_u8(tmp, 0);
9ee6e8bb 3224 } else if (size == 1) {
ad69471c 3225 gen_neon_dup_low16(tmp);
9ee6e8bb 3226 }
cbbccffc 3227 for (n = 0; n <= pass * 2; n++) {
7d1b0095 3228 tmp2 = tcg_temp_new_i32();
cbbccffc
PB
3229 tcg_gen_mov_i32(tmp2, tmp);
3230 neon_store_reg(rn, n, tmp2);
3231 }
3232 neon_store_reg(rn, n, tmp);
9ee6e8bb
PB
3233 } else {
3234 /* VMOV */
3235 switch (size) {
3236 case 0:
ad69471c 3237 tmp2 = neon_load_reg(rn, pass);
d593c48e 3238 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
7d1b0095 3239 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
3240 break;
3241 case 1:
ad69471c 3242 tmp2 = neon_load_reg(rn, pass);
d593c48e 3243 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
7d1b0095 3244 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
3245 break;
3246 case 2:
9ee6e8bb
PB
3247 break;
3248 }
ad69471c 3249 neon_store_reg(rn, pass, tmp);
9ee6e8bb 3250 }
b7bcbe95 3251 }
9ee6e8bb
PB
3252 } else { /* !dp */
3253 if ((insn & 0x6f) != 0x00)
3254 return 1;
3255 rn = VFP_SREG_N(insn);
18c9b560 3256 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
3257 /* vfp->arm */
3258 if (insn & (1 << 21)) {
3259 /* system register */
40f137e1 3260 rn >>= 1;
9ee6e8bb 3261
b7bcbe95 3262 switch (rn) {
40f137e1 3263 case ARM_VFP_FPSID:
4373f3ce 3264 /* VFP2 allows access to FSID from userspace.
9ee6e8bb
PB
3265 VFP3 restricts all id registers to privileged
3266 accesses. */
3267 if (IS_USER(s)
d614a513 3268 && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
9ee6e8bb 3269 return 1;
d614a513 3270 }
4373f3ce 3271 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3272 break;
40f137e1 3273 case ARM_VFP_FPEXC:
9ee6e8bb
PB
3274 if (IS_USER(s))
3275 return 1;
4373f3ce 3276 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3277 break;
40f137e1
PB
3278 case ARM_VFP_FPINST:
3279 case ARM_VFP_FPINST2:
9ee6e8bb
PB
3280 /* Not present in VFP3. */
3281 if (IS_USER(s)
d614a513 3282 || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
9ee6e8bb 3283 return 1;
d614a513 3284 }
4373f3ce 3285 tmp = load_cpu_field(vfp.xregs[rn]);
b7bcbe95 3286 break;
40f137e1 3287 case ARM_VFP_FPSCR:
601d70b9 3288 if (rd == 15) {
4373f3ce
PB
3289 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3290 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3291 } else {
7d1b0095 3292 tmp = tcg_temp_new_i32();
4373f3ce
PB
3293 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3294 }
b7bcbe95 3295 break;
a50c0f51 3296 case ARM_VFP_MVFR2:
d614a513 3297 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
a50c0f51
PM
3298 return 1;
3299 }
3300 /* fall through */
9ee6e8bb
PB
3301 case ARM_VFP_MVFR0:
3302 case ARM_VFP_MVFR1:
3303 if (IS_USER(s)
d614a513 3304 || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
9ee6e8bb 3305 return 1;
d614a513 3306 }
4373f3ce 3307 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3308 break;
b7bcbe95
FB
3309 default:
3310 return 1;
3311 }
3312 } else {
3313 gen_mov_F0_vreg(0, rn);
4373f3ce 3314 tmp = gen_vfp_mrs();
b7bcbe95
FB
3315 }
3316 if (rd == 15) {
b5ff1b31 3317 /* Set the 4 flag bits in the CPSR. */
4373f3ce 3318 gen_set_nzcv(tmp);
7d1b0095 3319 tcg_temp_free_i32(tmp);
4373f3ce
PB
3320 } else {
3321 store_reg(s, rd, tmp);
3322 }
b7bcbe95
FB
3323 } else {
3324 /* arm->vfp */
b7bcbe95 3325 if (insn & (1 << 21)) {
40f137e1 3326 rn >>= 1;
b7bcbe95
FB
3327 /* system register */
3328 switch (rn) {
40f137e1 3329 case ARM_VFP_FPSID:
9ee6e8bb
PB
3330 case ARM_VFP_MVFR0:
3331 case ARM_VFP_MVFR1:
b7bcbe95
FB
3332 /* Writes are ignored. */
3333 break;
40f137e1 3334 case ARM_VFP_FPSCR:
e4c1cfa5 3335 tmp = load_reg(s, rd);
4373f3ce 3336 gen_helper_vfp_set_fpscr(cpu_env, tmp);
7d1b0095 3337 tcg_temp_free_i32(tmp);
b5ff1b31 3338 gen_lookup_tb(s);
b7bcbe95 3339 break;
40f137e1 3340 case ARM_VFP_FPEXC:
9ee6e8bb
PB
3341 if (IS_USER(s))
3342 return 1;
71b3c3de
JR
3343 /* TODO: VFP subarchitecture support.
3344 * For now, keep the EN bit only */
e4c1cfa5 3345 tmp = load_reg(s, rd);
71b3c3de 3346 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
4373f3ce 3347 store_cpu_field(tmp, vfp.xregs[rn]);
40f137e1
PB
3348 gen_lookup_tb(s);
3349 break;
3350 case ARM_VFP_FPINST:
3351 case ARM_VFP_FPINST2:
23adb861
PM
3352 if (IS_USER(s)) {
3353 return 1;
3354 }
e4c1cfa5 3355 tmp = load_reg(s, rd);
4373f3ce 3356 store_cpu_field(tmp, vfp.xregs[rn]);
40f137e1 3357 break;
b7bcbe95
FB
3358 default:
3359 return 1;
3360 }
3361 } else {
e4c1cfa5 3362 tmp = load_reg(s, rd);
4373f3ce 3363 gen_vfp_msr(tmp);
b7bcbe95
FB
3364 gen_mov_vreg_F0(0, rn);
3365 }
3366 }
3367 }
3368 } else {
3369 /* data processing */
3370 /* The opcode is in bits 23, 21, 20 and 6. */
3371 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3372 if (dp) {
3373 if (op == 15) {
3374 /* rn is opcode */
3375 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3376 } else {
3377 /* rn is register number */
9ee6e8bb 3378 VFP_DREG_N(rn, insn);
b7bcbe95
FB
3379 }
3380
239c20c7
WN
3381 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
3382 ((rn & 0x1e) == 0x6))) {
3383 /* Integer or single/half precision destination. */
9ee6e8bb 3384 rd = VFP_SREG_D(insn);
b7bcbe95 3385 } else {
9ee6e8bb 3386 VFP_DREG_D(rd, insn);
b7bcbe95 3387 }
04595bf6 3388 if (op == 15 &&
239c20c7
WN
3389 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
3390 ((rn & 0x1e) == 0x4))) {
3391 /* VCVT from int or half precision is always from S reg
3392 * regardless of dp bit. VCVT with immediate frac_bits
3393 * has same format as SREG_M.
04595bf6
PM
3394 */
3395 rm = VFP_SREG_M(insn);
b7bcbe95 3396 } else {
9ee6e8bb 3397 VFP_DREG_M(rm, insn);
b7bcbe95
FB
3398 }
3399 } else {
9ee6e8bb 3400 rn = VFP_SREG_N(insn);
b7bcbe95
FB
3401 if (op == 15 && rn == 15) {
3402 /* Double precision destination. */
9ee6e8bb
PB
3403 VFP_DREG_D(rd, insn);
3404 } else {
3405 rd = VFP_SREG_D(insn);
3406 }
04595bf6
PM
3407 /* NB that we implicitly rely on the encoding for the frac_bits
3408 * in VCVT of fixed to float being the same as that of an SREG_M
3409 */
9ee6e8bb 3410 rm = VFP_SREG_M(insn);
b7bcbe95
FB
3411 }
3412
69d1fc22 3413 veclen = s->vec_len;
b7bcbe95
FB
3414 if (op == 15 && rn > 3)
3415 veclen = 0;
3416
3417 /* Shut up compiler warnings. */
3418 delta_m = 0;
3419 delta_d = 0;
3420 bank_mask = 0;
3b46e624 3421
b7bcbe95
FB
3422 if (veclen > 0) {
3423 if (dp)
3424 bank_mask = 0xc;
3425 else
3426 bank_mask = 0x18;
3427
3428 /* Figure out what type of vector operation this is. */
3429 if ((rd & bank_mask) == 0) {
3430 /* scalar */
3431 veclen = 0;
3432 } else {
3433 if (dp)
69d1fc22 3434 delta_d = (s->vec_stride >> 1) + 1;
b7bcbe95 3435 else
69d1fc22 3436 delta_d = s->vec_stride + 1;
b7bcbe95
FB
3437
3438 if ((rm & bank_mask) == 0) {
3439 /* mixed scalar/vector */
3440 delta_m = 0;
3441 } else {
3442 /* vector */
3443 delta_m = delta_d;
3444 }
3445 }
3446 }
3447
3448 /* Load the initial operands. */
3449 if (op == 15) {
3450 switch (rn) {
3451 case 16:
3452 case 17:
3453 /* Integer source */
3454 gen_mov_F0_vreg(0, rm);
3455 break;
3456 case 8:
3457 case 9:
3458 /* Compare */
3459 gen_mov_F0_vreg(dp, rd);
3460 gen_mov_F1_vreg(dp, rm);
3461 break;
3462 case 10:
3463 case 11:
3464 /* Compare with zero */
3465 gen_mov_F0_vreg(dp, rd);
3466 gen_vfp_F1_ld0(dp);
3467 break;
9ee6e8bb
PB
3468 case 20:
3469 case 21:
3470 case 22:
3471 case 23:
644ad806
PB
3472 case 28:
3473 case 29:
3474 case 30:
3475 case 31:
9ee6e8bb
PB
3476 /* Source and destination the same. */
3477 gen_mov_F0_vreg(dp, rd);
3478 break;
6e0c0ed1
PM
3479 case 4:
3480 case 5:
3481 case 6:
3482 case 7:
239c20c7
WN
3483 /* VCVTB, VCVTT: only present with the halfprec extension
3484 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3485 * (we choose to UNDEF)
6e0c0ed1 3486 */
d614a513
PM
3487 if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
3488 !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
6e0c0ed1
PM
3489 return 1;
3490 }
239c20c7
WN
3491 if (!extract32(rn, 1, 1)) {
3492 /* Half precision source. */
3493 gen_mov_F0_vreg(0, rm);
3494 break;
3495 }
6e0c0ed1 3496 /* Otherwise fall through */
b7bcbe95
FB
3497 default:
3498 /* One source operand. */
3499 gen_mov_F0_vreg(dp, rm);
9ee6e8bb 3500 break;
b7bcbe95
FB
3501 }
3502 } else {
3503 /* Two source operands. */
3504 gen_mov_F0_vreg(dp, rn);
3505 gen_mov_F1_vreg(dp, rm);
3506 }
3507
3508 for (;;) {
3509 /* Perform the calculation. */
3510 switch (op) {
605a6aed
PM
3511 case 0: /* VMLA: fd + (fn * fm) */
3512 /* Note that order of inputs to the add matters for NaNs */
3513 gen_vfp_F1_mul(dp);
3514 gen_mov_F0_vreg(dp, rd);
b7bcbe95
FB
3515 gen_vfp_add(dp);
3516 break;
605a6aed 3517 case 1: /* VMLS: fd + -(fn * fm) */
b7bcbe95 3518 gen_vfp_mul(dp);
605a6aed
PM
3519 gen_vfp_F1_neg(dp);
3520 gen_mov_F0_vreg(dp, rd);
b7bcbe95
FB
3521 gen_vfp_add(dp);
3522 break;
605a6aed
PM
3523 case 2: /* VNMLS: -fd + (fn * fm) */
3524 /* Note that it isn't valid to replace (-A + B) with (B - A)
3525 * or similar plausible looking simplifications
3526 * because this will give wrong results for NaNs.
3527 */
3528 gen_vfp_F1_mul(dp);
3529 gen_mov_F0_vreg(dp, rd);
3530 gen_vfp_neg(dp);
3531 gen_vfp_add(dp);
b7bcbe95 3532 break;
605a6aed 3533 case 3: /* VNMLA: -fd + -(fn * fm) */
b7bcbe95 3534 gen_vfp_mul(dp);
605a6aed
PM
3535 gen_vfp_F1_neg(dp);
3536 gen_mov_F0_vreg(dp, rd);
b7bcbe95 3537 gen_vfp_neg(dp);
605a6aed 3538 gen_vfp_add(dp);
b7bcbe95
FB
3539 break;
3540 case 4: /* mul: fn * fm */
3541 gen_vfp_mul(dp);
3542 break;
3543 case 5: /* nmul: -(fn * fm) */
3544 gen_vfp_mul(dp);
3545 gen_vfp_neg(dp);
3546 break;
3547 case 6: /* add: fn + fm */
3548 gen_vfp_add(dp);
3549 break;
3550 case 7: /* sub: fn - fm */
3551 gen_vfp_sub(dp);
3552 break;
3553 case 8: /* div: fn / fm */
3554 gen_vfp_div(dp);
3555 break;
da97f52c
PM
3556 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3557 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3558 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3559 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3560 /* These are fused multiply-add, and must be done as one
3561 * floating point operation with no rounding between the
3562 * multiplication and addition steps.
3563 * NB that doing the negations here as separate steps is
3564 * correct : an input NaN should come out with its sign bit
3565 * flipped if it is a negated-input.
3566 */
d614a513 3567 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
da97f52c
PM
3568 return 1;
3569 }
3570 if (dp) {
3571 TCGv_ptr fpst;
3572 TCGv_i64 frd;
3573 if (op & 1) {
3574 /* VFNMS, VFMS */
3575 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3576 }
3577 frd = tcg_temp_new_i64();
3578 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3579 if (op & 2) {
3580 /* VFNMA, VFNMS */
3581 gen_helper_vfp_negd(frd, frd);
3582 }
3583 fpst = get_fpstatus_ptr(0);
3584 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3585 cpu_F1d, frd, fpst);
3586 tcg_temp_free_ptr(fpst);
3587 tcg_temp_free_i64(frd);
3588 } else {
3589 TCGv_ptr fpst;
3590 TCGv_i32 frd;
3591 if (op & 1) {
3592 /* VFNMS, VFMS */
3593 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3594 }
3595 frd = tcg_temp_new_i32();
3596 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3597 if (op & 2) {
3598 gen_helper_vfp_negs(frd, frd);
3599 }
3600 fpst = get_fpstatus_ptr(0);
3601 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3602 cpu_F1s, frd, fpst);
3603 tcg_temp_free_ptr(fpst);
3604 tcg_temp_free_i32(frd);
3605 }
3606 break;
9ee6e8bb 3607 case 14: /* fconst */
d614a513
PM
3608 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3609 return 1;
3610 }
9ee6e8bb
PB
3611
3612 n = (insn << 12) & 0x80000000;
3613 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3614 if (dp) {
3615 if (i & 0x40)
3616 i |= 0x3f80;
3617 else
3618 i |= 0x4000;
3619 n |= i << 16;
4373f3ce 3620 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
9ee6e8bb
PB
3621 } else {
3622 if (i & 0x40)
3623 i |= 0x780;
3624 else
3625 i |= 0x800;
3626 n |= i << 19;
5b340b51 3627 tcg_gen_movi_i32(cpu_F0s, n);
9ee6e8bb 3628 }
9ee6e8bb 3629 break;
b7bcbe95
FB
3630 case 15: /* extension space */
3631 switch (rn) {
3632 case 0: /* cpy */
3633 /* no-op */
3634 break;
3635 case 1: /* abs */
3636 gen_vfp_abs(dp);
3637 break;
3638 case 2: /* neg */
3639 gen_vfp_neg(dp);
3640 break;
3641 case 3: /* sqrt */
3642 gen_vfp_sqrt(dp);
3643 break;
239c20c7 3644 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
60011498
PB
3645 tmp = gen_vfp_mrs();
3646 tcg_gen_ext16u_i32(tmp, tmp);
239c20c7
WN
3647 if (dp) {
3648 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3649 cpu_env);
3650 } else {
3651 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3652 cpu_env);
3653 }
7d1b0095 3654 tcg_temp_free_i32(tmp);
60011498 3655 break;
239c20c7 3656 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
60011498
PB
3657 tmp = gen_vfp_mrs();
3658 tcg_gen_shri_i32(tmp, tmp, 16);
239c20c7
WN
3659 if (dp) {
3660 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3661 cpu_env);
3662 } else {
3663 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3664 cpu_env);
3665 }
7d1b0095 3666 tcg_temp_free_i32(tmp);
60011498 3667 break;
239c20c7 3668 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
7d1b0095 3669 tmp = tcg_temp_new_i32();
239c20c7
WN
3670 if (dp) {
3671 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3672 cpu_env);
3673 } else {
3674 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3675 cpu_env);
3676 }
60011498
PB
3677 gen_mov_F0_vreg(0, rd);
3678 tmp2 = gen_vfp_mrs();
3679 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3680 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 3681 tcg_temp_free_i32(tmp2);
60011498
PB
3682 gen_vfp_msr(tmp);
3683 break;
239c20c7 3684 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
7d1b0095 3685 tmp = tcg_temp_new_i32();
239c20c7
WN
3686 if (dp) {
3687 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3688 cpu_env);
3689 } else {
3690 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3691 cpu_env);
3692 }
60011498
PB
3693 tcg_gen_shli_i32(tmp, tmp, 16);
3694 gen_mov_F0_vreg(0, rd);
3695 tmp2 = gen_vfp_mrs();
3696 tcg_gen_ext16u_i32(tmp2, tmp2);
3697 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 3698 tcg_temp_free_i32(tmp2);
60011498
PB
3699 gen_vfp_msr(tmp);
3700 break;
b7bcbe95
FB
3701 case 8: /* cmp */
3702 gen_vfp_cmp(dp);
3703 break;
3704 case 9: /* cmpe */
3705 gen_vfp_cmpe(dp);
3706 break;
3707 case 10: /* cmpz */
3708 gen_vfp_cmp(dp);
3709 break;
3710 case 11: /* cmpez */
3711 gen_vfp_F1_ld0(dp);
3712 gen_vfp_cmpe(dp);
3713 break;
664c6733
WN
3714 case 12: /* vrintr */
3715 {
3716 TCGv_ptr fpst = get_fpstatus_ptr(0);
3717 if (dp) {
3718 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3719 } else {
3720 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3721 }
3722 tcg_temp_free_ptr(fpst);
3723 break;
3724 }
a290c62a
WN
3725 case 13: /* vrintz */
3726 {
3727 TCGv_ptr fpst = get_fpstatus_ptr(0);
3728 TCGv_i32 tcg_rmode;
3729 tcg_rmode = tcg_const_i32(float_round_to_zero);
3730 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3731 if (dp) {
3732 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3733 } else {
3734 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3735 }
3736 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3737 tcg_temp_free_i32(tcg_rmode);
3738 tcg_temp_free_ptr(fpst);
3739 break;
3740 }
4e82bc01
WN
3741 case 14: /* vrintx */
3742 {
3743 TCGv_ptr fpst = get_fpstatus_ptr(0);
3744 if (dp) {
3745 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3746 } else {
3747 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3748 }
3749 tcg_temp_free_ptr(fpst);
3750 break;
3751 }
b7bcbe95
FB
3752 case 15: /* single<->double conversion */
3753 if (dp)
4373f3ce 3754 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
b7bcbe95 3755 else
4373f3ce 3756 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
b7bcbe95
FB
3757 break;
3758 case 16: /* fuito */
5500b06c 3759 gen_vfp_uito(dp, 0);
b7bcbe95
FB
3760 break;
3761 case 17: /* fsito */
5500b06c 3762 gen_vfp_sito(dp, 0);
b7bcbe95 3763 break;
9ee6e8bb 3764 case 20: /* fshto */
d614a513
PM
3765 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3766 return 1;
3767 }
5500b06c 3768 gen_vfp_shto(dp, 16 - rm, 0);
9ee6e8bb
PB
3769 break;
3770 case 21: /* fslto */
d614a513
PM
3771 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3772 return 1;
3773 }
5500b06c 3774 gen_vfp_slto(dp, 32 - rm, 0);
9ee6e8bb
PB
3775 break;
3776 case 22: /* fuhto */
d614a513
PM
3777 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3778 return 1;
3779 }
5500b06c 3780 gen_vfp_uhto(dp, 16 - rm, 0);
9ee6e8bb
PB
3781 break;
3782 case 23: /* fulto */
d614a513
PM
3783 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3784 return 1;
3785 }
5500b06c 3786 gen_vfp_ulto(dp, 32 - rm, 0);
9ee6e8bb 3787 break;
b7bcbe95 3788 case 24: /* ftoui */
5500b06c 3789 gen_vfp_toui(dp, 0);
b7bcbe95
FB
3790 break;
3791 case 25: /* ftouiz */
5500b06c 3792 gen_vfp_touiz(dp, 0);
b7bcbe95
FB
3793 break;
3794 case 26: /* ftosi */
5500b06c 3795 gen_vfp_tosi(dp, 0);
b7bcbe95
FB
3796 break;
3797 case 27: /* ftosiz */
5500b06c 3798 gen_vfp_tosiz(dp, 0);
b7bcbe95 3799 break;
9ee6e8bb 3800 case 28: /* ftosh */
d614a513
PM
3801 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3802 return 1;
3803 }
5500b06c 3804 gen_vfp_tosh(dp, 16 - rm, 0);
9ee6e8bb
PB
3805 break;
3806 case 29: /* ftosl */
d614a513
PM
3807 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3808 return 1;
3809 }
5500b06c 3810 gen_vfp_tosl(dp, 32 - rm, 0);
9ee6e8bb
PB
3811 break;
3812 case 30: /* ftouh */
d614a513
PM
3813 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3814 return 1;
3815 }
5500b06c 3816 gen_vfp_touh(dp, 16 - rm, 0);
9ee6e8bb
PB
3817 break;
3818 case 31: /* ftoul */
d614a513
PM
3819 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3820 return 1;
3821 }
5500b06c 3822 gen_vfp_toul(dp, 32 - rm, 0);
9ee6e8bb 3823 break;
b7bcbe95 3824 default: /* undefined */
b7bcbe95
FB
3825 return 1;
3826 }
3827 break;
3828 default: /* undefined */
b7bcbe95
FB
3829 return 1;
3830 }
3831
3832 /* Write back the result. */
239c20c7
WN
3833 if (op == 15 && (rn >= 8 && rn <= 11)) {
3834 /* Comparison, do nothing. */
3835 } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
3836 (rn & 0x1e) == 0x6)) {
3837 /* VCVT double to int: always integer result.
3838 * VCVT double to half precision is always a single
3839 * precision result.
3840 */
b7bcbe95 3841 gen_mov_vreg_F0(0, rd);
239c20c7 3842 } else if (op == 15 && rn == 15) {
b7bcbe95
FB
3843 /* conversion */
3844 gen_mov_vreg_F0(!dp, rd);
239c20c7 3845 } else {
b7bcbe95 3846 gen_mov_vreg_F0(dp, rd);
239c20c7 3847 }
b7bcbe95
FB
3848
3849 /* break out of the loop if we have finished */
3850 if (veclen == 0)
3851 break;
3852
3853 if (op == 15 && delta_m == 0) {
3854 /* single source one-many */
3855 while (veclen--) {
3856 rd = ((rd + delta_d) & (bank_mask - 1))
3857 | (rd & bank_mask);
3858 gen_mov_vreg_F0(dp, rd);
3859 }
3860 break;
3861 }
3862 /* Setup the next operands. */
3863 veclen--;
3864 rd = ((rd + delta_d) & (bank_mask - 1))
3865 | (rd & bank_mask);
3866
3867 if (op == 15) {
3868 /* One source operand. */
3869 rm = ((rm + delta_m) & (bank_mask - 1))
3870 | (rm & bank_mask);
3871 gen_mov_F0_vreg(dp, rm);
3872 } else {
3873 /* Two source operands. */
3874 rn = ((rn + delta_d) & (bank_mask - 1))
3875 | (rn & bank_mask);
3876 gen_mov_F0_vreg(dp, rn);
3877 if (delta_m) {
3878 rm = ((rm + delta_m) & (bank_mask - 1))
3879 | (rm & bank_mask);
3880 gen_mov_F1_vreg(dp, rm);
3881 }
3882 }
3883 }
3884 }
3885 break;
3886 case 0xc:
3887 case 0xd:
8387da81 3888 if ((insn & 0x03e00000) == 0x00400000) {
b7bcbe95
FB
3889 /* two-register transfer */
3890 rn = (insn >> 16) & 0xf;
3891 rd = (insn >> 12) & 0xf;
3892 if (dp) {
9ee6e8bb
PB
3893 VFP_DREG_M(rm, insn);
3894 } else {
3895 rm = VFP_SREG_M(insn);
3896 }
b7bcbe95 3897
18c9b560 3898 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
3899 /* vfp->arm */
3900 if (dp) {
4373f3ce
PB
3901 gen_mov_F0_vreg(0, rm * 2);
3902 tmp = gen_vfp_mrs();
3903 store_reg(s, rd, tmp);
3904 gen_mov_F0_vreg(0, rm * 2 + 1);
3905 tmp = gen_vfp_mrs();
3906 store_reg(s, rn, tmp);
b7bcbe95
FB
3907 } else {
3908 gen_mov_F0_vreg(0, rm);
4373f3ce 3909 tmp = gen_vfp_mrs();
8387da81 3910 store_reg(s, rd, tmp);
b7bcbe95 3911 gen_mov_F0_vreg(0, rm + 1);
4373f3ce 3912 tmp = gen_vfp_mrs();
8387da81 3913 store_reg(s, rn, tmp);
b7bcbe95
FB
3914 }
3915 } else {
3916 /* arm->vfp */
3917 if (dp) {
4373f3ce
PB
3918 tmp = load_reg(s, rd);
3919 gen_vfp_msr(tmp);
3920 gen_mov_vreg_F0(0, rm * 2);
3921 tmp = load_reg(s, rn);
3922 gen_vfp_msr(tmp);
3923 gen_mov_vreg_F0(0, rm * 2 + 1);
b7bcbe95 3924 } else {
8387da81 3925 tmp = load_reg(s, rd);
4373f3ce 3926 gen_vfp_msr(tmp);
b7bcbe95 3927 gen_mov_vreg_F0(0, rm);
8387da81 3928 tmp = load_reg(s, rn);
4373f3ce 3929 gen_vfp_msr(tmp);
b7bcbe95
FB
3930 gen_mov_vreg_F0(0, rm + 1);
3931 }
3932 }
3933 } else {
3934 /* Load/store */
3935 rn = (insn >> 16) & 0xf;
3936 if (dp)
9ee6e8bb 3937 VFP_DREG_D(rd, insn);
b7bcbe95 3938 else
9ee6e8bb 3939 rd = VFP_SREG_D(insn);
b7bcbe95
FB
3940 if ((insn & 0x01200000) == 0x01000000) {
3941 /* Single load/store */
3942 offset = (insn & 0xff) << 2;
3943 if ((insn & (1 << 23)) == 0)
3944 offset = -offset;
934814f1
PM
3945 if (s->thumb && rn == 15) {
3946 /* This is actually UNPREDICTABLE */
3947 addr = tcg_temp_new_i32();
3948 tcg_gen_movi_i32(addr, s->pc & ~2);
3949 } else {
3950 addr = load_reg(s, rn);
3951 }
312eea9f 3952 tcg_gen_addi_i32(addr, addr, offset);
b7bcbe95 3953 if (insn & (1 << 20)) {
312eea9f 3954 gen_vfp_ld(s, dp, addr);
b7bcbe95
FB
3955 gen_mov_vreg_F0(dp, rd);
3956 } else {
3957 gen_mov_F0_vreg(dp, rd);
312eea9f 3958 gen_vfp_st(s, dp, addr);
b7bcbe95 3959 }
7d1b0095 3960 tcg_temp_free_i32(addr);
b7bcbe95
FB
3961 } else {
3962 /* load/store multiple */
934814f1 3963 int w = insn & (1 << 21);
b7bcbe95
FB
3964 if (dp)
3965 n = (insn >> 1) & 0x7f;
3966 else
3967 n = insn & 0xff;
3968
934814f1
PM
3969 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3970 /* P == U , W == 1 => UNDEF */
3971 return 1;
3972 }
3973 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3974 /* UNPREDICTABLE cases for bad immediates: we choose to
3975 * UNDEF to avoid generating huge numbers of TCG ops
3976 */
3977 return 1;
3978 }
3979 if (rn == 15 && w) {
3980 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3981 return 1;
3982 }
3983
3984 if (s->thumb && rn == 15) {
3985 /* This is actually UNPREDICTABLE */
3986 addr = tcg_temp_new_i32();
3987 tcg_gen_movi_i32(addr, s->pc & ~2);
3988 } else {
3989 addr = load_reg(s, rn);
3990 }
b7bcbe95 3991 if (insn & (1 << 24)) /* pre-decrement */
312eea9f 3992 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
b7bcbe95
FB
3993
3994 if (dp)
3995 offset = 8;
3996 else
3997 offset = 4;
3998 for (i = 0; i < n; i++) {
18c9b560 3999 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 4000 /* load */
312eea9f 4001 gen_vfp_ld(s, dp, addr);
b7bcbe95
FB
4002 gen_mov_vreg_F0(dp, rd + i);
4003 } else {
4004 /* store */
4005 gen_mov_F0_vreg(dp, rd + i);
312eea9f 4006 gen_vfp_st(s, dp, addr);
b7bcbe95 4007 }
312eea9f 4008 tcg_gen_addi_i32(addr, addr, offset);
b7bcbe95 4009 }
934814f1 4010 if (w) {
b7bcbe95
FB
4011 /* writeback */
4012 if (insn & (1 << 24))
4013 offset = -offset * n;
4014 else if (dp && (insn & 1))
4015 offset = 4;
4016 else
4017 offset = 0;
4018
4019 if (offset != 0)
312eea9f
FN
4020 tcg_gen_addi_i32(addr, addr, offset);
4021 store_reg(s, rn, addr);
4022 } else {
7d1b0095 4023 tcg_temp_free_i32(addr);
b7bcbe95
FB
4024 }
4025 }
4026 }
4027 break;
4028 default:
4029 /* Should never happen. */
4030 return 1;
4031 }
4032 return 0;
4033}
4034
90aa39a1 4035static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
c53be334 4036{
90aa39a1
SF
4037#ifndef CONFIG_USER_ONLY
4038 return (s->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
4039 ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4040#else
4041 return true;
4042#endif
4043}
6e256c93 4044
90aa39a1
SF
4045static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
4046{
4047 if (use_goto_tb(s, dest)) {
57fec1fe 4048 tcg_gen_goto_tb(n);
eaed129d 4049 gen_set_pc_im(s, dest);
90aa39a1 4050 tcg_gen_exit_tb((uintptr_t)s->tb + n);
6e256c93 4051 } else {
eaed129d 4052 gen_set_pc_im(s, dest);
57fec1fe 4053 tcg_gen_exit_tb(0);
6e256c93 4054 }
c53be334
FB
4055}
4056
8aaca4c0
FB
4057static inline void gen_jmp (DisasContext *s, uint32_t dest)
4058{
50225ad0 4059 if (unlikely(s->singlestep_enabled || s->ss_active)) {
8aaca4c0 4060 /* An indirect jump so that we still trigger the debug exception. */
5899f386 4061 if (s->thumb)
d9ba4830
PB
4062 dest |= 1;
4063 gen_bx_im(s, dest);
8aaca4c0 4064 } else {
6e256c93 4065 gen_goto_tb(s, 0, dest);
8aaca4c0
FB
4066 s->is_jmp = DISAS_TB_JUMP;
4067 }
4068}
4069
39d5492a 4070static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
b5ff1b31 4071{
ee097184 4072 if (x)
d9ba4830 4073 tcg_gen_sari_i32(t0, t0, 16);
b5ff1b31 4074 else
d9ba4830 4075 gen_sxth(t0);
ee097184 4076 if (y)
d9ba4830 4077 tcg_gen_sari_i32(t1, t1, 16);
b5ff1b31 4078 else
d9ba4830
PB
4079 gen_sxth(t1);
4080 tcg_gen_mul_i32(t0, t0, t1);
b5ff1b31
FB
4081}
4082
4083/* Return the mask of PSR bits set by a MSR instruction. */
7dcc1f89
PM
4084static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
4085{
b5ff1b31
FB
4086 uint32_t mask;
4087
4088 mask = 0;
4089 if (flags & (1 << 0))
4090 mask |= 0xff;
4091 if (flags & (1 << 1))
4092 mask |= 0xff00;
4093 if (flags & (1 << 2))
4094 mask |= 0xff0000;
4095 if (flags & (1 << 3))
4096 mask |= 0xff000000;
9ee6e8bb 4097
2ae23e75 4098 /* Mask out undefined bits. */
9ee6e8bb 4099 mask &= ~CPSR_RESERVED;
d614a513 4100 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
be5e7a76 4101 mask &= ~CPSR_T;
d614a513
PM
4102 }
4103 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
be5e7a76 4104 mask &= ~CPSR_Q; /* V5TE in reality*/
d614a513
PM
4105 }
4106 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
e160c51c 4107 mask &= ~(CPSR_E | CPSR_GE);
d614a513
PM
4108 }
4109 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
e160c51c 4110 mask &= ~CPSR_IT;
d614a513 4111 }
4051e12c
PM
4112 /* Mask out execution state and reserved bits. */
4113 if (!spsr) {
4114 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
4115 }
b5ff1b31
FB
4116 /* Mask out privileged bits. */
4117 if (IS_USER(s))
9ee6e8bb 4118 mask &= CPSR_USER;
b5ff1b31
FB
4119 return mask;
4120}
4121
2fbac54b 4122/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
39d5492a 4123static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
b5ff1b31 4124{
39d5492a 4125 TCGv_i32 tmp;
b5ff1b31
FB
4126 if (spsr) {
4127 /* ??? This is also undefined in system mode. */
4128 if (IS_USER(s))
4129 return 1;
d9ba4830
PB
4130
4131 tmp = load_cpu_field(spsr);
4132 tcg_gen_andi_i32(tmp, tmp, ~mask);
2fbac54b
FN
4133 tcg_gen_andi_i32(t0, t0, mask);
4134 tcg_gen_or_i32(tmp, tmp, t0);
d9ba4830 4135 store_cpu_field(tmp, spsr);
b5ff1b31 4136 } else {
2fbac54b 4137 gen_set_cpsr(t0, mask);
b5ff1b31 4138 }
7d1b0095 4139 tcg_temp_free_i32(t0);
b5ff1b31
FB
4140 gen_lookup_tb(s);
4141 return 0;
4142}
4143
2fbac54b
FN
4144/* Returns nonzero if access to the PSR is not permitted. */
4145static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
4146{
39d5492a 4147 TCGv_i32 tmp;
7d1b0095 4148 tmp = tcg_temp_new_i32();
2fbac54b
FN
4149 tcg_gen_movi_i32(tmp, val);
4150 return gen_set_psr(s, mask, spsr, tmp);
4151}
4152
8bfd0550
PM
4153static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
4154 int *tgtmode, int *regno)
4155{
4156 /* Decode the r and sysm fields of MSR/MRS banked accesses into
4157 * the target mode and register number, and identify the various
4158 * unpredictable cases.
4159 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
4160 * + executed in user mode
4161 * + using R15 as the src/dest register
4162 * + accessing an unimplemented register
4163 * + accessing a register that's inaccessible at current PL/security state*
4164 * + accessing a register that you could access with a different insn
4165 * We choose to UNDEF in all these cases.
4166 * Since we don't know which of the various AArch32 modes we are in
4167 * we have to defer some checks to runtime.
4168 * Accesses to Monitor mode registers from Secure EL1 (which implies
4169 * that EL3 is AArch64) must trap to EL3.
4170 *
4171 * If the access checks fail this function will emit code to take
4172 * an exception and return false. Otherwise it will return true,
4173 * and set *tgtmode and *regno appropriately.
4174 */
4175 int exc_target = default_exception_el(s);
4176
4177 /* These instructions are present only in ARMv8, or in ARMv7 with the
4178 * Virtualization Extensions.
4179 */
4180 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
4181 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
4182 goto undef;
4183 }
4184
4185 if (IS_USER(s) || rn == 15) {
4186 goto undef;
4187 }
4188
4189 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
4190 * of registers into (r, sysm).
4191 */
4192 if (r) {
4193 /* SPSRs for other modes */
4194 switch (sysm) {
4195 case 0xe: /* SPSR_fiq */
4196 *tgtmode = ARM_CPU_MODE_FIQ;
4197 break;
4198 case 0x10: /* SPSR_irq */
4199 *tgtmode = ARM_CPU_MODE_IRQ;
4200 break;
4201 case 0x12: /* SPSR_svc */
4202 *tgtmode = ARM_CPU_MODE_SVC;
4203 break;
4204 case 0x14: /* SPSR_abt */
4205 *tgtmode = ARM_CPU_MODE_ABT;
4206 break;
4207 case 0x16: /* SPSR_und */
4208 *tgtmode = ARM_CPU_MODE_UND;
4209 break;
4210 case 0x1c: /* SPSR_mon */
4211 *tgtmode = ARM_CPU_MODE_MON;
4212 break;
4213 case 0x1e: /* SPSR_hyp */
4214 *tgtmode = ARM_CPU_MODE_HYP;
4215 break;
4216 default: /* unallocated */
4217 goto undef;
4218 }
4219 /* We arbitrarily assign SPSR a register number of 16. */
4220 *regno = 16;
4221 } else {
4222 /* general purpose registers for other modes */
4223 switch (sysm) {
4224 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
4225 *tgtmode = ARM_CPU_MODE_USR;
4226 *regno = sysm + 8;
4227 break;
4228 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
4229 *tgtmode = ARM_CPU_MODE_FIQ;
4230 *regno = sysm;
4231 break;
4232 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
4233 *tgtmode = ARM_CPU_MODE_IRQ;
4234 *regno = sysm & 1 ? 13 : 14;
4235 break;
4236 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
4237 *tgtmode = ARM_CPU_MODE_SVC;
4238 *regno = sysm & 1 ? 13 : 14;
4239 break;
4240 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
4241 *tgtmode = ARM_CPU_MODE_ABT;
4242 *regno = sysm & 1 ? 13 : 14;
4243 break;
4244 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
4245 *tgtmode = ARM_CPU_MODE_UND;
4246 *regno = sysm & 1 ? 13 : 14;
4247 break;
4248 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
4249 *tgtmode = ARM_CPU_MODE_MON;
4250 *regno = sysm & 1 ? 13 : 14;
4251 break;
4252 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
4253 *tgtmode = ARM_CPU_MODE_HYP;
4254 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
4255 *regno = sysm & 1 ? 13 : 17;
4256 break;
4257 default: /* unallocated */
4258 goto undef;
4259 }
4260 }
4261
4262 /* Catch the 'accessing inaccessible register' cases we can detect
4263 * at translate time.
4264 */
4265 switch (*tgtmode) {
4266 case ARM_CPU_MODE_MON:
4267 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
4268 goto undef;
4269 }
4270 if (s->current_el == 1) {
4271 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
4272 * then accesses to Mon registers trap to EL3
4273 */
4274 exc_target = 3;
4275 goto undef;
4276 }
4277 break;
4278 case ARM_CPU_MODE_HYP:
4279 /* Note that we can forbid accesses from EL2 here because they
4280 * must be from Hyp mode itself
4281 */
4282 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 3) {
4283 goto undef;
4284 }
4285 break;
4286 default:
4287 break;
4288 }
4289
4290 return true;
4291
4292undef:
4293 /* If we get here then some access check did not pass */
4294 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
4295 return false;
4296}
4297
4298static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
4299{
4300 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4301 int tgtmode = 0, regno = 0;
4302
4303 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4304 return;
4305 }
4306
4307 /* Sync state because msr_banked() can raise exceptions */
4308 gen_set_condexec(s);
4309 gen_set_pc_im(s, s->pc - 4);
4310 tcg_reg = load_reg(s, rn);
4311 tcg_tgtmode = tcg_const_i32(tgtmode);
4312 tcg_regno = tcg_const_i32(regno);
4313 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
4314 tcg_temp_free_i32(tcg_tgtmode);
4315 tcg_temp_free_i32(tcg_regno);
4316 tcg_temp_free_i32(tcg_reg);
4317 s->is_jmp = DISAS_UPDATE;
4318}
4319
4320static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
4321{
4322 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4323 int tgtmode = 0, regno = 0;
4324
4325 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4326 return;
4327 }
4328
4329 /* Sync state because mrs_banked() can raise exceptions */
4330 gen_set_condexec(s);
4331 gen_set_pc_im(s, s->pc - 4);
4332 tcg_reg = tcg_temp_new_i32();
4333 tcg_tgtmode = tcg_const_i32(tgtmode);
4334 tcg_regno = tcg_const_i32(regno);
4335 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
4336 tcg_temp_free_i32(tcg_tgtmode);
4337 tcg_temp_free_i32(tcg_regno);
4338 store_reg(s, rn, tcg_reg);
4339 s->is_jmp = DISAS_UPDATE;
4340}
4341
fb0e8e79
PM
4342/* Store value to PC as for an exception return (ie don't
4343 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
4344 * will do the masking based on the new value of the Thumb bit.
4345 */
4346static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
b5ff1b31 4347{
fb0e8e79
PM
4348 tcg_gen_mov_i32(cpu_R[15], pc);
4349 tcg_temp_free_i32(pc);
b5ff1b31
FB
4350}
4351
b0109805 4352/* Generate a v6 exception return. Marks both values as dead. */
39d5492a 4353static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2c0262af 4354{
fb0e8e79
PM
4355 store_pc_exc_ret(s, pc);
4356 /* The cpsr_write_eret helper will mask the low bits of PC
4357 * appropriately depending on the new Thumb bit, so it must
4358 * be called after storing the new PC.
4359 */
235ea1f5 4360 gen_helper_cpsr_write_eret(cpu_env, cpsr);
7d1b0095 4361 tcg_temp_free_i32(cpsr);
577bf808 4362 s->is_jmp = DISAS_JUMP;
9ee6e8bb 4363}
3b46e624 4364
fb0e8e79
PM
4365/* Generate an old-style exception return. Marks pc as dead. */
4366static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
4367{
4368 gen_rfe(s, pc, load_cpu_field(spsr));
4369}
4370
9ee6e8bb
PB
4371static void gen_nop_hint(DisasContext *s, int val)
4372{
4373 switch (val) {
c87e5a61
PM
4374 case 1: /* yield */
4375 gen_set_pc_im(s, s->pc);
4376 s->is_jmp = DISAS_YIELD;
4377 break;
9ee6e8bb 4378 case 3: /* wfi */
eaed129d 4379 gen_set_pc_im(s, s->pc);
9ee6e8bb
PB
4380 s->is_jmp = DISAS_WFI;
4381 break;
4382 case 2: /* wfe */
72c1d3af
PM
4383 gen_set_pc_im(s, s->pc);
4384 s->is_jmp = DISAS_WFE;
4385 break;
9ee6e8bb 4386 case 4: /* sev */
12b10571
MR
4387 case 5: /* sevl */
4388 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
9ee6e8bb
PB
4389 default: /* nop */
4390 break;
4391 }
4392}
99c475ab 4393
ad69471c 4394#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
9ee6e8bb 4395
39d5492a 4396static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
4397{
4398 switch (size) {
dd8fbd78
FN
4399 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4400 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4401 case 2: tcg_gen_add_i32(t0, t0, t1); break;
62698be3 4402 default: abort();
9ee6e8bb 4403 }
9ee6e8bb
PB
4404}
4405
39d5492a 4406static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
ad69471c
PB
4407{
4408 switch (size) {
dd8fbd78
FN
4409 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4410 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4411 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
ad69471c
PB
4412 default: return;
4413 }
4414}
4415
4416/* 32-bit pairwise ops end up the same as the elementwise versions. */
4417#define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
4418#define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
4419#define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
4420#define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
4421
ad69471c
PB
4422#define GEN_NEON_INTEGER_OP_ENV(name) do { \
4423 switch ((size << 1) | u) { \
4424 case 0: \
dd8fbd78 4425 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4426 break; \
4427 case 1: \
dd8fbd78 4428 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4429 break; \
4430 case 2: \
dd8fbd78 4431 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4432 break; \
4433 case 3: \
dd8fbd78 4434 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4435 break; \
4436 case 4: \
dd8fbd78 4437 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4438 break; \
4439 case 5: \
dd8fbd78 4440 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4441 break; \
4442 default: return 1; \
4443 }} while (0)
9ee6e8bb
PB
4444
4445#define GEN_NEON_INTEGER_OP(name) do { \
4446 switch ((size << 1) | u) { \
ad69471c 4447 case 0: \
dd8fbd78 4448 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
ad69471c
PB
4449 break; \
4450 case 1: \
dd8fbd78 4451 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
ad69471c
PB
4452 break; \
4453 case 2: \
dd8fbd78 4454 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
ad69471c
PB
4455 break; \
4456 case 3: \
dd8fbd78 4457 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
ad69471c
PB
4458 break; \
4459 case 4: \
dd8fbd78 4460 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
ad69471c
PB
4461 break; \
4462 case 5: \
dd8fbd78 4463 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
ad69471c 4464 break; \
9ee6e8bb
PB
4465 default: return 1; \
4466 }} while (0)
4467
39d5492a 4468static TCGv_i32 neon_load_scratch(int scratch)
9ee6e8bb 4469{
39d5492a 4470 TCGv_i32 tmp = tcg_temp_new_i32();
dd8fbd78
FN
4471 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4472 return tmp;
9ee6e8bb
PB
4473}
4474
39d5492a 4475static void neon_store_scratch(int scratch, TCGv_i32 var)
9ee6e8bb 4476{
dd8fbd78 4477 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
7d1b0095 4478 tcg_temp_free_i32(var);
9ee6e8bb
PB
4479}
4480
39d5492a 4481static inline TCGv_i32 neon_get_scalar(int size, int reg)
9ee6e8bb 4482{
39d5492a 4483 TCGv_i32 tmp;
9ee6e8bb 4484 if (size == 1) {
0fad6efc
PM
4485 tmp = neon_load_reg(reg & 7, reg >> 4);
4486 if (reg & 8) {
dd8fbd78 4487 gen_neon_dup_high16(tmp);
0fad6efc
PM
4488 } else {
4489 gen_neon_dup_low16(tmp);
dd8fbd78 4490 }
0fad6efc
PM
4491 } else {
4492 tmp = neon_load_reg(reg & 15, reg >> 4);
9ee6e8bb 4493 }
dd8fbd78 4494 return tmp;
9ee6e8bb
PB
4495}
4496
02acedf9 4497static int gen_neon_unzip(int rd, int rm, int size, int q)
19457615 4498{
39d5492a 4499 TCGv_i32 tmp, tmp2;
600b828c 4500 if (!q && size == 2) {
02acedf9
PM
4501 return 1;
4502 }
4503 tmp = tcg_const_i32(rd);
4504 tmp2 = tcg_const_i32(rm);
4505 if (q) {
4506 switch (size) {
4507 case 0:
02da0b2d 4508 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
02acedf9
PM
4509 break;
4510 case 1:
02da0b2d 4511 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
02acedf9
PM
4512 break;
4513 case 2:
02da0b2d 4514 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
02acedf9
PM
4515 break;
4516 default:
4517 abort();
4518 }
4519 } else {
4520 switch (size) {
4521 case 0:
02da0b2d 4522 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
02acedf9
PM
4523 break;
4524 case 1:
02da0b2d 4525 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
02acedf9
PM
4526 break;
4527 default:
4528 abort();
4529 }
4530 }
4531 tcg_temp_free_i32(tmp);
4532 tcg_temp_free_i32(tmp2);
4533 return 0;
19457615
FN
4534}
4535
d68a6f3a 4536static int gen_neon_zip(int rd, int rm, int size, int q)
19457615 4537{
39d5492a 4538 TCGv_i32 tmp, tmp2;
600b828c 4539 if (!q && size == 2) {
d68a6f3a
PM
4540 return 1;
4541 }
4542 tmp = tcg_const_i32(rd);
4543 tmp2 = tcg_const_i32(rm);
4544 if (q) {
4545 switch (size) {
4546 case 0:
02da0b2d 4547 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
d68a6f3a
PM
4548 break;
4549 case 1:
02da0b2d 4550 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
d68a6f3a
PM
4551 break;
4552 case 2:
02da0b2d 4553 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
d68a6f3a
PM
4554 break;
4555 default:
4556 abort();
4557 }
4558 } else {
4559 switch (size) {
4560 case 0:
02da0b2d 4561 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
d68a6f3a
PM
4562 break;
4563 case 1:
02da0b2d 4564 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
d68a6f3a
PM
4565 break;
4566 default:
4567 abort();
4568 }
4569 }
4570 tcg_temp_free_i32(tmp);
4571 tcg_temp_free_i32(tmp2);
4572 return 0;
19457615
FN
4573}
4574
39d5492a 4575static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
19457615 4576{
39d5492a 4577 TCGv_i32 rd, tmp;
19457615 4578
7d1b0095
PM
4579 rd = tcg_temp_new_i32();
4580 tmp = tcg_temp_new_i32();
19457615
FN
4581
4582 tcg_gen_shli_i32(rd, t0, 8);
4583 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4584 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4585 tcg_gen_or_i32(rd, rd, tmp);
4586
4587 tcg_gen_shri_i32(t1, t1, 8);
4588 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4589 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4590 tcg_gen_or_i32(t1, t1, tmp);
4591 tcg_gen_mov_i32(t0, rd);
4592
7d1b0095
PM
4593 tcg_temp_free_i32(tmp);
4594 tcg_temp_free_i32(rd);
19457615
FN
4595}
4596
39d5492a 4597static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
19457615 4598{
39d5492a 4599 TCGv_i32 rd, tmp;
19457615 4600
7d1b0095
PM
4601 rd = tcg_temp_new_i32();
4602 tmp = tcg_temp_new_i32();
19457615
FN
4603
4604 tcg_gen_shli_i32(rd, t0, 16);
4605 tcg_gen_andi_i32(tmp, t1, 0xffff);
4606 tcg_gen_or_i32(rd, rd, tmp);
4607 tcg_gen_shri_i32(t1, t1, 16);
4608 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4609 tcg_gen_or_i32(t1, t1, tmp);
4610 tcg_gen_mov_i32(t0, rd);
4611
7d1b0095
PM
4612 tcg_temp_free_i32(tmp);
4613 tcg_temp_free_i32(rd);
19457615
FN
4614}
4615
4616
9ee6e8bb
PB
4617static struct {
4618 int nregs;
4619 int interleave;
4620 int spacing;
4621} neon_ls_element_type[11] = {
4622 {4, 4, 1},
4623 {4, 4, 2},
4624 {4, 1, 1},
4625 {4, 2, 1},
4626 {3, 3, 1},
4627 {3, 3, 2},
4628 {3, 1, 1},
4629 {1, 1, 1},
4630 {2, 2, 1},
4631 {2, 2, 2},
4632 {2, 1, 1}
4633};
4634
4635/* Translate a NEON load/store element instruction. Return nonzero if the
4636 instruction is invalid. */
7dcc1f89 4637static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
4638{
4639 int rd, rn, rm;
4640 int op;
4641 int nregs;
4642 int interleave;
84496233 4643 int spacing;
9ee6e8bb
PB
4644 int stride;
4645 int size;
4646 int reg;
4647 int pass;
4648 int load;
4649 int shift;
9ee6e8bb 4650 int n;
39d5492a
PM
4651 TCGv_i32 addr;
4652 TCGv_i32 tmp;
4653 TCGv_i32 tmp2;
84496233 4654 TCGv_i64 tmp64;
9ee6e8bb 4655
2c7ffc41
PM
4656 /* FIXME: this access check should not take precedence over UNDEF
4657 * for invalid encodings; we will generate incorrect syndrome information
4658 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4659 */
9dbbc748 4660 if (s->fp_excp_el) {
2c7ffc41 4661 gen_exception_insn(s, 4, EXCP_UDEF,
7d197d2d 4662 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
4663 return 0;
4664 }
4665
5df8bac1 4666 if (!s->vfp_enabled)
9ee6e8bb
PB
4667 return 1;
4668 VFP_DREG_D(rd, insn);
4669 rn = (insn >> 16) & 0xf;
4670 rm = insn & 0xf;
4671 load = (insn & (1 << 21)) != 0;
4672 if ((insn & (1 << 23)) == 0) {
4673 /* Load store all elements. */
4674 op = (insn >> 8) & 0xf;
4675 size = (insn >> 6) & 3;
84496233 4676 if (op > 10)
9ee6e8bb 4677 return 1;
f2dd89d0
PM
4678 /* Catch UNDEF cases for bad values of align field */
4679 switch (op & 0xc) {
4680 case 4:
4681 if (((insn >> 5) & 1) == 1) {
4682 return 1;
4683 }
4684 break;
4685 case 8:
4686 if (((insn >> 4) & 3) == 3) {
4687 return 1;
4688 }
4689 break;
4690 default:
4691 break;
4692 }
9ee6e8bb
PB
4693 nregs = neon_ls_element_type[op].nregs;
4694 interleave = neon_ls_element_type[op].interleave;
84496233
JR
4695 spacing = neon_ls_element_type[op].spacing;
4696 if (size == 3 && (interleave | spacing) != 1)
4697 return 1;
e318a60b 4698 addr = tcg_temp_new_i32();
dcc65026 4699 load_reg_var(s, addr, rn);
9ee6e8bb
PB
4700 stride = (1 << size) * interleave;
4701 for (reg = 0; reg < nregs; reg++) {
4702 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
dcc65026
AJ
4703 load_reg_var(s, addr, rn);
4704 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
9ee6e8bb 4705 } else if (interleave == 2 && nregs == 4 && reg == 2) {
dcc65026
AJ
4706 load_reg_var(s, addr, rn);
4707 tcg_gen_addi_i32(addr, addr, 1 << size);
9ee6e8bb 4708 }
84496233 4709 if (size == 3) {
8ed1237d 4710 tmp64 = tcg_temp_new_i64();
84496233 4711 if (load) {
12dcc321 4712 gen_aa32_ld64(s, tmp64, addr, get_mem_index(s));
84496233 4713 neon_store_reg64(tmp64, rd);
84496233 4714 } else {
84496233 4715 neon_load_reg64(tmp64, rd);
12dcc321 4716 gen_aa32_st64(s, tmp64, addr, get_mem_index(s));
84496233 4717 }
8ed1237d 4718 tcg_temp_free_i64(tmp64);
84496233
JR
4719 tcg_gen_addi_i32(addr, addr, stride);
4720 } else {
4721 for (pass = 0; pass < 2; pass++) {
4722 if (size == 2) {
4723 if (load) {
58ab8e96 4724 tmp = tcg_temp_new_i32();
12dcc321 4725 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
84496233
JR
4726 neon_store_reg(rd, pass, tmp);
4727 } else {
4728 tmp = neon_load_reg(rd, pass);
12dcc321 4729 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
58ab8e96 4730 tcg_temp_free_i32(tmp);
84496233 4731 }
1b2b1e54 4732 tcg_gen_addi_i32(addr, addr, stride);
84496233
JR
4733 } else if (size == 1) {
4734 if (load) {
58ab8e96 4735 tmp = tcg_temp_new_i32();
12dcc321 4736 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
84496233 4737 tcg_gen_addi_i32(addr, addr, stride);
58ab8e96 4738 tmp2 = tcg_temp_new_i32();
12dcc321 4739 gen_aa32_ld16u(s, tmp2, addr, get_mem_index(s));
84496233 4740 tcg_gen_addi_i32(addr, addr, stride);
41ba8341
PB
4741 tcg_gen_shli_i32(tmp2, tmp2, 16);
4742 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 4743 tcg_temp_free_i32(tmp2);
84496233
JR
4744 neon_store_reg(rd, pass, tmp);
4745 } else {
4746 tmp = neon_load_reg(rd, pass);
7d1b0095 4747 tmp2 = tcg_temp_new_i32();
84496233 4748 tcg_gen_shri_i32(tmp2, tmp, 16);
12dcc321 4749 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
58ab8e96 4750 tcg_temp_free_i32(tmp);
84496233 4751 tcg_gen_addi_i32(addr, addr, stride);
12dcc321 4752 gen_aa32_st16(s, tmp2, addr, get_mem_index(s));
58ab8e96 4753 tcg_temp_free_i32(tmp2);
1b2b1e54 4754 tcg_gen_addi_i32(addr, addr, stride);
9ee6e8bb 4755 }
84496233
JR
4756 } else /* size == 0 */ {
4757 if (load) {
39d5492a 4758 TCGV_UNUSED_I32(tmp2);
84496233 4759 for (n = 0; n < 4; n++) {
58ab8e96 4760 tmp = tcg_temp_new_i32();
12dcc321 4761 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
84496233
JR
4762 tcg_gen_addi_i32(addr, addr, stride);
4763 if (n == 0) {
4764 tmp2 = tmp;
4765 } else {
41ba8341
PB
4766 tcg_gen_shli_i32(tmp, tmp, n * 8);
4767 tcg_gen_or_i32(tmp2, tmp2, tmp);
7d1b0095 4768 tcg_temp_free_i32(tmp);
84496233 4769 }
9ee6e8bb 4770 }
84496233
JR
4771 neon_store_reg(rd, pass, tmp2);
4772 } else {
4773 tmp2 = neon_load_reg(rd, pass);
4774 for (n = 0; n < 4; n++) {
7d1b0095 4775 tmp = tcg_temp_new_i32();
84496233
JR
4776 if (n == 0) {
4777 tcg_gen_mov_i32(tmp, tmp2);
4778 } else {
4779 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4780 }
12dcc321 4781 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
58ab8e96 4782 tcg_temp_free_i32(tmp);
84496233
JR
4783 tcg_gen_addi_i32(addr, addr, stride);
4784 }
7d1b0095 4785 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
4786 }
4787 }
4788 }
4789 }
84496233 4790 rd += spacing;
9ee6e8bb 4791 }
e318a60b 4792 tcg_temp_free_i32(addr);
9ee6e8bb
PB
4793 stride = nregs * 8;
4794 } else {
4795 size = (insn >> 10) & 3;
4796 if (size == 3) {
4797 /* Load single element to all lanes. */
8e18cde3
PM
4798 int a = (insn >> 4) & 1;
4799 if (!load) {
9ee6e8bb 4800 return 1;
8e18cde3 4801 }
9ee6e8bb
PB
4802 size = (insn >> 6) & 3;
4803 nregs = ((insn >> 8) & 3) + 1;
8e18cde3
PM
4804
4805 if (size == 3) {
4806 if (nregs != 4 || a == 0) {
9ee6e8bb 4807 return 1;
99c475ab 4808 }
8e18cde3
PM
4809 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4810 size = 2;
4811 }
4812 if (nregs == 1 && a == 1 && size == 0) {
4813 return 1;
4814 }
4815 if (nregs == 3 && a == 1) {
4816 return 1;
4817 }
e318a60b 4818 addr = tcg_temp_new_i32();
8e18cde3
PM
4819 load_reg_var(s, addr, rn);
4820 if (nregs == 1) {
4821 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4822 tmp = gen_load_and_replicate(s, addr, size);
4823 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4824 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4825 if (insn & (1 << 5)) {
4826 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4827 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4828 }
4829 tcg_temp_free_i32(tmp);
4830 } else {
4831 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4832 stride = (insn & (1 << 5)) ? 2 : 1;
4833 for (reg = 0; reg < nregs; reg++) {
4834 tmp = gen_load_and_replicate(s, addr, size);
4835 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4836 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4837 tcg_temp_free_i32(tmp);
4838 tcg_gen_addi_i32(addr, addr, 1 << size);
4839 rd += stride;
4840 }
9ee6e8bb 4841 }
e318a60b 4842 tcg_temp_free_i32(addr);
9ee6e8bb
PB
4843 stride = (1 << size) * nregs;
4844 } else {
4845 /* Single element. */
93262b16 4846 int idx = (insn >> 4) & 0xf;
9ee6e8bb
PB
4847 pass = (insn >> 7) & 1;
4848 switch (size) {
4849 case 0:
4850 shift = ((insn >> 5) & 3) * 8;
9ee6e8bb
PB
4851 stride = 1;
4852 break;
4853 case 1:
4854 shift = ((insn >> 6) & 1) * 16;
9ee6e8bb
PB
4855 stride = (insn & (1 << 5)) ? 2 : 1;
4856 break;
4857 case 2:
4858 shift = 0;
9ee6e8bb
PB
4859 stride = (insn & (1 << 6)) ? 2 : 1;
4860 break;
4861 default:
4862 abort();
4863 }
4864 nregs = ((insn >> 8) & 3) + 1;
93262b16
PM
4865 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4866 switch (nregs) {
4867 case 1:
4868 if (((idx & (1 << size)) != 0) ||
4869 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4870 return 1;
4871 }
4872 break;
4873 case 3:
4874 if ((idx & 1) != 0) {
4875 return 1;
4876 }
4877 /* fall through */
4878 case 2:
4879 if (size == 2 && (idx & 2) != 0) {
4880 return 1;
4881 }
4882 break;
4883 case 4:
4884 if ((size == 2) && ((idx & 3) == 3)) {
4885 return 1;
4886 }
4887 break;
4888 default:
4889 abort();
4890 }
4891 if ((rd + stride * (nregs - 1)) > 31) {
4892 /* Attempts to write off the end of the register file
4893 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4894 * the neon_load_reg() would write off the end of the array.
4895 */
4896 return 1;
4897 }
e318a60b 4898 addr = tcg_temp_new_i32();
dcc65026 4899 load_reg_var(s, addr, rn);
9ee6e8bb
PB
4900 for (reg = 0; reg < nregs; reg++) {
4901 if (load) {
58ab8e96 4902 tmp = tcg_temp_new_i32();
9ee6e8bb
PB
4903 switch (size) {
4904 case 0:
12dcc321 4905 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
4906 break;
4907 case 1:
12dcc321 4908 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
4909 break;
4910 case 2:
12dcc321 4911 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 4912 break;
a50f5b91
PB
4913 default: /* Avoid compiler warnings. */
4914 abort();
9ee6e8bb
PB
4915 }
4916 if (size != 2) {
8f8e3aa4 4917 tmp2 = neon_load_reg(rd, pass);
d593c48e
AJ
4918 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4919 shift, size ? 16 : 8);
7d1b0095 4920 tcg_temp_free_i32(tmp2);
9ee6e8bb 4921 }
8f8e3aa4 4922 neon_store_reg(rd, pass, tmp);
9ee6e8bb 4923 } else { /* Store */
8f8e3aa4
PB
4924 tmp = neon_load_reg(rd, pass);
4925 if (shift)
4926 tcg_gen_shri_i32(tmp, tmp, shift);
9ee6e8bb
PB
4927 switch (size) {
4928 case 0:
12dcc321 4929 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
4930 break;
4931 case 1:
12dcc321 4932 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
4933 break;
4934 case 2:
12dcc321 4935 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9ee6e8bb 4936 break;
99c475ab 4937 }
58ab8e96 4938 tcg_temp_free_i32(tmp);
99c475ab 4939 }
9ee6e8bb 4940 rd += stride;
1b2b1e54 4941 tcg_gen_addi_i32(addr, addr, 1 << size);
99c475ab 4942 }
e318a60b 4943 tcg_temp_free_i32(addr);
9ee6e8bb 4944 stride = nregs * (1 << size);
99c475ab 4945 }
9ee6e8bb
PB
4946 }
4947 if (rm != 15) {
39d5492a 4948 TCGv_i32 base;
b26eefb6
PB
4949
4950 base = load_reg(s, rn);
9ee6e8bb 4951 if (rm == 13) {
b26eefb6 4952 tcg_gen_addi_i32(base, base, stride);
9ee6e8bb 4953 } else {
39d5492a 4954 TCGv_i32 index;
b26eefb6
PB
4955 index = load_reg(s, rm);
4956 tcg_gen_add_i32(base, base, index);
7d1b0095 4957 tcg_temp_free_i32(index);
9ee6e8bb 4958 }
b26eefb6 4959 store_reg(s, rn, base);
9ee6e8bb
PB
4960 }
4961 return 0;
4962}
3b46e624 4963
8f8e3aa4 4964/* Bitwise select. dest = c ? t : f. Clobbers T and F. */
39d5492a 4965static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
8f8e3aa4
PB
4966{
4967 tcg_gen_and_i32(t, t, c);
f669df27 4968 tcg_gen_andc_i32(f, f, c);
8f8e3aa4
PB
4969 tcg_gen_or_i32(dest, t, f);
4970}
4971
39d5492a 4972static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
4973{
4974 switch (size) {
4975 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4976 case 1: gen_helper_neon_narrow_u16(dest, src); break;
ecc7b3aa 4977 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
ad69471c
PB
4978 default: abort();
4979 }
4980}
4981
39d5492a 4982static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
4983{
4984 switch (size) {
02da0b2d
PM
4985 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4986 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4987 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
ad69471c
PB
4988 default: abort();
4989 }
4990}
4991
39d5492a 4992static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
4993{
4994 switch (size) {
02da0b2d
PM
4995 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4996 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4997 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
ad69471c
PB
4998 default: abort();
4999 }
5000}
5001
39d5492a 5002static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
af1bbf30
JR
5003{
5004 switch (size) {
02da0b2d
PM
5005 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
5006 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
5007 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
af1bbf30
JR
5008 default: abort();
5009 }
5010}
5011
39d5492a 5012static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
ad69471c
PB
5013 int q, int u)
5014{
5015 if (q) {
5016 if (u) {
5017 switch (size) {
5018 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
5019 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
5020 default: abort();
5021 }
5022 } else {
5023 switch (size) {
5024 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
5025 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
5026 default: abort();
5027 }
5028 }
5029 } else {
5030 if (u) {
5031 switch (size) {
b408a9b0
CL
5032 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
5033 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
ad69471c
PB
5034 default: abort();
5035 }
5036 } else {
5037 switch (size) {
5038 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
5039 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
5040 default: abort();
5041 }
5042 }
5043 }
5044}
5045
39d5492a 5046static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
ad69471c
PB
5047{
5048 if (u) {
5049 switch (size) {
5050 case 0: gen_helper_neon_widen_u8(dest, src); break;
5051 case 1: gen_helper_neon_widen_u16(dest, src); break;
5052 case 2: tcg_gen_extu_i32_i64(dest, src); break;
5053 default: abort();
5054 }
5055 } else {
5056 switch (size) {
5057 case 0: gen_helper_neon_widen_s8(dest, src); break;
5058 case 1: gen_helper_neon_widen_s16(dest, src); break;
5059 case 2: tcg_gen_ext_i32_i64(dest, src); break;
5060 default: abort();
5061 }
5062 }
7d1b0095 5063 tcg_temp_free_i32(src);
ad69471c
PB
5064}
5065
5066static inline void gen_neon_addl(int size)
5067{
5068 switch (size) {
5069 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
5070 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
5071 case 2: tcg_gen_add_i64(CPU_V001); break;
5072 default: abort();
5073 }
5074}
5075
5076static inline void gen_neon_subl(int size)
5077{
5078 switch (size) {
5079 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
5080 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
5081 case 2: tcg_gen_sub_i64(CPU_V001); break;
5082 default: abort();
5083 }
5084}
5085
a7812ae4 5086static inline void gen_neon_negl(TCGv_i64 var, int size)
ad69471c
PB
5087{
5088 switch (size) {
5089 case 0: gen_helper_neon_negl_u16(var, var); break;
5090 case 1: gen_helper_neon_negl_u32(var, var); break;
ee6fa559
PM
5091 case 2:
5092 tcg_gen_neg_i64(var, var);
5093 break;
ad69471c
PB
5094 default: abort();
5095 }
5096}
5097
a7812ae4 5098static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
ad69471c
PB
5099{
5100 switch (size) {
02da0b2d
PM
5101 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
5102 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
ad69471c
PB
5103 default: abort();
5104 }
5105}
5106
39d5492a
PM
5107static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
5108 int size, int u)
ad69471c 5109{
a7812ae4 5110 TCGv_i64 tmp;
ad69471c
PB
5111
5112 switch ((size << 1) | u) {
5113 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
5114 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
5115 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
5116 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
5117 case 4:
5118 tmp = gen_muls_i64_i32(a, b);
5119 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 5120 tcg_temp_free_i64(tmp);
ad69471c
PB
5121 break;
5122 case 5:
5123 tmp = gen_mulu_i64_i32(a, b);
5124 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 5125 tcg_temp_free_i64(tmp);
ad69471c
PB
5126 break;
5127 default: abort();
5128 }
c6067f04
CL
5129
5130 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
5131 Don't forget to clean them now. */
5132 if (size < 2) {
7d1b0095
PM
5133 tcg_temp_free_i32(a);
5134 tcg_temp_free_i32(b);
c6067f04 5135 }
ad69471c
PB
5136}
5137
39d5492a
PM
5138static void gen_neon_narrow_op(int op, int u, int size,
5139 TCGv_i32 dest, TCGv_i64 src)
c33171c7
PM
5140{
5141 if (op) {
5142 if (u) {
5143 gen_neon_unarrow_sats(size, dest, src);
5144 } else {
5145 gen_neon_narrow(size, dest, src);
5146 }
5147 } else {
5148 if (u) {
5149 gen_neon_narrow_satu(size, dest, src);
5150 } else {
5151 gen_neon_narrow_sats(size, dest, src);
5152 }
5153 }
5154}
5155
62698be3
PM
5156/* Symbolic constants for op fields for Neon 3-register same-length.
5157 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
5158 * table A7-9.
5159 */
5160#define NEON_3R_VHADD 0
5161#define NEON_3R_VQADD 1
5162#define NEON_3R_VRHADD 2
5163#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
5164#define NEON_3R_VHSUB 4
5165#define NEON_3R_VQSUB 5
5166#define NEON_3R_VCGT 6
5167#define NEON_3R_VCGE 7
5168#define NEON_3R_VSHL 8
5169#define NEON_3R_VQSHL 9
5170#define NEON_3R_VRSHL 10
5171#define NEON_3R_VQRSHL 11
5172#define NEON_3R_VMAX 12
5173#define NEON_3R_VMIN 13
5174#define NEON_3R_VABD 14
5175#define NEON_3R_VABA 15
5176#define NEON_3R_VADD_VSUB 16
5177#define NEON_3R_VTST_VCEQ 17
5178#define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
5179#define NEON_3R_VMUL 19
5180#define NEON_3R_VPMAX 20
5181#define NEON_3R_VPMIN 21
5182#define NEON_3R_VQDMULH_VQRDMULH 22
5183#define NEON_3R_VPADD 23
f1ecb913 5184#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
da97f52c 5185#define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
62698be3
PM
5186#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
5187#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
5188#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
5189#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
5190#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
505935fc 5191#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
62698be3
PM
5192
5193static const uint8_t neon_3r_sizes[] = {
5194 [NEON_3R_VHADD] = 0x7,
5195 [NEON_3R_VQADD] = 0xf,
5196 [NEON_3R_VRHADD] = 0x7,
5197 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
5198 [NEON_3R_VHSUB] = 0x7,
5199 [NEON_3R_VQSUB] = 0xf,
5200 [NEON_3R_VCGT] = 0x7,
5201 [NEON_3R_VCGE] = 0x7,
5202 [NEON_3R_VSHL] = 0xf,
5203 [NEON_3R_VQSHL] = 0xf,
5204 [NEON_3R_VRSHL] = 0xf,
5205 [NEON_3R_VQRSHL] = 0xf,
5206 [NEON_3R_VMAX] = 0x7,
5207 [NEON_3R_VMIN] = 0x7,
5208 [NEON_3R_VABD] = 0x7,
5209 [NEON_3R_VABA] = 0x7,
5210 [NEON_3R_VADD_VSUB] = 0xf,
5211 [NEON_3R_VTST_VCEQ] = 0x7,
5212 [NEON_3R_VML] = 0x7,
5213 [NEON_3R_VMUL] = 0x7,
5214 [NEON_3R_VPMAX] = 0x7,
5215 [NEON_3R_VPMIN] = 0x7,
5216 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
5217 [NEON_3R_VPADD] = 0x7,
f1ecb913 5218 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
da97f52c 5219 [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
62698be3
PM
5220 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
5221 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
5222 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
5223 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
5224 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
505935fc 5225 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
62698be3
PM
5226};
5227
600b828c
PM
5228/* Symbolic constants for op fields for Neon 2-register miscellaneous.
5229 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
5230 * table A7-13.
5231 */
5232#define NEON_2RM_VREV64 0
5233#define NEON_2RM_VREV32 1
5234#define NEON_2RM_VREV16 2
5235#define NEON_2RM_VPADDL 4
5236#define NEON_2RM_VPADDL_U 5
9d935509
AB
5237#define NEON_2RM_AESE 6 /* Includes AESD */
5238#define NEON_2RM_AESMC 7 /* Includes AESIMC */
600b828c
PM
5239#define NEON_2RM_VCLS 8
5240#define NEON_2RM_VCLZ 9
5241#define NEON_2RM_VCNT 10
5242#define NEON_2RM_VMVN 11
5243#define NEON_2RM_VPADAL 12
5244#define NEON_2RM_VPADAL_U 13
5245#define NEON_2RM_VQABS 14
5246#define NEON_2RM_VQNEG 15
5247#define NEON_2RM_VCGT0 16
5248#define NEON_2RM_VCGE0 17
5249#define NEON_2RM_VCEQ0 18
5250#define NEON_2RM_VCLE0 19
5251#define NEON_2RM_VCLT0 20
f1ecb913 5252#define NEON_2RM_SHA1H 21
600b828c
PM
5253#define NEON_2RM_VABS 22
5254#define NEON_2RM_VNEG 23
5255#define NEON_2RM_VCGT0_F 24
5256#define NEON_2RM_VCGE0_F 25
5257#define NEON_2RM_VCEQ0_F 26
5258#define NEON_2RM_VCLE0_F 27
5259#define NEON_2RM_VCLT0_F 28
5260#define NEON_2RM_VABS_F 30
5261#define NEON_2RM_VNEG_F 31
5262#define NEON_2RM_VSWP 32
5263#define NEON_2RM_VTRN 33
5264#define NEON_2RM_VUZP 34
5265#define NEON_2RM_VZIP 35
5266#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
5267#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
5268#define NEON_2RM_VSHLL 38
f1ecb913 5269#define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
34f7b0a2 5270#define NEON_2RM_VRINTN 40
2ce70625 5271#define NEON_2RM_VRINTX 41
34f7b0a2
WN
5272#define NEON_2RM_VRINTA 42
5273#define NEON_2RM_VRINTZ 43
600b828c 5274#define NEON_2RM_VCVT_F16_F32 44
34f7b0a2 5275#define NEON_2RM_VRINTM 45
600b828c 5276#define NEON_2RM_VCVT_F32_F16 46
34f7b0a2 5277#define NEON_2RM_VRINTP 47
901ad525
WN
5278#define NEON_2RM_VCVTAU 48
5279#define NEON_2RM_VCVTAS 49
5280#define NEON_2RM_VCVTNU 50
5281#define NEON_2RM_VCVTNS 51
5282#define NEON_2RM_VCVTPU 52
5283#define NEON_2RM_VCVTPS 53
5284#define NEON_2RM_VCVTMU 54
5285#define NEON_2RM_VCVTMS 55
600b828c
PM
5286#define NEON_2RM_VRECPE 56
5287#define NEON_2RM_VRSQRTE 57
5288#define NEON_2RM_VRECPE_F 58
5289#define NEON_2RM_VRSQRTE_F 59
5290#define NEON_2RM_VCVT_FS 60
5291#define NEON_2RM_VCVT_FU 61
5292#define NEON_2RM_VCVT_SF 62
5293#define NEON_2RM_VCVT_UF 63
5294
5295static int neon_2rm_is_float_op(int op)
5296{
5297 /* Return true if this neon 2reg-misc op is float-to-float */
5298 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
34f7b0a2 5299 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
901ad525
WN
5300 op == NEON_2RM_VRINTM ||
5301 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
34f7b0a2 5302 op >= NEON_2RM_VRECPE_F);
600b828c
PM
5303}
5304
fe8fcf3d
PM
5305static bool neon_2rm_is_v8_op(int op)
5306{
5307 /* Return true if this neon 2reg-misc op is ARMv8 and up */
5308 switch (op) {
5309 case NEON_2RM_VRINTN:
5310 case NEON_2RM_VRINTA:
5311 case NEON_2RM_VRINTM:
5312 case NEON_2RM_VRINTP:
5313 case NEON_2RM_VRINTZ:
5314 case NEON_2RM_VRINTX:
5315 case NEON_2RM_VCVTAU:
5316 case NEON_2RM_VCVTAS:
5317 case NEON_2RM_VCVTNU:
5318 case NEON_2RM_VCVTNS:
5319 case NEON_2RM_VCVTPU:
5320 case NEON_2RM_VCVTPS:
5321 case NEON_2RM_VCVTMU:
5322 case NEON_2RM_VCVTMS:
5323 return true;
5324 default:
5325 return false;
5326 }
5327}
5328
600b828c
PM
5329/* Each entry in this array has bit n set if the insn allows
5330 * size value n (otherwise it will UNDEF). Since unallocated
5331 * op values will have no bits set they always UNDEF.
5332 */
5333static const uint8_t neon_2rm_sizes[] = {
5334 [NEON_2RM_VREV64] = 0x7,
5335 [NEON_2RM_VREV32] = 0x3,
5336 [NEON_2RM_VREV16] = 0x1,
5337 [NEON_2RM_VPADDL] = 0x7,
5338 [NEON_2RM_VPADDL_U] = 0x7,
9d935509
AB
5339 [NEON_2RM_AESE] = 0x1,
5340 [NEON_2RM_AESMC] = 0x1,
600b828c
PM
5341 [NEON_2RM_VCLS] = 0x7,
5342 [NEON_2RM_VCLZ] = 0x7,
5343 [NEON_2RM_VCNT] = 0x1,
5344 [NEON_2RM_VMVN] = 0x1,
5345 [NEON_2RM_VPADAL] = 0x7,
5346 [NEON_2RM_VPADAL_U] = 0x7,
5347 [NEON_2RM_VQABS] = 0x7,
5348 [NEON_2RM_VQNEG] = 0x7,
5349 [NEON_2RM_VCGT0] = 0x7,
5350 [NEON_2RM_VCGE0] = 0x7,
5351 [NEON_2RM_VCEQ0] = 0x7,
5352 [NEON_2RM_VCLE0] = 0x7,
5353 [NEON_2RM_VCLT0] = 0x7,
f1ecb913 5354 [NEON_2RM_SHA1H] = 0x4,
600b828c
PM
5355 [NEON_2RM_VABS] = 0x7,
5356 [NEON_2RM_VNEG] = 0x7,
5357 [NEON_2RM_VCGT0_F] = 0x4,
5358 [NEON_2RM_VCGE0_F] = 0x4,
5359 [NEON_2RM_VCEQ0_F] = 0x4,
5360 [NEON_2RM_VCLE0_F] = 0x4,
5361 [NEON_2RM_VCLT0_F] = 0x4,
5362 [NEON_2RM_VABS_F] = 0x4,
5363 [NEON_2RM_VNEG_F] = 0x4,
5364 [NEON_2RM_VSWP] = 0x1,
5365 [NEON_2RM_VTRN] = 0x7,
5366 [NEON_2RM_VUZP] = 0x7,
5367 [NEON_2RM_VZIP] = 0x7,
5368 [NEON_2RM_VMOVN] = 0x7,
5369 [NEON_2RM_VQMOVN] = 0x7,
5370 [NEON_2RM_VSHLL] = 0x7,
f1ecb913 5371 [NEON_2RM_SHA1SU1] = 0x4,
34f7b0a2 5372 [NEON_2RM_VRINTN] = 0x4,
2ce70625 5373 [NEON_2RM_VRINTX] = 0x4,
34f7b0a2
WN
5374 [NEON_2RM_VRINTA] = 0x4,
5375 [NEON_2RM_VRINTZ] = 0x4,
600b828c 5376 [NEON_2RM_VCVT_F16_F32] = 0x2,
34f7b0a2 5377 [NEON_2RM_VRINTM] = 0x4,
600b828c 5378 [NEON_2RM_VCVT_F32_F16] = 0x2,
34f7b0a2 5379 [NEON_2RM_VRINTP] = 0x4,
901ad525
WN
5380 [NEON_2RM_VCVTAU] = 0x4,
5381 [NEON_2RM_VCVTAS] = 0x4,
5382 [NEON_2RM_VCVTNU] = 0x4,
5383 [NEON_2RM_VCVTNS] = 0x4,
5384 [NEON_2RM_VCVTPU] = 0x4,
5385 [NEON_2RM_VCVTPS] = 0x4,
5386 [NEON_2RM_VCVTMU] = 0x4,
5387 [NEON_2RM_VCVTMS] = 0x4,
600b828c
PM
5388 [NEON_2RM_VRECPE] = 0x4,
5389 [NEON_2RM_VRSQRTE] = 0x4,
5390 [NEON_2RM_VRECPE_F] = 0x4,
5391 [NEON_2RM_VRSQRTE_F] = 0x4,
5392 [NEON_2RM_VCVT_FS] = 0x4,
5393 [NEON_2RM_VCVT_FU] = 0x4,
5394 [NEON_2RM_VCVT_SF] = 0x4,
5395 [NEON_2RM_VCVT_UF] = 0x4,
5396};
5397
9ee6e8bb
PB
5398/* Translate a NEON data processing instruction. Return nonzero if the
5399 instruction is invalid.
ad69471c
PB
5400 We process data in a mixture of 32-bit and 64-bit chunks.
5401 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
2c0262af 5402
7dcc1f89 5403static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
5404{
5405 int op;
5406 int q;
5407 int rd, rn, rm;
5408 int size;
5409 int shift;
5410 int pass;
5411 int count;
5412 int pairwise;
5413 int u;
ca9a32e4 5414 uint32_t imm, mask;
39d5492a 5415 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
a7812ae4 5416 TCGv_i64 tmp64;
9ee6e8bb 5417
2c7ffc41
PM
5418 /* FIXME: this access check should not take precedence over UNDEF
5419 * for invalid encodings; we will generate incorrect syndrome information
5420 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5421 */
9dbbc748 5422 if (s->fp_excp_el) {
2c7ffc41 5423 gen_exception_insn(s, 4, EXCP_UDEF,
7d197d2d 5424 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
5425 return 0;
5426 }
5427
5df8bac1 5428 if (!s->vfp_enabled)
9ee6e8bb
PB
5429 return 1;
5430 q = (insn & (1 << 6)) != 0;
5431 u = (insn >> 24) & 1;
5432 VFP_DREG_D(rd, insn);
5433 VFP_DREG_N(rn, insn);
5434 VFP_DREG_M(rm, insn);
5435 size = (insn >> 20) & 3;
5436 if ((insn & (1 << 23)) == 0) {
5437 /* Three register same length. */
5438 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
62698be3
PM
5439 /* Catch invalid op and bad size combinations: UNDEF */
5440 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
5441 return 1;
5442 }
25f84f79
PM
5443 /* All insns of this form UNDEF for either this condition or the
5444 * superset of cases "Q==1"; we catch the latter later.
5445 */
5446 if (q && ((rd | rn | rm) & 1)) {
5447 return 1;
5448 }
f1ecb913
AB
5449 /*
5450 * The SHA-1/SHA-256 3-register instructions require special treatment
5451 * here, as their size field is overloaded as an op type selector, and
5452 * they all consume their input in a single pass.
5453 */
5454 if (op == NEON_3R_SHA) {
5455 if (!q) {
5456 return 1;
5457 }
5458 if (!u) { /* SHA-1 */
d614a513 5459 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
f1ecb913
AB
5460 return 1;
5461 }
5462 tmp = tcg_const_i32(rd);
5463 tmp2 = tcg_const_i32(rn);
5464 tmp3 = tcg_const_i32(rm);
5465 tmp4 = tcg_const_i32(size);
5466 gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4);
5467 tcg_temp_free_i32(tmp4);
5468 } else { /* SHA-256 */
d614a513 5469 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256) || size == 3) {
f1ecb913
AB
5470 return 1;
5471 }
5472 tmp = tcg_const_i32(rd);
5473 tmp2 = tcg_const_i32(rn);
5474 tmp3 = tcg_const_i32(rm);
5475 switch (size) {
5476 case 0:
5477 gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3);
5478 break;
5479 case 1:
5480 gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3);
5481 break;
5482 case 2:
5483 gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3);
5484 break;
5485 }
5486 }
5487 tcg_temp_free_i32(tmp);
5488 tcg_temp_free_i32(tmp2);
5489 tcg_temp_free_i32(tmp3);
5490 return 0;
5491 }
62698be3
PM
5492 if (size == 3 && op != NEON_3R_LOGIC) {
5493 /* 64-bit element instructions. */
9ee6e8bb 5494 for (pass = 0; pass < (q ? 2 : 1); pass++) {
ad69471c
PB
5495 neon_load_reg64(cpu_V0, rn + pass);
5496 neon_load_reg64(cpu_V1, rm + pass);
9ee6e8bb 5497 switch (op) {
62698be3 5498 case NEON_3R_VQADD:
9ee6e8bb 5499 if (u) {
02da0b2d
PM
5500 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
5501 cpu_V0, cpu_V1);
2c0262af 5502 } else {
02da0b2d
PM
5503 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
5504 cpu_V0, cpu_V1);
2c0262af 5505 }
9ee6e8bb 5506 break;
62698be3 5507 case NEON_3R_VQSUB:
9ee6e8bb 5508 if (u) {
02da0b2d
PM
5509 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
5510 cpu_V0, cpu_V1);
ad69471c 5511 } else {
02da0b2d
PM
5512 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
5513 cpu_V0, cpu_V1);
ad69471c
PB
5514 }
5515 break;
62698be3 5516 case NEON_3R_VSHL:
ad69471c
PB
5517 if (u) {
5518 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5519 } else {
5520 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5521 }
5522 break;
62698be3 5523 case NEON_3R_VQSHL:
ad69471c 5524 if (u) {
02da0b2d
PM
5525 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5526 cpu_V1, cpu_V0);
ad69471c 5527 } else {
02da0b2d
PM
5528 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5529 cpu_V1, cpu_V0);
ad69471c
PB
5530 }
5531 break;
62698be3 5532 case NEON_3R_VRSHL:
ad69471c
PB
5533 if (u) {
5534 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
1e8d4eec 5535 } else {
ad69471c
PB
5536 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5537 }
5538 break;
62698be3 5539 case NEON_3R_VQRSHL:
ad69471c 5540 if (u) {
02da0b2d
PM
5541 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5542 cpu_V1, cpu_V0);
ad69471c 5543 } else {
02da0b2d
PM
5544 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5545 cpu_V1, cpu_V0);
1e8d4eec 5546 }
9ee6e8bb 5547 break;
62698be3 5548 case NEON_3R_VADD_VSUB:
9ee6e8bb 5549 if (u) {
ad69471c 5550 tcg_gen_sub_i64(CPU_V001);
9ee6e8bb 5551 } else {
ad69471c 5552 tcg_gen_add_i64(CPU_V001);
9ee6e8bb
PB
5553 }
5554 break;
5555 default:
5556 abort();
2c0262af 5557 }
ad69471c 5558 neon_store_reg64(cpu_V0, rd + pass);
2c0262af 5559 }
9ee6e8bb 5560 return 0;
2c0262af 5561 }
25f84f79 5562 pairwise = 0;
9ee6e8bb 5563 switch (op) {
62698be3
PM
5564 case NEON_3R_VSHL:
5565 case NEON_3R_VQSHL:
5566 case NEON_3R_VRSHL:
5567 case NEON_3R_VQRSHL:
9ee6e8bb 5568 {
ad69471c
PB
5569 int rtmp;
5570 /* Shift instruction operands are reversed. */
5571 rtmp = rn;
9ee6e8bb 5572 rn = rm;
ad69471c 5573 rm = rtmp;
9ee6e8bb 5574 }
2c0262af 5575 break;
25f84f79
PM
5576 case NEON_3R_VPADD:
5577 if (u) {
5578 return 1;
5579 }
5580 /* Fall through */
62698be3
PM
5581 case NEON_3R_VPMAX:
5582 case NEON_3R_VPMIN:
9ee6e8bb 5583 pairwise = 1;
2c0262af 5584 break;
25f84f79
PM
5585 case NEON_3R_FLOAT_ARITH:
5586 pairwise = (u && size < 2); /* if VPADD (float) */
5587 break;
5588 case NEON_3R_FLOAT_MINMAX:
5589 pairwise = u; /* if VPMIN/VPMAX (float) */
5590 break;
5591 case NEON_3R_FLOAT_CMP:
5592 if (!u && size) {
5593 /* no encoding for U=0 C=1x */
5594 return 1;
5595 }
5596 break;
5597 case NEON_3R_FLOAT_ACMP:
5598 if (!u) {
5599 return 1;
5600 }
5601 break;
505935fc
WN
5602 case NEON_3R_FLOAT_MISC:
5603 /* VMAXNM/VMINNM in ARMv8 */
d614a513 5604 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
25f84f79
PM
5605 return 1;
5606 }
2c0262af 5607 break;
25f84f79
PM
5608 case NEON_3R_VMUL:
5609 if (u && (size != 0)) {
5610 /* UNDEF on invalid size for polynomial subcase */
5611 return 1;
5612 }
2c0262af 5613 break;
da97f52c 5614 case NEON_3R_VFM:
d614a513 5615 if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) {
da97f52c
PM
5616 return 1;
5617 }
5618 break;
9ee6e8bb 5619 default:
2c0262af 5620 break;
9ee6e8bb 5621 }
dd8fbd78 5622
25f84f79
PM
5623 if (pairwise && q) {
5624 /* All the pairwise insns UNDEF if Q is set */
5625 return 1;
5626 }
5627
9ee6e8bb
PB
5628 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5629
5630 if (pairwise) {
5631 /* Pairwise. */
a5a14945
JR
5632 if (pass < 1) {
5633 tmp = neon_load_reg(rn, 0);
5634 tmp2 = neon_load_reg(rn, 1);
9ee6e8bb 5635 } else {
a5a14945
JR
5636 tmp = neon_load_reg(rm, 0);
5637 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb
PB
5638 }
5639 } else {
5640 /* Elementwise. */
dd8fbd78
FN
5641 tmp = neon_load_reg(rn, pass);
5642 tmp2 = neon_load_reg(rm, pass);
9ee6e8bb
PB
5643 }
5644 switch (op) {
62698be3 5645 case NEON_3R_VHADD:
9ee6e8bb
PB
5646 GEN_NEON_INTEGER_OP(hadd);
5647 break;
62698be3 5648 case NEON_3R_VQADD:
02da0b2d 5649 GEN_NEON_INTEGER_OP_ENV(qadd);
2c0262af 5650 break;
62698be3 5651 case NEON_3R_VRHADD:
9ee6e8bb 5652 GEN_NEON_INTEGER_OP(rhadd);
2c0262af 5653 break;
62698be3 5654 case NEON_3R_LOGIC: /* Logic ops. */
9ee6e8bb
PB
5655 switch ((u << 2) | size) {
5656 case 0: /* VAND */
dd8fbd78 5657 tcg_gen_and_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5658 break;
5659 case 1: /* BIC */
f669df27 5660 tcg_gen_andc_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5661 break;
5662 case 2: /* VORR */
dd8fbd78 5663 tcg_gen_or_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5664 break;
5665 case 3: /* VORN */
f669df27 5666 tcg_gen_orc_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5667 break;
5668 case 4: /* VEOR */
dd8fbd78 5669 tcg_gen_xor_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5670 break;
5671 case 5: /* VBSL */
dd8fbd78
FN
5672 tmp3 = neon_load_reg(rd, pass);
5673 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
7d1b0095 5674 tcg_temp_free_i32(tmp3);
9ee6e8bb
PB
5675 break;
5676 case 6: /* VBIT */
dd8fbd78
FN
5677 tmp3 = neon_load_reg(rd, pass);
5678 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
7d1b0095 5679 tcg_temp_free_i32(tmp3);
9ee6e8bb
PB
5680 break;
5681 case 7: /* VBIF */
dd8fbd78
FN
5682 tmp3 = neon_load_reg(rd, pass);
5683 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
7d1b0095 5684 tcg_temp_free_i32(tmp3);
9ee6e8bb 5685 break;
2c0262af
FB
5686 }
5687 break;
62698be3 5688 case NEON_3R_VHSUB:
9ee6e8bb
PB
5689 GEN_NEON_INTEGER_OP(hsub);
5690 break;
62698be3 5691 case NEON_3R_VQSUB:
02da0b2d 5692 GEN_NEON_INTEGER_OP_ENV(qsub);
2c0262af 5693 break;
62698be3 5694 case NEON_3R_VCGT:
9ee6e8bb
PB
5695 GEN_NEON_INTEGER_OP(cgt);
5696 break;
62698be3 5697 case NEON_3R_VCGE:
9ee6e8bb
PB
5698 GEN_NEON_INTEGER_OP(cge);
5699 break;
62698be3 5700 case NEON_3R_VSHL:
ad69471c 5701 GEN_NEON_INTEGER_OP(shl);
2c0262af 5702 break;
62698be3 5703 case NEON_3R_VQSHL:
02da0b2d 5704 GEN_NEON_INTEGER_OP_ENV(qshl);
2c0262af 5705 break;
62698be3 5706 case NEON_3R_VRSHL:
ad69471c 5707 GEN_NEON_INTEGER_OP(rshl);
2c0262af 5708 break;
62698be3 5709 case NEON_3R_VQRSHL:
02da0b2d 5710 GEN_NEON_INTEGER_OP_ENV(qrshl);
9ee6e8bb 5711 break;
62698be3 5712 case NEON_3R_VMAX:
9ee6e8bb
PB
5713 GEN_NEON_INTEGER_OP(max);
5714 break;
62698be3 5715 case NEON_3R_VMIN:
9ee6e8bb
PB
5716 GEN_NEON_INTEGER_OP(min);
5717 break;
62698be3 5718 case NEON_3R_VABD:
9ee6e8bb
PB
5719 GEN_NEON_INTEGER_OP(abd);
5720 break;
62698be3 5721 case NEON_3R_VABA:
9ee6e8bb 5722 GEN_NEON_INTEGER_OP(abd);
7d1b0095 5723 tcg_temp_free_i32(tmp2);
dd8fbd78
FN
5724 tmp2 = neon_load_reg(rd, pass);
5725 gen_neon_add(size, tmp, tmp2);
9ee6e8bb 5726 break;
62698be3 5727 case NEON_3R_VADD_VSUB:
9ee6e8bb 5728 if (!u) { /* VADD */
62698be3 5729 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
5730 } else { /* VSUB */
5731 switch (size) {
dd8fbd78
FN
5732 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
5733 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
5734 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
62698be3 5735 default: abort();
9ee6e8bb
PB
5736 }
5737 }
5738 break;
62698be3 5739 case NEON_3R_VTST_VCEQ:
9ee6e8bb
PB
5740 if (!u) { /* VTST */
5741 switch (size) {
dd8fbd78
FN
5742 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
5743 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
5744 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
62698be3 5745 default: abort();
9ee6e8bb
PB
5746 }
5747 } else { /* VCEQ */
5748 switch (size) {
dd8fbd78
FN
5749 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5750 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5751 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
62698be3 5752 default: abort();
9ee6e8bb
PB
5753 }
5754 }
5755 break;
62698be3 5756 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
9ee6e8bb 5757 switch (size) {
dd8fbd78
FN
5758 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5759 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5760 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
62698be3 5761 default: abort();
9ee6e8bb 5762 }
7d1b0095 5763 tcg_temp_free_i32(tmp2);
dd8fbd78 5764 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 5765 if (u) { /* VMLS */
dd8fbd78 5766 gen_neon_rsb(size, tmp, tmp2);
9ee6e8bb 5767 } else { /* VMLA */
dd8fbd78 5768 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
5769 }
5770 break;
62698be3 5771 case NEON_3R_VMUL:
9ee6e8bb 5772 if (u) { /* polynomial */
dd8fbd78 5773 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
9ee6e8bb
PB
5774 } else { /* Integer */
5775 switch (size) {
dd8fbd78
FN
5776 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5777 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5778 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
62698be3 5779 default: abort();
9ee6e8bb
PB
5780 }
5781 }
5782 break;
62698be3 5783 case NEON_3R_VPMAX:
9ee6e8bb
PB
5784 GEN_NEON_INTEGER_OP(pmax);
5785 break;
62698be3 5786 case NEON_3R_VPMIN:
9ee6e8bb
PB
5787 GEN_NEON_INTEGER_OP(pmin);
5788 break;
62698be3 5789 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
9ee6e8bb
PB
5790 if (!u) { /* VQDMULH */
5791 switch (size) {
02da0b2d
PM
5792 case 1:
5793 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5794 break;
5795 case 2:
5796 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5797 break;
62698be3 5798 default: abort();
9ee6e8bb 5799 }
62698be3 5800 } else { /* VQRDMULH */
9ee6e8bb 5801 switch (size) {
02da0b2d
PM
5802 case 1:
5803 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5804 break;
5805 case 2:
5806 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5807 break;
62698be3 5808 default: abort();
9ee6e8bb
PB
5809 }
5810 }
5811 break;
62698be3 5812 case NEON_3R_VPADD:
9ee6e8bb 5813 switch (size) {
dd8fbd78
FN
5814 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5815 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5816 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
62698be3 5817 default: abort();
9ee6e8bb
PB
5818 }
5819 break;
62698be3 5820 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
aa47cfdd
PM
5821 {
5822 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb
PB
5823 switch ((u << 2) | size) {
5824 case 0: /* VADD */
aa47cfdd
PM
5825 case 4: /* VPADD */
5826 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5827 break;
5828 case 2: /* VSUB */
aa47cfdd 5829 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5830 break;
5831 case 6: /* VABD */
aa47cfdd 5832 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5833 break;
5834 default:
62698be3 5835 abort();
9ee6e8bb 5836 }
aa47cfdd 5837 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5838 break;
aa47cfdd 5839 }
62698be3 5840 case NEON_3R_FLOAT_MULTIPLY:
aa47cfdd
PM
5841 {
5842 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5843 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 5844 if (!u) {
7d1b0095 5845 tcg_temp_free_i32(tmp2);
dd8fbd78 5846 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 5847 if (size == 0) {
aa47cfdd 5848 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 5849 } else {
aa47cfdd 5850 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
9ee6e8bb
PB
5851 }
5852 }
aa47cfdd 5853 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5854 break;
aa47cfdd 5855 }
62698be3 5856 case NEON_3R_FLOAT_CMP:
aa47cfdd
PM
5857 {
5858 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb 5859 if (!u) {
aa47cfdd 5860 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
b5ff1b31 5861 } else {
aa47cfdd
PM
5862 if (size == 0) {
5863 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5864 } else {
5865 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5866 }
b5ff1b31 5867 }
aa47cfdd 5868 tcg_temp_free_ptr(fpstatus);
2c0262af 5869 break;
aa47cfdd 5870 }
62698be3 5871 case NEON_3R_FLOAT_ACMP:
aa47cfdd
PM
5872 {
5873 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5874 if (size == 0) {
5875 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5876 } else {
5877 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5878 }
5879 tcg_temp_free_ptr(fpstatus);
2c0262af 5880 break;
aa47cfdd 5881 }
62698be3 5882 case NEON_3R_FLOAT_MINMAX:
aa47cfdd
PM
5883 {
5884 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5885 if (size == 0) {
f71a2ae5 5886 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
aa47cfdd 5887 } else {
f71a2ae5 5888 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
aa47cfdd
PM
5889 }
5890 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5891 break;
aa47cfdd 5892 }
505935fc
WN
5893 case NEON_3R_FLOAT_MISC:
5894 if (u) {
5895 /* VMAXNM/VMINNM */
5896 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5897 if (size == 0) {
f71a2ae5 5898 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
505935fc 5899 } else {
f71a2ae5 5900 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
505935fc
WN
5901 }
5902 tcg_temp_free_ptr(fpstatus);
5903 } else {
5904 if (size == 0) {
5905 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5906 } else {
5907 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5908 }
5909 }
2c0262af 5910 break;
da97f52c
PM
5911 case NEON_3R_VFM:
5912 {
5913 /* VFMA, VFMS: fused multiply-add */
5914 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5915 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5916 if (size) {
5917 /* VFMS */
5918 gen_helper_vfp_negs(tmp, tmp);
5919 }
5920 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5921 tcg_temp_free_i32(tmp3);
5922 tcg_temp_free_ptr(fpstatus);
5923 break;
5924 }
9ee6e8bb
PB
5925 default:
5926 abort();
2c0262af 5927 }
7d1b0095 5928 tcg_temp_free_i32(tmp2);
dd8fbd78 5929
9ee6e8bb
PB
5930 /* Save the result. For elementwise operations we can put it
5931 straight into the destination register. For pairwise operations
5932 we have to be careful to avoid clobbering the source operands. */
5933 if (pairwise && rd == rm) {
dd8fbd78 5934 neon_store_scratch(pass, tmp);
9ee6e8bb 5935 } else {
dd8fbd78 5936 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5937 }
5938
5939 } /* for pass */
5940 if (pairwise && rd == rm) {
5941 for (pass = 0; pass < (q ? 4 : 2); pass++) {
dd8fbd78
FN
5942 tmp = neon_load_scratch(pass);
5943 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5944 }
5945 }
ad69471c 5946 /* End of 3 register same size operations. */
9ee6e8bb
PB
5947 } else if (insn & (1 << 4)) {
5948 if ((insn & 0x00380080) != 0) {
5949 /* Two registers and shift. */
5950 op = (insn >> 8) & 0xf;
5951 if (insn & (1 << 7)) {
cc13115b
PM
5952 /* 64-bit shift. */
5953 if (op > 7) {
5954 return 1;
5955 }
9ee6e8bb
PB
5956 size = 3;
5957 } else {
5958 size = 2;
5959 while ((insn & (1 << (size + 19))) == 0)
5960 size--;
5961 }
5962 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
b90372ad 5963 /* To avoid excessive duplication of ops we implement shift
9ee6e8bb
PB
5964 by immediate using the variable shift operations. */
5965 if (op < 8) {
5966 /* Shift by immediate:
5967 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
cc13115b
PM
5968 if (q && ((rd | rm) & 1)) {
5969 return 1;
5970 }
5971 if (!u && (op == 4 || op == 6)) {
5972 return 1;
5973 }
9ee6e8bb
PB
5974 /* Right shifts are encoded as N - shift, where N is the
5975 element size in bits. */
5976 if (op <= 4)
5977 shift = shift - (1 << (size + 3));
9ee6e8bb
PB
5978 if (size == 3) {
5979 count = q + 1;
5980 } else {
5981 count = q ? 4: 2;
5982 }
5983 switch (size) {
5984 case 0:
5985 imm = (uint8_t) shift;
5986 imm |= imm << 8;
5987 imm |= imm << 16;
5988 break;
5989 case 1:
5990 imm = (uint16_t) shift;
5991 imm |= imm << 16;
5992 break;
5993 case 2:
5994 case 3:
5995 imm = shift;
5996 break;
5997 default:
5998 abort();
5999 }
6000
6001 for (pass = 0; pass < count; pass++) {
ad69471c
PB
6002 if (size == 3) {
6003 neon_load_reg64(cpu_V0, rm + pass);
6004 tcg_gen_movi_i64(cpu_V1, imm);
6005 switch (op) {
6006 case 0: /* VSHR */
6007 case 1: /* VSRA */
6008 if (u)
6009 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 6010 else
ad69471c 6011 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 6012 break;
ad69471c
PB
6013 case 2: /* VRSHR */
6014 case 3: /* VRSRA */
6015 if (u)
6016 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 6017 else
ad69471c 6018 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 6019 break;
ad69471c 6020 case 4: /* VSRI */
ad69471c
PB
6021 case 5: /* VSHL, VSLI */
6022 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
6023 break;
0322b26e 6024 case 6: /* VQSHLU */
02da0b2d
PM
6025 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
6026 cpu_V0, cpu_V1);
ad69471c 6027 break;
0322b26e
PM
6028 case 7: /* VQSHL */
6029 if (u) {
02da0b2d 6030 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
0322b26e
PM
6031 cpu_V0, cpu_V1);
6032 } else {
02da0b2d 6033 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
0322b26e
PM
6034 cpu_V0, cpu_V1);
6035 }
9ee6e8bb 6036 break;
9ee6e8bb 6037 }
ad69471c
PB
6038 if (op == 1 || op == 3) {
6039 /* Accumulate. */
5371cb81 6040 neon_load_reg64(cpu_V1, rd + pass);
ad69471c
PB
6041 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
6042 } else if (op == 4 || (op == 5 && u)) {
6043 /* Insert */
923e6509
CL
6044 neon_load_reg64(cpu_V1, rd + pass);
6045 uint64_t mask;
6046 if (shift < -63 || shift > 63) {
6047 mask = 0;
6048 } else {
6049 if (op == 4) {
6050 mask = 0xffffffffffffffffull >> -shift;
6051 } else {
6052 mask = 0xffffffffffffffffull << shift;
6053 }
6054 }
6055 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
6056 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
ad69471c
PB
6057 }
6058 neon_store_reg64(cpu_V0, rd + pass);
6059 } else { /* size < 3 */
6060 /* Operands in T0 and T1. */
dd8fbd78 6061 tmp = neon_load_reg(rm, pass);
7d1b0095 6062 tmp2 = tcg_temp_new_i32();
dd8fbd78 6063 tcg_gen_movi_i32(tmp2, imm);
ad69471c
PB
6064 switch (op) {
6065 case 0: /* VSHR */
6066 case 1: /* VSRA */
6067 GEN_NEON_INTEGER_OP(shl);
6068 break;
6069 case 2: /* VRSHR */
6070 case 3: /* VRSRA */
6071 GEN_NEON_INTEGER_OP(rshl);
6072 break;
6073 case 4: /* VSRI */
ad69471c
PB
6074 case 5: /* VSHL, VSLI */
6075 switch (size) {
dd8fbd78
FN
6076 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
6077 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
6078 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
cc13115b 6079 default: abort();
ad69471c
PB
6080 }
6081 break;
0322b26e 6082 case 6: /* VQSHLU */
ad69471c 6083 switch (size) {
0322b26e 6084 case 0:
02da0b2d
PM
6085 gen_helper_neon_qshlu_s8(tmp, cpu_env,
6086 tmp, tmp2);
0322b26e
PM
6087 break;
6088 case 1:
02da0b2d
PM
6089 gen_helper_neon_qshlu_s16(tmp, cpu_env,
6090 tmp, tmp2);
0322b26e
PM
6091 break;
6092 case 2:
02da0b2d
PM
6093 gen_helper_neon_qshlu_s32(tmp, cpu_env,
6094 tmp, tmp2);
0322b26e
PM
6095 break;
6096 default:
cc13115b 6097 abort();
ad69471c
PB
6098 }
6099 break;
0322b26e 6100 case 7: /* VQSHL */
02da0b2d 6101 GEN_NEON_INTEGER_OP_ENV(qshl);
0322b26e 6102 break;
ad69471c 6103 }
7d1b0095 6104 tcg_temp_free_i32(tmp2);
ad69471c
PB
6105
6106 if (op == 1 || op == 3) {
6107 /* Accumulate. */
dd8fbd78 6108 tmp2 = neon_load_reg(rd, pass);
5371cb81 6109 gen_neon_add(size, tmp, tmp2);
7d1b0095 6110 tcg_temp_free_i32(tmp2);
ad69471c
PB
6111 } else if (op == 4 || (op == 5 && u)) {
6112 /* Insert */
6113 switch (size) {
6114 case 0:
6115 if (op == 4)
ca9a32e4 6116 mask = 0xff >> -shift;
ad69471c 6117 else
ca9a32e4
JR
6118 mask = (uint8_t)(0xff << shift);
6119 mask |= mask << 8;
6120 mask |= mask << 16;
ad69471c
PB
6121 break;
6122 case 1:
6123 if (op == 4)
ca9a32e4 6124 mask = 0xffff >> -shift;
ad69471c 6125 else
ca9a32e4
JR
6126 mask = (uint16_t)(0xffff << shift);
6127 mask |= mask << 16;
ad69471c
PB
6128 break;
6129 case 2:
ca9a32e4
JR
6130 if (shift < -31 || shift > 31) {
6131 mask = 0;
6132 } else {
6133 if (op == 4)
6134 mask = 0xffffffffu >> -shift;
6135 else
6136 mask = 0xffffffffu << shift;
6137 }
ad69471c
PB
6138 break;
6139 default:
6140 abort();
6141 }
dd8fbd78 6142 tmp2 = neon_load_reg(rd, pass);
ca9a32e4
JR
6143 tcg_gen_andi_i32(tmp, tmp, mask);
6144 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
dd8fbd78 6145 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 6146 tcg_temp_free_i32(tmp2);
ad69471c 6147 }
dd8fbd78 6148 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6149 }
6150 } /* for pass */
6151 } else if (op < 10) {
ad69471c 6152 /* Shift by immediate and narrow:
9ee6e8bb 6153 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
0b36f4cd 6154 int input_unsigned = (op == 8) ? !u : u;
cc13115b
PM
6155 if (rm & 1) {
6156 return 1;
6157 }
9ee6e8bb
PB
6158 shift = shift - (1 << (size + 3));
6159 size++;
92cdfaeb 6160 if (size == 3) {
a7812ae4 6161 tmp64 = tcg_const_i64(shift);
92cdfaeb
PM
6162 neon_load_reg64(cpu_V0, rm);
6163 neon_load_reg64(cpu_V1, rm + 1);
6164 for (pass = 0; pass < 2; pass++) {
6165 TCGv_i64 in;
6166 if (pass == 0) {
6167 in = cpu_V0;
6168 } else {
6169 in = cpu_V1;
6170 }
ad69471c 6171 if (q) {
0b36f4cd 6172 if (input_unsigned) {
92cdfaeb 6173 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
0b36f4cd 6174 } else {
92cdfaeb 6175 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
0b36f4cd 6176 }
ad69471c 6177 } else {
0b36f4cd 6178 if (input_unsigned) {
92cdfaeb 6179 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
0b36f4cd 6180 } else {
92cdfaeb 6181 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
0b36f4cd 6182 }
ad69471c 6183 }
7d1b0095 6184 tmp = tcg_temp_new_i32();
92cdfaeb
PM
6185 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6186 neon_store_reg(rd, pass, tmp);
6187 } /* for pass */
6188 tcg_temp_free_i64(tmp64);
6189 } else {
6190 if (size == 1) {
6191 imm = (uint16_t)shift;
6192 imm |= imm << 16;
2c0262af 6193 } else {
92cdfaeb
PM
6194 /* size == 2 */
6195 imm = (uint32_t)shift;
6196 }
6197 tmp2 = tcg_const_i32(imm);
6198 tmp4 = neon_load_reg(rm + 1, 0);
6199 tmp5 = neon_load_reg(rm + 1, 1);
6200 for (pass = 0; pass < 2; pass++) {
6201 if (pass == 0) {
6202 tmp = neon_load_reg(rm, 0);
6203 } else {
6204 tmp = tmp4;
6205 }
0b36f4cd
CL
6206 gen_neon_shift_narrow(size, tmp, tmp2, q,
6207 input_unsigned);
92cdfaeb
PM
6208 if (pass == 0) {
6209 tmp3 = neon_load_reg(rm, 1);
6210 } else {
6211 tmp3 = tmp5;
6212 }
0b36f4cd
CL
6213 gen_neon_shift_narrow(size, tmp3, tmp2, q,
6214 input_unsigned);
36aa55dc 6215 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
7d1b0095
PM
6216 tcg_temp_free_i32(tmp);
6217 tcg_temp_free_i32(tmp3);
6218 tmp = tcg_temp_new_i32();
92cdfaeb
PM
6219 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6220 neon_store_reg(rd, pass, tmp);
6221 } /* for pass */
c6067f04 6222 tcg_temp_free_i32(tmp2);
b75263d6 6223 }
9ee6e8bb 6224 } else if (op == 10) {
cc13115b
PM
6225 /* VSHLL, VMOVL */
6226 if (q || (rd & 1)) {
9ee6e8bb 6227 return 1;
cc13115b 6228 }
ad69471c
PB
6229 tmp = neon_load_reg(rm, 0);
6230 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 6231 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6232 if (pass == 1)
6233 tmp = tmp2;
6234
6235 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb 6236
9ee6e8bb
PB
6237 if (shift != 0) {
6238 /* The shift is less than the width of the source
ad69471c
PB
6239 type, so we can just shift the whole register. */
6240 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
acdf01ef
CL
6241 /* Widen the result of shift: we need to clear
6242 * the potential overflow bits resulting from
6243 * left bits of the narrow input appearing as
6244 * right bits of left the neighbour narrow
6245 * input. */
ad69471c
PB
6246 if (size < 2 || !u) {
6247 uint64_t imm64;
6248 if (size == 0) {
6249 imm = (0xffu >> (8 - shift));
6250 imm |= imm << 16;
acdf01ef 6251 } else if (size == 1) {
ad69471c 6252 imm = 0xffff >> (16 - shift);
acdf01ef
CL
6253 } else {
6254 /* size == 2 */
6255 imm = 0xffffffff >> (32 - shift);
6256 }
6257 if (size < 2) {
6258 imm64 = imm | (((uint64_t)imm) << 32);
6259 } else {
6260 imm64 = imm;
9ee6e8bb 6261 }
acdf01ef 6262 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
9ee6e8bb
PB
6263 }
6264 }
ad69471c 6265 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 6266 }
f73534a5 6267 } else if (op >= 14) {
9ee6e8bb 6268 /* VCVT fixed-point. */
cc13115b
PM
6269 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
6270 return 1;
6271 }
f73534a5
PM
6272 /* We have already masked out the must-be-1 top bit of imm6,
6273 * hence this 32-shift where the ARM ARM has 64-imm6.
6274 */
6275 shift = 32 - shift;
9ee6e8bb 6276 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4373f3ce 6277 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
f73534a5 6278 if (!(op & 1)) {
9ee6e8bb 6279 if (u)
5500b06c 6280 gen_vfp_ulto(0, shift, 1);
9ee6e8bb 6281 else
5500b06c 6282 gen_vfp_slto(0, shift, 1);
9ee6e8bb
PB
6283 } else {
6284 if (u)
5500b06c 6285 gen_vfp_toul(0, shift, 1);
9ee6e8bb 6286 else
5500b06c 6287 gen_vfp_tosl(0, shift, 1);
2c0262af 6288 }
4373f3ce 6289 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
2c0262af
FB
6290 }
6291 } else {
9ee6e8bb
PB
6292 return 1;
6293 }
6294 } else { /* (insn & 0x00380080) == 0 */
6295 int invert;
7d80fee5
PM
6296 if (q && (rd & 1)) {
6297 return 1;
6298 }
9ee6e8bb
PB
6299
6300 op = (insn >> 8) & 0xf;
6301 /* One register and immediate. */
6302 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
6303 invert = (insn & (1 << 5)) != 0;
7d80fee5
PM
6304 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
6305 * We choose to not special-case this and will behave as if a
6306 * valid constant encoding of 0 had been given.
6307 */
9ee6e8bb
PB
6308 switch (op) {
6309 case 0: case 1:
6310 /* no-op */
6311 break;
6312 case 2: case 3:
6313 imm <<= 8;
6314 break;
6315 case 4: case 5:
6316 imm <<= 16;
6317 break;
6318 case 6: case 7:
6319 imm <<= 24;
6320 break;
6321 case 8: case 9:
6322 imm |= imm << 16;
6323 break;
6324 case 10: case 11:
6325 imm = (imm << 8) | (imm << 24);
6326 break;
6327 case 12:
8e31209e 6328 imm = (imm << 8) | 0xff;
9ee6e8bb
PB
6329 break;
6330 case 13:
6331 imm = (imm << 16) | 0xffff;
6332 break;
6333 case 14:
6334 imm |= (imm << 8) | (imm << 16) | (imm << 24);
6335 if (invert)
6336 imm = ~imm;
6337 break;
6338 case 15:
7d80fee5
PM
6339 if (invert) {
6340 return 1;
6341 }
9ee6e8bb
PB
6342 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
6343 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
6344 break;
6345 }
6346 if (invert)
6347 imm = ~imm;
6348
9ee6e8bb
PB
6349 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6350 if (op & 1 && op < 12) {
ad69471c 6351 tmp = neon_load_reg(rd, pass);
9ee6e8bb
PB
6352 if (invert) {
6353 /* The immediate value has already been inverted, so
6354 BIC becomes AND. */
ad69471c 6355 tcg_gen_andi_i32(tmp, tmp, imm);
9ee6e8bb 6356 } else {
ad69471c 6357 tcg_gen_ori_i32(tmp, tmp, imm);
9ee6e8bb 6358 }
9ee6e8bb 6359 } else {
ad69471c 6360 /* VMOV, VMVN. */
7d1b0095 6361 tmp = tcg_temp_new_i32();
9ee6e8bb 6362 if (op == 14 && invert) {
a5a14945 6363 int n;
ad69471c
PB
6364 uint32_t val;
6365 val = 0;
9ee6e8bb
PB
6366 for (n = 0; n < 4; n++) {
6367 if (imm & (1 << (n + (pass & 1) * 4)))
ad69471c 6368 val |= 0xff << (n * 8);
9ee6e8bb 6369 }
ad69471c
PB
6370 tcg_gen_movi_i32(tmp, val);
6371 } else {
6372 tcg_gen_movi_i32(tmp, imm);
9ee6e8bb 6373 }
9ee6e8bb 6374 }
ad69471c 6375 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6376 }
6377 }
e4b3861d 6378 } else { /* (insn & 0x00800010 == 0x00800000) */
9ee6e8bb
PB
6379 if (size != 3) {
6380 op = (insn >> 8) & 0xf;
6381 if ((insn & (1 << 6)) == 0) {
6382 /* Three registers of different lengths. */
6383 int src1_wide;
6384 int src2_wide;
6385 int prewiden;
526d0096
PM
6386 /* undefreq: bit 0 : UNDEF if size == 0
6387 * bit 1 : UNDEF if size == 1
6388 * bit 2 : UNDEF if size == 2
6389 * bit 3 : UNDEF if U == 1
6390 * Note that [2:0] set implies 'always UNDEF'
695272dc
PM
6391 */
6392 int undefreq;
6393 /* prewiden, src1_wide, src2_wide, undefreq */
6394 static const int neon_3reg_wide[16][4] = {
6395 {1, 0, 0, 0}, /* VADDL */
6396 {1, 1, 0, 0}, /* VADDW */
6397 {1, 0, 0, 0}, /* VSUBL */
6398 {1, 1, 0, 0}, /* VSUBW */
6399 {0, 1, 1, 0}, /* VADDHN */
6400 {0, 0, 0, 0}, /* VABAL */
6401 {0, 1, 1, 0}, /* VSUBHN */
6402 {0, 0, 0, 0}, /* VABDL */
6403 {0, 0, 0, 0}, /* VMLAL */
526d0096 6404 {0, 0, 0, 9}, /* VQDMLAL */
695272dc 6405 {0, 0, 0, 0}, /* VMLSL */
526d0096 6406 {0, 0, 0, 9}, /* VQDMLSL */
695272dc 6407 {0, 0, 0, 0}, /* Integer VMULL */
526d0096 6408 {0, 0, 0, 1}, /* VQDMULL */
4e624eda 6409 {0, 0, 0, 0xa}, /* Polynomial VMULL */
526d0096 6410 {0, 0, 0, 7}, /* Reserved: always UNDEF */
9ee6e8bb
PB
6411 };
6412
6413 prewiden = neon_3reg_wide[op][0];
6414 src1_wide = neon_3reg_wide[op][1];
6415 src2_wide = neon_3reg_wide[op][2];
695272dc 6416 undefreq = neon_3reg_wide[op][3];
9ee6e8bb 6417
526d0096
PM
6418 if ((undefreq & (1 << size)) ||
6419 ((undefreq & 8) && u)) {
695272dc
PM
6420 return 1;
6421 }
6422 if ((src1_wide && (rn & 1)) ||
6423 (src2_wide && (rm & 1)) ||
6424 (!src2_wide && (rd & 1))) {
ad69471c 6425 return 1;
695272dc 6426 }
ad69471c 6427
4e624eda
PM
6428 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
6429 * outside the loop below as it only performs a single pass.
6430 */
6431 if (op == 14 && size == 2) {
6432 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
6433
d614a513 6434 if (!arm_dc_feature(s, ARM_FEATURE_V8_PMULL)) {
4e624eda
PM
6435 return 1;
6436 }
6437 tcg_rn = tcg_temp_new_i64();
6438 tcg_rm = tcg_temp_new_i64();
6439 tcg_rd = tcg_temp_new_i64();
6440 neon_load_reg64(tcg_rn, rn);
6441 neon_load_reg64(tcg_rm, rm);
6442 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
6443 neon_store_reg64(tcg_rd, rd);
6444 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
6445 neon_store_reg64(tcg_rd, rd + 1);
6446 tcg_temp_free_i64(tcg_rn);
6447 tcg_temp_free_i64(tcg_rm);
6448 tcg_temp_free_i64(tcg_rd);
6449 return 0;
6450 }
6451
9ee6e8bb
PB
6452 /* Avoid overlapping operands. Wide source operands are
6453 always aligned so will never overlap with wide
6454 destinations in problematic ways. */
8f8e3aa4 6455 if (rd == rm && !src2_wide) {
dd8fbd78
FN
6456 tmp = neon_load_reg(rm, 1);
6457 neon_store_scratch(2, tmp);
8f8e3aa4 6458 } else if (rd == rn && !src1_wide) {
dd8fbd78
FN
6459 tmp = neon_load_reg(rn, 1);
6460 neon_store_scratch(2, tmp);
9ee6e8bb 6461 }
39d5492a 6462 TCGV_UNUSED_I32(tmp3);
9ee6e8bb 6463 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6464 if (src1_wide) {
6465 neon_load_reg64(cpu_V0, rn + pass);
39d5492a 6466 TCGV_UNUSED_I32(tmp);
9ee6e8bb 6467 } else {
ad69471c 6468 if (pass == 1 && rd == rn) {
dd8fbd78 6469 tmp = neon_load_scratch(2);
9ee6e8bb 6470 } else {
ad69471c
PB
6471 tmp = neon_load_reg(rn, pass);
6472 }
6473 if (prewiden) {
6474 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb
PB
6475 }
6476 }
ad69471c
PB
6477 if (src2_wide) {
6478 neon_load_reg64(cpu_V1, rm + pass);
39d5492a 6479 TCGV_UNUSED_I32(tmp2);
9ee6e8bb 6480 } else {
ad69471c 6481 if (pass == 1 && rd == rm) {
dd8fbd78 6482 tmp2 = neon_load_scratch(2);
9ee6e8bb 6483 } else {
ad69471c
PB
6484 tmp2 = neon_load_reg(rm, pass);
6485 }
6486 if (prewiden) {
6487 gen_neon_widen(cpu_V1, tmp2, size, u);
9ee6e8bb 6488 }
9ee6e8bb
PB
6489 }
6490 switch (op) {
6491 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
ad69471c 6492 gen_neon_addl(size);
9ee6e8bb 6493 break;
79b0e534 6494 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
ad69471c 6495 gen_neon_subl(size);
9ee6e8bb
PB
6496 break;
6497 case 5: case 7: /* VABAL, VABDL */
6498 switch ((size << 1) | u) {
ad69471c
PB
6499 case 0:
6500 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
6501 break;
6502 case 1:
6503 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
6504 break;
6505 case 2:
6506 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
6507 break;
6508 case 3:
6509 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
6510 break;
6511 case 4:
6512 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
6513 break;
6514 case 5:
6515 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
6516 break;
9ee6e8bb
PB
6517 default: abort();
6518 }
7d1b0095
PM
6519 tcg_temp_free_i32(tmp2);
6520 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
6521 break;
6522 case 8: case 9: case 10: case 11: case 12: case 13:
6523 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
ad69471c 6524 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
9ee6e8bb
PB
6525 break;
6526 case 14: /* Polynomial VMULL */
e5ca24cb 6527 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
7d1b0095
PM
6528 tcg_temp_free_i32(tmp2);
6529 tcg_temp_free_i32(tmp);
e5ca24cb 6530 break;
695272dc
PM
6531 default: /* 15 is RESERVED: caught earlier */
6532 abort();
9ee6e8bb 6533 }
ebcd88ce
PM
6534 if (op == 13) {
6535 /* VQDMULL */
6536 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6537 neon_store_reg64(cpu_V0, rd + pass);
6538 } else if (op == 5 || (op >= 8 && op <= 11)) {
9ee6e8bb 6539 /* Accumulate. */
ebcd88ce 6540 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 6541 switch (op) {
4dc064e6
PM
6542 case 10: /* VMLSL */
6543 gen_neon_negl(cpu_V0, size);
6544 /* Fall through */
6545 case 5: case 8: /* VABAL, VMLAL */
ad69471c 6546 gen_neon_addl(size);
9ee6e8bb
PB
6547 break;
6548 case 9: case 11: /* VQDMLAL, VQDMLSL */
ad69471c 6549 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
6550 if (op == 11) {
6551 gen_neon_negl(cpu_V0, size);
6552 }
ad69471c
PB
6553 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6554 break;
9ee6e8bb
PB
6555 default:
6556 abort();
6557 }
ad69471c 6558 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6559 } else if (op == 4 || op == 6) {
6560 /* Narrowing operation. */
7d1b0095 6561 tmp = tcg_temp_new_i32();
79b0e534 6562 if (!u) {
9ee6e8bb 6563 switch (size) {
ad69471c
PB
6564 case 0:
6565 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6566 break;
6567 case 1:
6568 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6569 break;
6570 case 2:
6571 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 6572 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
ad69471c 6573 break;
9ee6e8bb
PB
6574 default: abort();
6575 }
6576 } else {
6577 switch (size) {
ad69471c
PB
6578 case 0:
6579 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6580 break;
6581 case 1:
6582 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6583 break;
6584 case 2:
6585 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6586 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 6587 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
ad69471c 6588 break;
9ee6e8bb
PB
6589 default: abort();
6590 }
6591 }
ad69471c
PB
6592 if (pass == 0) {
6593 tmp3 = tmp;
6594 } else {
6595 neon_store_reg(rd, 0, tmp3);
6596 neon_store_reg(rd, 1, tmp);
6597 }
9ee6e8bb
PB
6598 } else {
6599 /* Write back the result. */
ad69471c 6600 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6601 }
6602 }
6603 } else {
3e3326df
PM
6604 /* Two registers and a scalar. NB that for ops of this form
6605 * the ARM ARM labels bit 24 as Q, but it is in our variable
6606 * 'u', not 'q'.
6607 */
6608 if (size == 0) {
6609 return 1;
6610 }
9ee6e8bb 6611 switch (op) {
9ee6e8bb 6612 case 1: /* Float VMLA scalar */
9ee6e8bb 6613 case 5: /* Floating point VMLS scalar */
9ee6e8bb 6614 case 9: /* Floating point VMUL scalar */
3e3326df
PM
6615 if (size == 1) {
6616 return 1;
6617 }
6618 /* fall through */
6619 case 0: /* Integer VMLA scalar */
6620 case 4: /* Integer VMLS scalar */
6621 case 8: /* Integer VMUL scalar */
9ee6e8bb
PB
6622 case 12: /* VQDMULH scalar */
6623 case 13: /* VQRDMULH scalar */
3e3326df
PM
6624 if (u && ((rd | rn) & 1)) {
6625 return 1;
6626 }
dd8fbd78
FN
6627 tmp = neon_get_scalar(size, rm);
6628 neon_store_scratch(0, tmp);
9ee6e8bb 6629 for (pass = 0; pass < (u ? 4 : 2); pass++) {
dd8fbd78
FN
6630 tmp = neon_load_scratch(0);
6631 tmp2 = neon_load_reg(rn, pass);
9ee6e8bb
PB
6632 if (op == 12) {
6633 if (size == 1) {
02da0b2d 6634 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 6635 } else {
02da0b2d 6636 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
6637 }
6638 } else if (op == 13) {
6639 if (size == 1) {
02da0b2d 6640 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 6641 } else {
02da0b2d 6642 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
6643 }
6644 } else if (op & 1) {
aa47cfdd
PM
6645 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6646 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6647 tcg_temp_free_ptr(fpstatus);
9ee6e8bb
PB
6648 } else {
6649 switch (size) {
dd8fbd78
FN
6650 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6651 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6652 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
3e3326df 6653 default: abort();
9ee6e8bb
PB
6654 }
6655 }
7d1b0095 6656 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
6657 if (op < 8) {
6658 /* Accumulate. */
dd8fbd78 6659 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb
PB
6660 switch (op) {
6661 case 0:
dd8fbd78 6662 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
6663 break;
6664 case 1:
aa47cfdd
PM
6665 {
6666 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6667 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6668 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6669 break;
aa47cfdd 6670 }
9ee6e8bb 6671 case 4:
dd8fbd78 6672 gen_neon_rsb(size, tmp, tmp2);
9ee6e8bb
PB
6673 break;
6674 case 5:
aa47cfdd
PM
6675 {
6676 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6677 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6678 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6679 break;
aa47cfdd 6680 }
9ee6e8bb
PB
6681 default:
6682 abort();
6683 }
7d1b0095 6684 tcg_temp_free_i32(tmp2);
9ee6e8bb 6685 }
dd8fbd78 6686 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6687 }
6688 break;
9ee6e8bb 6689 case 3: /* VQDMLAL scalar */
9ee6e8bb 6690 case 7: /* VQDMLSL scalar */
9ee6e8bb 6691 case 11: /* VQDMULL scalar */
3e3326df 6692 if (u == 1) {
ad69471c 6693 return 1;
3e3326df
PM
6694 }
6695 /* fall through */
6696 case 2: /* VMLAL sclar */
6697 case 6: /* VMLSL scalar */
6698 case 10: /* VMULL scalar */
6699 if (rd & 1) {
6700 return 1;
6701 }
dd8fbd78 6702 tmp2 = neon_get_scalar(size, rm);
c6067f04
CL
6703 /* We need a copy of tmp2 because gen_neon_mull
6704 * deletes it during pass 0. */
7d1b0095 6705 tmp4 = tcg_temp_new_i32();
c6067f04 6706 tcg_gen_mov_i32(tmp4, tmp2);
dd8fbd78 6707 tmp3 = neon_load_reg(rn, 1);
ad69471c 6708
9ee6e8bb 6709 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6710 if (pass == 0) {
6711 tmp = neon_load_reg(rn, 0);
9ee6e8bb 6712 } else {
dd8fbd78 6713 tmp = tmp3;
c6067f04 6714 tmp2 = tmp4;
9ee6e8bb 6715 }
ad69471c 6716 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
ad69471c
PB
6717 if (op != 11) {
6718 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 6719 }
9ee6e8bb 6720 switch (op) {
4dc064e6
PM
6721 case 6:
6722 gen_neon_negl(cpu_V0, size);
6723 /* Fall through */
6724 case 2:
ad69471c 6725 gen_neon_addl(size);
9ee6e8bb
PB
6726 break;
6727 case 3: case 7:
ad69471c 6728 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
6729 if (op == 7) {
6730 gen_neon_negl(cpu_V0, size);
6731 }
ad69471c 6732 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
9ee6e8bb
PB
6733 break;
6734 case 10:
6735 /* no-op */
6736 break;
6737 case 11:
ad69471c 6738 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
9ee6e8bb
PB
6739 break;
6740 default:
6741 abort();
6742 }
ad69471c 6743 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 6744 }
dd8fbd78 6745
dd8fbd78 6746
9ee6e8bb
PB
6747 break;
6748 default: /* 14 and 15 are RESERVED */
6749 return 1;
6750 }
6751 }
6752 } else { /* size == 3 */
6753 if (!u) {
6754 /* Extract. */
9ee6e8bb 6755 imm = (insn >> 8) & 0xf;
ad69471c
PB
6756
6757 if (imm > 7 && !q)
6758 return 1;
6759
52579ea1
PM
6760 if (q && ((rd | rn | rm) & 1)) {
6761 return 1;
6762 }
6763
ad69471c
PB
6764 if (imm == 0) {
6765 neon_load_reg64(cpu_V0, rn);
6766 if (q) {
6767 neon_load_reg64(cpu_V1, rn + 1);
9ee6e8bb 6768 }
ad69471c
PB
6769 } else if (imm == 8) {
6770 neon_load_reg64(cpu_V0, rn + 1);
6771 if (q) {
6772 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 6773 }
ad69471c 6774 } else if (q) {
a7812ae4 6775 tmp64 = tcg_temp_new_i64();
ad69471c
PB
6776 if (imm < 8) {
6777 neon_load_reg64(cpu_V0, rn);
a7812ae4 6778 neon_load_reg64(tmp64, rn + 1);
ad69471c
PB
6779 } else {
6780 neon_load_reg64(cpu_V0, rn + 1);
a7812ae4 6781 neon_load_reg64(tmp64, rm);
ad69471c
PB
6782 }
6783 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
a7812ae4 6784 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
ad69471c
PB
6785 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6786 if (imm < 8) {
6787 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 6788 } else {
ad69471c
PB
6789 neon_load_reg64(cpu_V1, rm + 1);
6790 imm -= 8;
9ee6e8bb 6791 }
ad69471c 6792 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
a7812ae4
PB
6793 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6794 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
b75263d6 6795 tcg_temp_free_i64(tmp64);
ad69471c 6796 } else {
a7812ae4 6797 /* BUGFIX */
ad69471c 6798 neon_load_reg64(cpu_V0, rn);
a7812ae4 6799 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
ad69471c 6800 neon_load_reg64(cpu_V1, rm);
a7812ae4 6801 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
ad69471c
PB
6802 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6803 }
6804 neon_store_reg64(cpu_V0, rd);
6805 if (q) {
6806 neon_store_reg64(cpu_V1, rd + 1);
9ee6e8bb
PB
6807 }
6808 } else if ((insn & (1 << 11)) == 0) {
6809 /* Two register misc. */
6810 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6811 size = (insn >> 18) & 3;
600b828c
PM
6812 /* UNDEF for unknown op values and bad op-size combinations */
6813 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6814 return 1;
6815 }
fe8fcf3d
PM
6816 if (neon_2rm_is_v8_op(op) &&
6817 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6818 return 1;
6819 }
fc2a9b37
PM
6820 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6821 q && ((rm | rd) & 1)) {
6822 return 1;
6823 }
9ee6e8bb 6824 switch (op) {
600b828c 6825 case NEON_2RM_VREV64:
9ee6e8bb 6826 for (pass = 0; pass < (q ? 2 : 1); pass++) {
dd8fbd78
FN
6827 tmp = neon_load_reg(rm, pass * 2);
6828 tmp2 = neon_load_reg(rm, pass * 2 + 1);
9ee6e8bb 6829 switch (size) {
dd8fbd78
FN
6830 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6831 case 1: gen_swap_half(tmp); break;
9ee6e8bb
PB
6832 case 2: /* no-op */ break;
6833 default: abort();
6834 }
dd8fbd78 6835 neon_store_reg(rd, pass * 2 + 1, tmp);
9ee6e8bb 6836 if (size == 2) {
dd8fbd78 6837 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb 6838 } else {
9ee6e8bb 6839 switch (size) {
dd8fbd78
FN
6840 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6841 case 1: gen_swap_half(tmp2); break;
9ee6e8bb
PB
6842 default: abort();
6843 }
dd8fbd78 6844 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb
PB
6845 }
6846 }
6847 break;
600b828c
PM
6848 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6849 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
ad69471c
PB
6850 for (pass = 0; pass < q + 1; pass++) {
6851 tmp = neon_load_reg(rm, pass * 2);
6852 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6853 tmp = neon_load_reg(rm, pass * 2 + 1);
6854 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6855 switch (size) {
6856 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6857 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6858 case 2: tcg_gen_add_i64(CPU_V001); break;
6859 default: abort();
6860 }
600b828c 6861 if (op >= NEON_2RM_VPADAL) {
9ee6e8bb 6862 /* Accumulate. */
ad69471c
PB
6863 neon_load_reg64(cpu_V1, rd + pass);
6864 gen_neon_addl(size);
9ee6e8bb 6865 }
ad69471c 6866 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6867 }
6868 break;
600b828c 6869 case NEON_2RM_VTRN:
9ee6e8bb 6870 if (size == 2) {
a5a14945 6871 int n;
9ee6e8bb 6872 for (n = 0; n < (q ? 4 : 2); n += 2) {
dd8fbd78
FN
6873 tmp = neon_load_reg(rm, n);
6874 tmp2 = neon_load_reg(rd, n + 1);
6875 neon_store_reg(rm, n, tmp2);
6876 neon_store_reg(rd, n + 1, tmp);
9ee6e8bb
PB
6877 }
6878 } else {
6879 goto elementwise;
6880 }
6881 break;
600b828c 6882 case NEON_2RM_VUZP:
02acedf9 6883 if (gen_neon_unzip(rd, rm, size, q)) {
9ee6e8bb 6884 return 1;
9ee6e8bb
PB
6885 }
6886 break;
600b828c 6887 case NEON_2RM_VZIP:
d68a6f3a 6888 if (gen_neon_zip(rd, rm, size, q)) {
9ee6e8bb 6889 return 1;
9ee6e8bb
PB
6890 }
6891 break;
600b828c
PM
6892 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6893 /* also VQMOVUN; op field and mnemonics don't line up */
fc2a9b37
PM
6894 if (rm & 1) {
6895 return 1;
6896 }
39d5492a 6897 TCGV_UNUSED_I32(tmp2);
9ee6e8bb 6898 for (pass = 0; pass < 2; pass++) {
ad69471c 6899 neon_load_reg64(cpu_V0, rm + pass);
7d1b0095 6900 tmp = tcg_temp_new_i32();
600b828c
PM
6901 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6902 tmp, cpu_V0);
ad69471c
PB
6903 if (pass == 0) {
6904 tmp2 = tmp;
6905 } else {
6906 neon_store_reg(rd, 0, tmp2);
6907 neon_store_reg(rd, 1, tmp);
9ee6e8bb 6908 }
9ee6e8bb
PB
6909 }
6910 break;
600b828c 6911 case NEON_2RM_VSHLL:
fc2a9b37 6912 if (q || (rd & 1)) {
9ee6e8bb 6913 return 1;
600b828c 6914 }
ad69471c
PB
6915 tmp = neon_load_reg(rm, 0);
6916 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 6917 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6918 if (pass == 1)
6919 tmp = tmp2;
6920 gen_neon_widen(cpu_V0, tmp, size, 1);
30d11a2a 6921 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
ad69471c 6922 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6923 }
6924 break;
600b828c 6925 case NEON_2RM_VCVT_F16_F32:
d614a513 6926 if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
fc2a9b37
PM
6927 q || (rm & 1)) {
6928 return 1;
6929 }
7d1b0095
PM
6930 tmp = tcg_temp_new_i32();
6931 tmp2 = tcg_temp_new_i32();
60011498 6932 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
2d981da7 6933 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
60011498 6934 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
2d981da7 6935 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
60011498
PB
6936 tcg_gen_shli_i32(tmp2, tmp2, 16);
6937 tcg_gen_or_i32(tmp2, tmp2, tmp);
6938 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
2d981da7 6939 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
60011498
PB
6940 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
6941 neon_store_reg(rd, 0, tmp2);
7d1b0095 6942 tmp2 = tcg_temp_new_i32();
2d981da7 6943 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
60011498
PB
6944 tcg_gen_shli_i32(tmp2, tmp2, 16);
6945 tcg_gen_or_i32(tmp2, tmp2, tmp);
6946 neon_store_reg(rd, 1, tmp2);
7d1b0095 6947 tcg_temp_free_i32(tmp);
60011498 6948 break;
600b828c 6949 case NEON_2RM_VCVT_F32_F16:
d614a513 6950 if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
fc2a9b37
PM
6951 q || (rd & 1)) {
6952 return 1;
6953 }
7d1b0095 6954 tmp3 = tcg_temp_new_i32();
60011498
PB
6955 tmp = neon_load_reg(rm, 0);
6956 tmp2 = neon_load_reg(rm, 1);
6957 tcg_gen_ext16u_i32(tmp3, tmp);
2d981da7 6958 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
60011498
PB
6959 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6960 tcg_gen_shri_i32(tmp3, tmp, 16);
2d981da7 6961 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
60011498 6962 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
7d1b0095 6963 tcg_temp_free_i32(tmp);
60011498 6964 tcg_gen_ext16u_i32(tmp3, tmp2);
2d981da7 6965 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
60011498
PB
6966 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6967 tcg_gen_shri_i32(tmp3, tmp2, 16);
2d981da7 6968 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
60011498 6969 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
7d1b0095
PM
6970 tcg_temp_free_i32(tmp2);
6971 tcg_temp_free_i32(tmp3);
60011498 6972 break;
9d935509 6973 case NEON_2RM_AESE: case NEON_2RM_AESMC:
d614a513 6974 if (!arm_dc_feature(s, ARM_FEATURE_V8_AES)
9d935509
AB
6975 || ((rm | rd) & 1)) {
6976 return 1;
6977 }
6978 tmp = tcg_const_i32(rd);
6979 tmp2 = tcg_const_i32(rm);
6980
6981 /* Bit 6 is the lowest opcode bit; it distinguishes between
6982 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6983 */
6984 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6985
6986 if (op == NEON_2RM_AESE) {
6987 gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
6988 } else {
6989 gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
6990 }
6991 tcg_temp_free_i32(tmp);
6992 tcg_temp_free_i32(tmp2);
6993 tcg_temp_free_i32(tmp3);
6994 break;
f1ecb913 6995 case NEON_2RM_SHA1H:
d614a513 6996 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)
f1ecb913
AB
6997 || ((rm | rd) & 1)) {
6998 return 1;
6999 }
7000 tmp = tcg_const_i32(rd);
7001 tmp2 = tcg_const_i32(rm);
7002
7003 gen_helper_crypto_sha1h(cpu_env, tmp, tmp2);
7004
7005 tcg_temp_free_i32(tmp);
7006 tcg_temp_free_i32(tmp2);
7007 break;
7008 case NEON_2RM_SHA1SU1:
7009 if ((rm | rd) & 1) {
7010 return 1;
7011 }
7012 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
7013 if (q) {
d614a513 7014 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256)) {
f1ecb913
AB
7015 return 1;
7016 }
d614a513 7017 } else if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
f1ecb913
AB
7018 return 1;
7019 }
7020 tmp = tcg_const_i32(rd);
7021 tmp2 = tcg_const_i32(rm);
7022 if (q) {
7023 gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2);
7024 } else {
7025 gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2);
7026 }
7027 tcg_temp_free_i32(tmp);
7028 tcg_temp_free_i32(tmp2);
7029 break;
9ee6e8bb
PB
7030 default:
7031 elementwise:
7032 for (pass = 0; pass < (q ? 4 : 2); pass++) {
600b828c 7033 if (neon_2rm_is_float_op(op)) {
4373f3ce
PB
7034 tcg_gen_ld_f32(cpu_F0s, cpu_env,
7035 neon_reg_offset(rm, pass));
39d5492a 7036 TCGV_UNUSED_I32(tmp);
9ee6e8bb 7037 } else {
dd8fbd78 7038 tmp = neon_load_reg(rm, pass);
9ee6e8bb
PB
7039 }
7040 switch (op) {
600b828c 7041 case NEON_2RM_VREV32:
9ee6e8bb 7042 switch (size) {
dd8fbd78
FN
7043 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7044 case 1: gen_swap_half(tmp); break;
600b828c 7045 default: abort();
9ee6e8bb
PB
7046 }
7047 break;
600b828c 7048 case NEON_2RM_VREV16:
dd8fbd78 7049 gen_rev16(tmp);
9ee6e8bb 7050 break;
600b828c 7051 case NEON_2RM_VCLS:
9ee6e8bb 7052 switch (size) {
dd8fbd78
FN
7053 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
7054 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
7055 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
600b828c 7056 default: abort();
9ee6e8bb
PB
7057 }
7058 break;
600b828c 7059 case NEON_2RM_VCLZ:
9ee6e8bb 7060 switch (size) {
dd8fbd78
FN
7061 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
7062 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
7063 case 2: gen_helper_clz(tmp, tmp); break;
600b828c 7064 default: abort();
9ee6e8bb
PB
7065 }
7066 break;
600b828c 7067 case NEON_2RM_VCNT:
dd8fbd78 7068 gen_helper_neon_cnt_u8(tmp, tmp);
9ee6e8bb 7069 break;
600b828c 7070 case NEON_2RM_VMVN:
dd8fbd78 7071 tcg_gen_not_i32(tmp, tmp);
9ee6e8bb 7072 break;
600b828c 7073 case NEON_2RM_VQABS:
9ee6e8bb 7074 switch (size) {
02da0b2d
PM
7075 case 0:
7076 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
7077 break;
7078 case 1:
7079 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
7080 break;
7081 case 2:
7082 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
7083 break;
600b828c 7084 default: abort();
9ee6e8bb
PB
7085 }
7086 break;
600b828c 7087 case NEON_2RM_VQNEG:
9ee6e8bb 7088 switch (size) {
02da0b2d
PM
7089 case 0:
7090 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
7091 break;
7092 case 1:
7093 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
7094 break;
7095 case 2:
7096 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
7097 break;
600b828c 7098 default: abort();
9ee6e8bb
PB
7099 }
7100 break;
600b828c 7101 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
dd8fbd78 7102 tmp2 = tcg_const_i32(0);
9ee6e8bb 7103 switch(size) {
dd8fbd78
FN
7104 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
7105 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
7106 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
600b828c 7107 default: abort();
9ee6e8bb 7108 }
39d5492a 7109 tcg_temp_free_i32(tmp2);
600b828c 7110 if (op == NEON_2RM_VCLE0) {
dd8fbd78 7111 tcg_gen_not_i32(tmp, tmp);
600b828c 7112 }
9ee6e8bb 7113 break;
600b828c 7114 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
dd8fbd78 7115 tmp2 = tcg_const_i32(0);
9ee6e8bb 7116 switch(size) {
dd8fbd78
FN
7117 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
7118 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
7119 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
600b828c 7120 default: abort();
9ee6e8bb 7121 }
39d5492a 7122 tcg_temp_free_i32(tmp2);
600b828c 7123 if (op == NEON_2RM_VCLT0) {
dd8fbd78 7124 tcg_gen_not_i32(tmp, tmp);
600b828c 7125 }
9ee6e8bb 7126 break;
600b828c 7127 case NEON_2RM_VCEQ0:
dd8fbd78 7128 tmp2 = tcg_const_i32(0);
9ee6e8bb 7129 switch(size) {
dd8fbd78
FN
7130 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
7131 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
7132 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
600b828c 7133 default: abort();
9ee6e8bb 7134 }
39d5492a 7135 tcg_temp_free_i32(tmp2);
9ee6e8bb 7136 break;
600b828c 7137 case NEON_2RM_VABS:
9ee6e8bb 7138 switch(size) {
dd8fbd78
FN
7139 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
7140 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
7141 case 2: tcg_gen_abs_i32(tmp, tmp); break;
600b828c 7142 default: abort();
9ee6e8bb
PB
7143 }
7144 break;
600b828c 7145 case NEON_2RM_VNEG:
dd8fbd78
FN
7146 tmp2 = tcg_const_i32(0);
7147 gen_neon_rsb(size, tmp, tmp2);
39d5492a 7148 tcg_temp_free_i32(tmp2);
9ee6e8bb 7149 break;
600b828c 7150 case NEON_2RM_VCGT0_F:
aa47cfdd
PM
7151 {
7152 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 7153 tmp2 = tcg_const_i32(0);
aa47cfdd 7154 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 7155 tcg_temp_free_i32(tmp2);
aa47cfdd 7156 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7157 break;
aa47cfdd 7158 }
600b828c 7159 case NEON_2RM_VCGE0_F:
aa47cfdd
PM
7160 {
7161 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 7162 tmp2 = tcg_const_i32(0);
aa47cfdd 7163 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 7164 tcg_temp_free_i32(tmp2);
aa47cfdd 7165 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7166 break;
aa47cfdd 7167 }
600b828c 7168 case NEON_2RM_VCEQ0_F:
aa47cfdd
PM
7169 {
7170 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 7171 tmp2 = tcg_const_i32(0);
aa47cfdd 7172 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 7173 tcg_temp_free_i32(tmp2);
aa47cfdd 7174 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7175 break;
aa47cfdd 7176 }
600b828c 7177 case NEON_2RM_VCLE0_F:
aa47cfdd
PM
7178 {
7179 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 7180 tmp2 = tcg_const_i32(0);
aa47cfdd 7181 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 7182 tcg_temp_free_i32(tmp2);
aa47cfdd 7183 tcg_temp_free_ptr(fpstatus);
0e326109 7184 break;
aa47cfdd 7185 }
600b828c 7186 case NEON_2RM_VCLT0_F:
aa47cfdd
PM
7187 {
7188 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 7189 tmp2 = tcg_const_i32(0);
aa47cfdd 7190 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 7191 tcg_temp_free_i32(tmp2);
aa47cfdd 7192 tcg_temp_free_ptr(fpstatus);
0e326109 7193 break;
aa47cfdd 7194 }
600b828c 7195 case NEON_2RM_VABS_F:
4373f3ce 7196 gen_vfp_abs(0);
9ee6e8bb 7197 break;
600b828c 7198 case NEON_2RM_VNEG_F:
4373f3ce 7199 gen_vfp_neg(0);
9ee6e8bb 7200 break;
600b828c 7201 case NEON_2RM_VSWP:
dd8fbd78
FN
7202 tmp2 = neon_load_reg(rd, pass);
7203 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 7204 break;
600b828c 7205 case NEON_2RM_VTRN:
dd8fbd78 7206 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 7207 switch (size) {
dd8fbd78
FN
7208 case 0: gen_neon_trn_u8(tmp, tmp2); break;
7209 case 1: gen_neon_trn_u16(tmp, tmp2); break;
600b828c 7210 default: abort();
9ee6e8bb 7211 }
dd8fbd78 7212 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 7213 break;
34f7b0a2
WN
7214 case NEON_2RM_VRINTN:
7215 case NEON_2RM_VRINTA:
7216 case NEON_2RM_VRINTM:
7217 case NEON_2RM_VRINTP:
7218 case NEON_2RM_VRINTZ:
7219 {
7220 TCGv_i32 tcg_rmode;
7221 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7222 int rmode;
7223
7224 if (op == NEON_2RM_VRINTZ) {
7225 rmode = FPROUNDING_ZERO;
7226 } else {
7227 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
7228 }
7229
7230 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7231 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7232 cpu_env);
7233 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
7234 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7235 cpu_env);
7236 tcg_temp_free_ptr(fpstatus);
7237 tcg_temp_free_i32(tcg_rmode);
7238 break;
7239 }
2ce70625
WN
7240 case NEON_2RM_VRINTX:
7241 {
7242 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7243 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
7244 tcg_temp_free_ptr(fpstatus);
7245 break;
7246 }
901ad525
WN
7247 case NEON_2RM_VCVTAU:
7248 case NEON_2RM_VCVTAS:
7249 case NEON_2RM_VCVTNU:
7250 case NEON_2RM_VCVTNS:
7251 case NEON_2RM_VCVTPU:
7252 case NEON_2RM_VCVTPS:
7253 case NEON_2RM_VCVTMU:
7254 case NEON_2RM_VCVTMS:
7255 {
7256 bool is_signed = !extract32(insn, 7, 1);
7257 TCGv_ptr fpst = get_fpstatus_ptr(1);
7258 TCGv_i32 tcg_rmode, tcg_shift;
7259 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
7260
7261 tcg_shift = tcg_const_i32(0);
7262 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7263 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7264 cpu_env);
7265
7266 if (is_signed) {
7267 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
7268 tcg_shift, fpst);
7269 } else {
7270 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
7271 tcg_shift, fpst);
7272 }
7273
7274 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7275 cpu_env);
7276 tcg_temp_free_i32(tcg_rmode);
7277 tcg_temp_free_i32(tcg_shift);
7278 tcg_temp_free_ptr(fpst);
7279 break;
7280 }
600b828c 7281 case NEON_2RM_VRECPE:
b6d4443a
AB
7282 {
7283 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7284 gen_helper_recpe_u32(tmp, tmp, fpstatus);
7285 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7286 break;
b6d4443a 7287 }
600b828c 7288 case NEON_2RM_VRSQRTE:
c2fb418e
AB
7289 {
7290 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7291 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
7292 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7293 break;
c2fb418e 7294 }
600b828c 7295 case NEON_2RM_VRECPE_F:
b6d4443a
AB
7296 {
7297 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7298 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
7299 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7300 break;
b6d4443a 7301 }
600b828c 7302 case NEON_2RM_VRSQRTE_F:
c2fb418e
AB
7303 {
7304 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7305 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
7306 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7307 break;
c2fb418e 7308 }
600b828c 7309 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
5500b06c 7310 gen_vfp_sito(0, 1);
9ee6e8bb 7311 break;
600b828c 7312 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
5500b06c 7313 gen_vfp_uito(0, 1);
9ee6e8bb 7314 break;
600b828c 7315 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
5500b06c 7316 gen_vfp_tosiz(0, 1);
9ee6e8bb 7317 break;
600b828c 7318 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
5500b06c 7319 gen_vfp_touiz(0, 1);
9ee6e8bb
PB
7320 break;
7321 default:
600b828c
PM
7322 /* Reserved op values were caught by the
7323 * neon_2rm_sizes[] check earlier.
7324 */
7325 abort();
9ee6e8bb 7326 }
600b828c 7327 if (neon_2rm_is_float_op(op)) {
4373f3ce
PB
7328 tcg_gen_st_f32(cpu_F0s, cpu_env,
7329 neon_reg_offset(rd, pass));
9ee6e8bb 7330 } else {
dd8fbd78 7331 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
7332 }
7333 }
7334 break;
7335 }
7336 } else if ((insn & (1 << 10)) == 0) {
7337 /* VTBL, VTBX. */
56907d77
PM
7338 int n = ((insn >> 8) & 3) + 1;
7339 if ((rn + n) > 32) {
7340 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
7341 * helper function running off the end of the register file.
7342 */
7343 return 1;
7344 }
7345 n <<= 3;
9ee6e8bb 7346 if (insn & (1 << 6)) {
8f8e3aa4 7347 tmp = neon_load_reg(rd, 0);
9ee6e8bb 7348 } else {
7d1b0095 7349 tmp = tcg_temp_new_i32();
8f8e3aa4 7350 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 7351 }
8f8e3aa4 7352 tmp2 = neon_load_reg(rm, 0);
b75263d6
JR
7353 tmp4 = tcg_const_i32(rn);
7354 tmp5 = tcg_const_i32(n);
9ef39277 7355 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
7d1b0095 7356 tcg_temp_free_i32(tmp);
9ee6e8bb 7357 if (insn & (1 << 6)) {
8f8e3aa4 7358 tmp = neon_load_reg(rd, 1);
9ee6e8bb 7359 } else {
7d1b0095 7360 tmp = tcg_temp_new_i32();
8f8e3aa4 7361 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 7362 }
8f8e3aa4 7363 tmp3 = neon_load_reg(rm, 1);
9ef39277 7364 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
25aeb69b
JR
7365 tcg_temp_free_i32(tmp5);
7366 tcg_temp_free_i32(tmp4);
8f8e3aa4 7367 neon_store_reg(rd, 0, tmp2);
3018f259 7368 neon_store_reg(rd, 1, tmp3);
7d1b0095 7369 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
7370 } else if ((insn & 0x380) == 0) {
7371 /* VDUP */
133da6aa
JR
7372 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
7373 return 1;
7374 }
9ee6e8bb 7375 if (insn & (1 << 19)) {
dd8fbd78 7376 tmp = neon_load_reg(rm, 1);
9ee6e8bb 7377 } else {
dd8fbd78 7378 tmp = neon_load_reg(rm, 0);
9ee6e8bb
PB
7379 }
7380 if (insn & (1 << 16)) {
dd8fbd78 7381 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
9ee6e8bb
PB
7382 } else if (insn & (1 << 17)) {
7383 if ((insn >> 18) & 1)
dd8fbd78 7384 gen_neon_dup_high16(tmp);
9ee6e8bb 7385 else
dd8fbd78 7386 gen_neon_dup_low16(tmp);
9ee6e8bb
PB
7387 }
7388 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7d1b0095 7389 tmp2 = tcg_temp_new_i32();
dd8fbd78
FN
7390 tcg_gen_mov_i32(tmp2, tmp);
7391 neon_store_reg(rd, pass, tmp2);
9ee6e8bb 7392 }
7d1b0095 7393 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
7394 } else {
7395 return 1;
7396 }
7397 }
7398 }
7399 return 0;
7400}
7401
7dcc1f89 7402static int disas_coproc_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 7403{
4b6a83fb
PM
7404 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
7405 const ARMCPRegInfo *ri;
9ee6e8bb
PB
7406
7407 cpnum = (insn >> 8) & 0xf;
c0f4af17
PM
7408
7409 /* First check for coprocessor space used for XScale/iwMMXt insns */
d614a513 7410 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
c0f4af17
PM
7411 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
7412 return 1;
7413 }
d614a513 7414 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
7dcc1f89 7415 return disas_iwmmxt_insn(s, insn);
d614a513 7416 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
7dcc1f89 7417 return disas_dsp_insn(s, insn);
c0f4af17
PM
7418 }
7419 return 1;
4b6a83fb
PM
7420 }
7421
7422 /* Otherwise treat as a generic register access */
7423 is64 = (insn & (1 << 25)) == 0;
7424 if (!is64 && ((insn & (1 << 4)) == 0)) {
7425 /* cdp */
7426 return 1;
7427 }
7428
7429 crm = insn & 0xf;
7430 if (is64) {
7431 crn = 0;
7432 opc1 = (insn >> 4) & 0xf;
7433 opc2 = 0;
7434 rt2 = (insn >> 16) & 0xf;
7435 } else {
7436 crn = (insn >> 16) & 0xf;
7437 opc1 = (insn >> 21) & 7;
7438 opc2 = (insn >> 5) & 7;
7439 rt2 = 0;
7440 }
7441 isread = (insn >> 20) & 1;
7442 rt = (insn >> 12) & 0xf;
7443
60322b39 7444 ri = get_arm_cp_reginfo(s->cp_regs,
51a79b03 7445 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4b6a83fb
PM
7446 if (ri) {
7447 /* Check access permissions */
dcbff19b 7448 if (!cp_access_ok(s->current_el, ri, isread)) {
4b6a83fb
PM
7449 return 1;
7450 }
7451
c0f4af17 7452 if (ri->accessfn ||
d614a513 7453 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
f59df3f2
PM
7454 /* Emit code to perform further access permissions checks at
7455 * runtime; this may result in an exception.
c0f4af17
PM
7456 * Note that on XScale all cp0..c13 registers do an access check
7457 * call in order to handle c15_cpar.
f59df3f2
PM
7458 */
7459 TCGv_ptr tmpptr;
3f208fd7 7460 TCGv_i32 tcg_syn, tcg_isread;
8bcbf37c
PM
7461 uint32_t syndrome;
7462
7463 /* Note that since we are an implementation which takes an
7464 * exception on a trapped conditional instruction only if the
7465 * instruction passes its condition code check, we can take
7466 * advantage of the clause in the ARM ARM that allows us to set
7467 * the COND field in the instruction to 0xE in all cases.
7468 * We could fish the actual condition out of the insn (ARM)
7469 * or the condexec bits (Thumb) but it isn't necessary.
7470 */
7471 switch (cpnum) {
7472 case 14:
7473 if (is64) {
7474 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7475 isread, false);
8bcbf37c
PM
7476 } else {
7477 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7478 rt, isread, false);
8bcbf37c
PM
7479 }
7480 break;
7481 case 15:
7482 if (is64) {
7483 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7484 isread, false);
8bcbf37c
PM
7485 } else {
7486 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7487 rt, isread, false);
8bcbf37c
PM
7488 }
7489 break;
7490 default:
7491 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7492 * so this can only happen if this is an ARMv7 or earlier CPU,
7493 * in which case the syndrome information won't actually be
7494 * guest visible.
7495 */
d614a513 7496 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8bcbf37c
PM
7497 syndrome = syn_uncategorized();
7498 break;
7499 }
7500
43bfa4a1 7501 gen_set_condexec(s);
3977ee5d 7502 gen_set_pc_im(s, s->pc - 4);
f59df3f2 7503 tmpptr = tcg_const_ptr(ri);
8bcbf37c 7504 tcg_syn = tcg_const_i32(syndrome);
3f208fd7
PM
7505 tcg_isread = tcg_const_i32(isread);
7506 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
7507 tcg_isread);
f59df3f2 7508 tcg_temp_free_ptr(tmpptr);
8bcbf37c 7509 tcg_temp_free_i32(tcg_syn);
3f208fd7 7510 tcg_temp_free_i32(tcg_isread);
f59df3f2
PM
7511 }
7512
4b6a83fb
PM
7513 /* Handle special cases first */
7514 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7515 case ARM_CP_NOP:
7516 return 0;
7517 case ARM_CP_WFI:
7518 if (isread) {
7519 return 1;
7520 }
eaed129d 7521 gen_set_pc_im(s, s->pc);
4b6a83fb 7522 s->is_jmp = DISAS_WFI;
2bee5105 7523 return 0;
4b6a83fb
PM
7524 default:
7525 break;
7526 }
7527
bd79255d 7528 if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
7529 gen_io_start();
7530 }
7531
4b6a83fb
PM
7532 if (isread) {
7533 /* Read */
7534 if (is64) {
7535 TCGv_i64 tmp64;
7536 TCGv_i32 tmp;
7537 if (ri->type & ARM_CP_CONST) {
7538 tmp64 = tcg_const_i64(ri->resetvalue);
7539 } else if (ri->readfn) {
7540 TCGv_ptr tmpptr;
4b6a83fb
PM
7541 tmp64 = tcg_temp_new_i64();
7542 tmpptr = tcg_const_ptr(ri);
7543 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7544 tcg_temp_free_ptr(tmpptr);
7545 } else {
7546 tmp64 = tcg_temp_new_i64();
7547 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7548 }
7549 tmp = tcg_temp_new_i32();
ecc7b3aa 7550 tcg_gen_extrl_i64_i32(tmp, tmp64);
4b6a83fb
PM
7551 store_reg(s, rt, tmp);
7552 tcg_gen_shri_i64(tmp64, tmp64, 32);
ed336850 7553 tmp = tcg_temp_new_i32();
ecc7b3aa 7554 tcg_gen_extrl_i64_i32(tmp, tmp64);
ed336850 7555 tcg_temp_free_i64(tmp64);
4b6a83fb
PM
7556 store_reg(s, rt2, tmp);
7557 } else {
39d5492a 7558 TCGv_i32 tmp;
4b6a83fb
PM
7559 if (ri->type & ARM_CP_CONST) {
7560 tmp = tcg_const_i32(ri->resetvalue);
7561 } else if (ri->readfn) {
7562 TCGv_ptr tmpptr;
4b6a83fb
PM
7563 tmp = tcg_temp_new_i32();
7564 tmpptr = tcg_const_ptr(ri);
7565 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
7566 tcg_temp_free_ptr(tmpptr);
7567 } else {
7568 tmp = load_cpu_offset(ri->fieldoffset);
7569 }
7570 if (rt == 15) {
7571 /* Destination register of r15 for 32 bit loads sets
7572 * the condition codes from the high 4 bits of the value
7573 */
7574 gen_set_nzcv(tmp);
7575 tcg_temp_free_i32(tmp);
7576 } else {
7577 store_reg(s, rt, tmp);
7578 }
7579 }
7580 } else {
7581 /* Write */
7582 if (ri->type & ARM_CP_CONST) {
7583 /* If not forbidden by access permissions, treat as WI */
7584 return 0;
7585 }
7586
7587 if (is64) {
39d5492a 7588 TCGv_i32 tmplo, tmphi;
4b6a83fb
PM
7589 TCGv_i64 tmp64 = tcg_temp_new_i64();
7590 tmplo = load_reg(s, rt);
7591 tmphi = load_reg(s, rt2);
7592 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
7593 tcg_temp_free_i32(tmplo);
7594 tcg_temp_free_i32(tmphi);
7595 if (ri->writefn) {
7596 TCGv_ptr tmpptr = tcg_const_ptr(ri);
4b6a83fb
PM
7597 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
7598 tcg_temp_free_ptr(tmpptr);
7599 } else {
7600 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
7601 }
7602 tcg_temp_free_i64(tmp64);
7603 } else {
7604 if (ri->writefn) {
39d5492a 7605 TCGv_i32 tmp;
4b6a83fb 7606 TCGv_ptr tmpptr;
4b6a83fb
PM
7607 tmp = load_reg(s, rt);
7608 tmpptr = tcg_const_ptr(ri);
7609 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
7610 tcg_temp_free_ptr(tmpptr);
7611 tcg_temp_free_i32(tmp);
7612 } else {
39d5492a 7613 TCGv_i32 tmp = load_reg(s, rt);
4b6a83fb
PM
7614 store_cpu_offset(tmp, ri->fieldoffset);
7615 }
7616 }
2452731c
PM
7617 }
7618
bd79255d 7619 if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
7620 /* I/O operations must end the TB here (whether read or write) */
7621 gen_io_end();
7622 gen_lookup_tb(s);
7623 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4b6a83fb
PM
7624 /* We default to ending the TB on a coprocessor register write,
7625 * but allow this to be suppressed by the register definition
7626 * (usually only necessary to work around guest bugs).
7627 */
2452731c 7628 gen_lookup_tb(s);
4b6a83fb 7629 }
2452731c 7630
4b6a83fb
PM
7631 return 0;
7632 }
7633
626187d8
PM
7634 /* Unknown register; this might be a guest error or a QEMU
7635 * unimplemented feature.
7636 */
7637 if (is64) {
7638 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
7639 "64 bit system register cp:%d opc1: %d crm:%d "
7640 "(%s)\n",
7641 isread ? "read" : "write", cpnum, opc1, crm,
7642 s->ns ? "non-secure" : "secure");
626187d8
PM
7643 } else {
7644 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
7645 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
7646 "(%s)\n",
7647 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
7648 s->ns ? "non-secure" : "secure");
626187d8
PM
7649 }
7650
4a9a539f 7651 return 1;
9ee6e8bb
PB
7652}
7653
5e3f878a
PB
7654
7655/* Store a 64-bit value to a register pair. Clobbers val. */
a7812ae4 7656static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5e3f878a 7657{
39d5492a 7658 TCGv_i32 tmp;
7d1b0095 7659 tmp = tcg_temp_new_i32();
ecc7b3aa 7660 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a 7661 store_reg(s, rlow, tmp);
7d1b0095 7662 tmp = tcg_temp_new_i32();
5e3f878a 7663 tcg_gen_shri_i64(val, val, 32);
ecc7b3aa 7664 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a
PB
7665 store_reg(s, rhigh, tmp);
7666}
7667
7668/* load a 32-bit value from a register and perform a 64-bit accumulate. */
a7812ae4 7669static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5e3f878a 7670{
a7812ae4 7671 TCGv_i64 tmp;
39d5492a 7672 TCGv_i32 tmp2;
5e3f878a 7673
36aa55dc 7674 /* Load value and extend to 64 bits. */
a7812ae4 7675 tmp = tcg_temp_new_i64();
5e3f878a
PB
7676 tmp2 = load_reg(s, rlow);
7677 tcg_gen_extu_i32_i64(tmp, tmp2);
7d1b0095 7678 tcg_temp_free_i32(tmp2);
5e3f878a 7679 tcg_gen_add_i64(val, val, tmp);
b75263d6 7680 tcg_temp_free_i64(tmp);
5e3f878a
PB
7681}
7682
7683/* load and add a 64-bit value from a register pair. */
a7812ae4 7684static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5e3f878a 7685{
a7812ae4 7686 TCGv_i64 tmp;
39d5492a
PM
7687 TCGv_i32 tmpl;
7688 TCGv_i32 tmph;
5e3f878a
PB
7689
7690 /* Load 64-bit value rd:rn. */
36aa55dc
PB
7691 tmpl = load_reg(s, rlow);
7692 tmph = load_reg(s, rhigh);
a7812ae4 7693 tmp = tcg_temp_new_i64();
36aa55dc 7694 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7d1b0095
PM
7695 tcg_temp_free_i32(tmpl);
7696 tcg_temp_free_i32(tmph);
5e3f878a 7697 tcg_gen_add_i64(val, val, tmp);
b75263d6 7698 tcg_temp_free_i64(tmp);
5e3f878a
PB
7699}
7700
c9f10124 7701/* Set N and Z flags from hi|lo. */
39d5492a 7702static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
5e3f878a 7703{
c9f10124
RH
7704 tcg_gen_mov_i32(cpu_NF, hi);
7705 tcg_gen_or_i32(cpu_ZF, lo, hi);
5e3f878a
PB
7706}
7707
426f5abc
PB
7708/* Load/Store exclusive instructions are implemented by remembering
7709 the value/address loaded, and seeing if these are the same
354161b3 7710 when the store is performed. This should be sufficient to implement
426f5abc 7711 the architecturally mandated semantics, and avoids having to monitor
354161b3
EC
7712 regular stores. The compare vs the remembered value is done during
7713 the cmpxchg operation, but we must compare the addresses manually. */
426f5abc 7714static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
39d5492a 7715 TCGv_i32 addr, int size)
426f5abc 7716{
94ee24e7 7717 TCGv_i32 tmp = tcg_temp_new_i32();
354161b3 7718 TCGMemOp opc = size | MO_ALIGN | s->be_data;
426f5abc 7719
50225ad0
PM
7720 s->is_ldex = true;
7721
426f5abc 7722 if (size == 3) {
39d5492a 7723 TCGv_i32 tmp2 = tcg_temp_new_i32();
354161b3 7724 TCGv_i64 t64 = tcg_temp_new_i64();
03d05e2d 7725
354161b3
EC
7726 gen_aa32_ld_i64(s, t64, addr, get_mem_index(s), opc);
7727 tcg_gen_mov_i64(cpu_exclusive_val, t64);
7728 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
7729 tcg_temp_free_i64(t64);
7730
7731 store_reg(s, rt2, tmp2);
03d05e2d 7732 } else {
354161b3 7733 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
03d05e2d 7734 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
426f5abc 7735 }
03d05e2d
PM
7736
7737 store_reg(s, rt, tmp);
7738 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
426f5abc
PB
7739}
7740
7741static void gen_clrex(DisasContext *s)
7742{
03d05e2d 7743 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc
PB
7744}
7745
426f5abc 7746static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
39d5492a 7747 TCGv_i32 addr, int size)
426f5abc 7748{
354161b3
EC
7749 TCGv_i32 t0, t1, t2;
7750 TCGv_i64 extaddr;
7751 TCGv taddr;
42a268c2
RH
7752 TCGLabel *done_label;
7753 TCGLabel *fail_label;
354161b3 7754 TCGMemOp opc = size | MO_ALIGN | s->be_data;
426f5abc
PB
7755
7756 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7757 [addr] = {Rt};
7758 {Rd} = 0;
7759 } else {
7760 {Rd} = 1;
7761 } */
7762 fail_label = gen_new_label();
7763 done_label = gen_new_label();
03d05e2d
PM
7764 extaddr = tcg_temp_new_i64();
7765 tcg_gen_extu_i32_i64(extaddr, addr);
7766 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7767 tcg_temp_free_i64(extaddr);
7768
354161b3
EC
7769 taddr = gen_aa32_addr(s, addr, opc);
7770 t0 = tcg_temp_new_i32();
7771 t1 = load_reg(s, rt);
426f5abc 7772 if (size == 3) {
354161b3
EC
7773 TCGv_i64 o64 = tcg_temp_new_i64();
7774 TCGv_i64 n64 = tcg_temp_new_i64();
03d05e2d 7775
354161b3
EC
7776 t2 = load_reg(s, rt2);
7777 tcg_gen_concat_i32_i64(n64, t1, t2);
7778 tcg_temp_free_i32(t2);
7779 gen_aa32_frob64(s, n64);
03d05e2d 7780
354161b3
EC
7781 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
7782 get_mem_index(s), opc);
7783 tcg_temp_free_i64(n64);
7784
7785 gen_aa32_frob64(s, o64);
7786 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
7787 tcg_gen_extrl_i64_i32(t0, o64);
7788
7789 tcg_temp_free_i64(o64);
7790 } else {
7791 t2 = tcg_temp_new_i32();
7792 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
7793 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
7794 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
7795 tcg_temp_free_i32(t2);
426f5abc 7796 }
354161b3
EC
7797 tcg_temp_free_i32(t1);
7798 tcg_temp_free(taddr);
7799 tcg_gen_mov_i32(cpu_R[rd], t0);
7800 tcg_temp_free_i32(t0);
426f5abc 7801 tcg_gen_br(done_label);
354161b3 7802
426f5abc
PB
7803 gen_set_label(fail_label);
7804 tcg_gen_movi_i32(cpu_R[rd], 1);
7805 gen_set_label(done_label);
03d05e2d 7806 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc 7807}
426f5abc 7808
81465888
PM
7809/* gen_srs:
7810 * @env: CPUARMState
7811 * @s: DisasContext
7812 * @mode: mode field from insn (which stack to store to)
7813 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7814 * @writeback: true if writeback bit set
7815 *
7816 * Generate code for the SRS (Store Return State) insn.
7817 */
7818static void gen_srs(DisasContext *s,
7819 uint32_t mode, uint32_t amode, bool writeback)
7820{
7821 int32_t offset;
cbc0326b
PM
7822 TCGv_i32 addr, tmp;
7823 bool undef = false;
7824
7825 /* SRS is:
7826 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
ba63cf47 7827 * and specified mode is monitor mode
cbc0326b
PM
7828 * - UNDEFINED in Hyp mode
7829 * - UNPREDICTABLE in User or System mode
7830 * - UNPREDICTABLE if the specified mode is:
7831 * -- not implemented
7832 * -- not a valid mode number
7833 * -- a mode that's at a higher exception level
7834 * -- Monitor, if we are Non-secure
f01377f5 7835 * For the UNPREDICTABLE cases we choose to UNDEF.
cbc0326b 7836 */
ba63cf47 7837 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
cbc0326b
PM
7838 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
7839 return;
7840 }
7841
7842 if (s->current_el == 0 || s->current_el == 2) {
7843 undef = true;
7844 }
7845
7846 switch (mode) {
7847 case ARM_CPU_MODE_USR:
7848 case ARM_CPU_MODE_FIQ:
7849 case ARM_CPU_MODE_IRQ:
7850 case ARM_CPU_MODE_SVC:
7851 case ARM_CPU_MODE_ABT:
7852 case ARM_CPU_MODE_UND:
7853 case ARM_CPU_MODE_SYS:
7854 break;
7855 case ARM_CPU_MODE_HYP:
7856 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
7857 undef = true;
7858 }
7859 break;
7860 case ARM_CPU_MODE_MON:
7861 /* No need to check specifically for "are we non-secure" because
7862 * we've already made EL0 UNDEF and handled the trap for S-EL1;
7863 * so if this isn't EL3 then we must be non-secure.
7864 */
7865 if (s->current_el != 3) {
7866 undef = true;
7867 }
7868 break;
7869 default:
7870 undef = true;
7871 }
7872
7873 if (undef) {
7874 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
7875 default_exception_el(s));
7876 return;
7877 }
7878
7879 addr = tcg_temp_new_i32();
7880 tmp = tcg_const_i32(mode);
f01377f5
PM
7881 /* get_r13_banked() will raise an exception if called from System mode */
7882 gen_set_condexec(s);
7883 gen_set_pc_im(s, s->pc - 4);
81465888
PM
7884 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7885 tcg_temp_free_i32(tmp);
7886 switch (amode) {
7887 case 0: /* DA */
7888 offset = -4;
7889 break;
7890 case 1: /* IA */
7891 offset = 0;
7892 break;
7893 case 2: /* DB */
7894 offset = -8;
7895 break;
7896 case 3: /* IB */
7897 offset = 4;
7898 break;
7899 default:
7900 abort();
7901 }
7902 tcg_gen_addi_i32(addr, addr, offset);
7903 tmp = load_reg(s, 14);
12dcc321 7904 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 7905 tcg_temp_free_i32(tmp);
81465888
PM
7906 tmp = load_cpu_field(spsr);
7907 tcg_gen_addi_i32(addr, addr, 4);
12dcc321 7908 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 7909 tcg_temp_free_i32(tmp);
81465888
PM
7910 if (writeback) {
7911 switch (amode) {
7912 case 0:
7913 offset = -8;
7914 break;
7915 case 1:
7916 offset = 4;
7917 break;
7918 case 2:
7919 offset = -4;
7920 break;
7921 case 3:
7922 offset = 0;
7923 break;
7924 default:
7925 abort();
7926 }
7927 tcg_gen_addi_i32(addr, addr, offset);
7928 tmp = tcg_const_i32(mode);
7929 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7930 tcg_temp_free_i32(tmp);
7931 }
7932 tcg_temp_free_i32(addr);
f01377f5 7933 s->is_jmp = DISAS_UPDATE;
81465888
PM
7934}
7935
f4df2210 7936static void disas_arm_insn(DisasContext *s, unsigned int insn)
9ee6e8bb 7937{
f4df2210 7938 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
39d5492a
PM
7939 TCGv_i32 tmp;
7940 TCGv_i32 tmp2;
7941 TCGv_i32 tmp3;
7942 TCGv_i32 addr;
a7812ae4 7943 TCGv_i64 tmp64;
9ee6e8bb 7944
9ee6e8bb 7945 /* M variants do not implement ARM mode. */
b53d8923 7946 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 7947 goto illegal_op;
b53d8923 7948 }
9ee6e8bb
PB
7949 cond = insn >> 28;
7950 if (cond == 0xf){
be5e7a76
DES
7951 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
7952 * choose to UNDEF. In ARMv5 and above the space is used
7953 * for miscellaneous unconditional instructions.
7954 */
7955 ARCH(5);
7956
9ee6e8bb
PB
7957 /* Unconditional instructions. */
7958 if (((insn >> 25) & 7) == 1) {
7959 /* NEON Data processing. */
d614a513 7960 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 7961 goto illegal_op;
d614a513 7962 }
9ee6e8bb 7963
7dcc1f89 7964 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 7965 goto illegal_op;
7dcc1f89 7966 }
9ee6e8bb
PB
7967 return;
7968 }
7969 if ((insn & 0x0f100000) == 0x04000000) {
7970 /* NEON load/store. */
d614a513 7971 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 7972 goto illegal_op;
d614a513 7973 }
9ee6e8bb 7974
7dcc1f89 7975 if (disas_neon_ls_insn(s, insn)) {
9ee6e8bb 7976 goto illegal_op;
7dcc1f89 7977 }
9ee6e8bb
PB
7978 return;
7979 }
6a57f3eb
WN
7980 if ((insn & 0x0f000e10) == 0x0e000a00) {
7981 /* VFP. */
7dcc1f89 7982 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
7983 goto illegal_op;
7984 }
7985 return;
7986 }
3d185e5d
PM
7987 if (((insn & 0x0f30f000) == 0x0510f000) ||
7988 ((insn & 0x0f30f010) == 0x0710f000)) {
7989 if ((insn & (1 << 22)) == 0) {
7990 /* PLDW; v7MP */
d614a513 7991 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
7992 goto illegal_op;
7993 }
7994 }
7995 /* Otherwise PLD; v5TE+ */
be5e7a76 7996 ARCH(5TE);
3d185e5d
PM
7997 return;
7998 }
7999 if (((insn & 0x0f70f000) == 0x0450f000) ||
8000 ((insn & 0x0f70f010) == 0x0650f000)) {
8001 ARCH(7);
8002 return; /* PLI; V7 */
8003 }
8004 if (((insn & 0x0f700000) == 0x04100000) ||
8005 ((insn & 0x0f700010) == 0x06100000)) {
d614a513 8006 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
8007 goto illegal_op;
8008 }
8009 return; /* v7MP: Unallocated memory hint: must NOP */
8010 }
8011
8012 if ((insn & 0x0ffffdff) == 0x01010000) {
9ee6e8bb
PB
8013 ARCH(6);
8014 /* setend */
9886ecdf
PB
8015 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
8016 gen_helper_setend(cpu_env);
8017 s->is_jmp = DISAS_UPDATE;
9ee6e8bb
PB
8018 }
8019 return;
8020 } else if ((insn & 0x0fffff00) == 0x057ff000) {
8021 switch ((insn >> 4) & 0xf) {
8022 case 1: /* clrex */
8023 ARCH(6K);
426f5abc 8024 gen_clrex(s);
9ee6e8bb
PB
8025 return;
8026 case 4: /* dsb */
8027 case 5: /* dmb */
9ee6e8bb 8028 ARCH(7);
61e4c432 8029 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9ee6e8bb 8030 return;
6df99dec
SS
8031 case 6: /* isb */
8032 /* We need to break the TB after this insn to execute
8033 * self-modifying code correctly and also to take
8034 * any pending interrupts immediately.
8035 */
8036 gen_lookup_tb(s);
8037 return;
9ee6e8bb
PB
8038 default:
8039 goto illegal_op;
8040 }
8041 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
8042 /* srs */
81465888
PM
8043 ARCH(6);
8044 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
3b328448 8045 return;
ea825eee 8046 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
9ee6e8bb 8047 /* rfe */
c67b6b71 8048 int32_t offset;
9ee6e8bb
PB
8049 if (IS_USER(s))
8050 goto illegal_op;
8051 ARCH(6);
8052 rn = (insn >> 16) & 0xf;
b0109805 8053 addr = load_reg(s, rn);
9ee6e8bb
PB
8054 i = (insn >> 23) & 3;
8055 switch (i) {
b0109805 8056 case 0: offset = -4; break; /* DA */
c67b6b71
FN
8057 case 1: offset = 0; break; /* IA */
8058 case 2: offset = -8; break; /* DB */
b0109805 8059 case 3: offset = 4; break; /* IB */
9ee6e8bb
PB
8060 default: abort();
8061 }
8062 if (offset)
b0109805
PB
8063 tcg_gen_addi_i32(addr, addr, offset);
8064 /* Load PC into tmp and CPSR into tmp2. */
5a839c0d 8065 tmp = tcg_temp_new_i32();
12dcc321 8066 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 8067 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 8068 tmp2 = tcg_temp_new_i32();
12dcc321 8069 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
8070 if (insn & (1 << 21)) {
8071 /* Base writeback. */
8072 switch (i) {
b0109805 8073 case 0: offset = -8; break;
c67b6b71
FN
8074 case 1: offset = 4; break;
8075 case 2: offset = -4; break;
b0109805 8076 case 3: offset = 0; break;
9ee6e8bb
PB
8077 default: abort();
8078 }
8079 if (offset)
b0109805
PB
8080 tcg_gen_addi_i32(addr, addr, offset);
8081 store_reg(s, rn, addr);
8082 } else {
7d1b0095 8083 tcg_temp_free_i32(addr);
9ee6e8bb 8084 }
b0109805 8085 gen_rfe(s, tmp, tmp2);
c67b6b71 8086 return;
9ee6e8bb
PB
8087 } else if ((insn & 0x0e000000) == 0x0a000000) {
8088 /* branch link and change to thumb (blx <offset>) */
8089 int32_t offset;
8090
8091 val = (uint32_t)s->pc;
7d1b0095 8092 tmp = tcg_temp_new_i32();
d9ba4830
PB
8093 tcg_gen_movi_i32(tmp, val);
8094 store_reg(s, 14, tmp);
9ee6e8bb
PB
8095 /* Sign-extend the 24-bit offset */
8096 offset = (((int32_t)insn) << 8) >> 8;
8097 /* offset * 4 + bit24 * 2 + (thumb bit) */
8098 val += (offset << 2) | ((insn >> 23) & 2) | 1;
8099 /* pipeline offset */
8100 val += 4;
be5e7a76 8101 /* protected by ARCH(5); above, near the start of uncond block */
d9ba4830 8102 gen_bx_im(s, val);
9ee6e8bb
PB
8103 return;
8104 } else if ((insn & 0x0e000f00) == 0x0c000100) {
d614a513 8105 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9ee6e8bb 8106 /* iWMMXt register transfer. */
c0f4af17 8107 if (extract32(s->c15_cpar, 1, 1)) {
7dcc1f89 8108 if (!disas_iwmmxt_insn(s, insn)) {
9ee6e8bb 8109 return;
c0f4af17
PM
8110 }
8111 }
9ee6e8bb
PB
8112 }
8113 } else if ((insn & 0x0fe00000) == 0x0c400000) {
8114 /* Coprocessor double register transfer. */
be5e7a76 8115 ARCH(5TE);
9ee6e8bb
PB
8116 } else if ((insn & 0x0f000010) == 0x0e000010) {
8117 /* Additional coprocessor register transfer. */
7997d92f 8118 } else if ((insn & 0x0ff10020) == 0x01000000) {
9ee6e8bb
PB
8119 uint32_t mask;
8120 uint32_t val;
8121 /* cps (privileged) */
8122 if (IS_USER(s))
8123 return;
8124 mask = val = 0;
8125 if (insn & (1 << 19)) {
8126 if (insn & (1 << 8))
8127 mask |= CPSR_A;
8128 if (insn & (1 << 7))
8129 mask |= CPSR_I;
8130 if (insn & (1 << 6))
8131 mask |= CPSR_F;
8132 if (insn & (1 << 18))
8133 val |= mask;
8134 }
7997d92f 8135 if (insn & (1 << 17)) {
9ee6e8bb
PB
8136 mask |= CPSR_M;
8137 val |= (insn & 0x1f);
8138 }
8139 if (mask) {
2fbac54b 8140 gen_set_psr_im(s, mask, 0, val);
9ee6e8bb
PB
8141 }
8142 return;
8143 }
8144 goto illegal_op;
8145 }
8146 if (cond != 0xe) {
8147 /* if not always execute, we generate a conditional jump to
8148 next instruction */
8149 s->condlabel = gen_new_label();
39fb730a 8150 arm_gen_test_cc(cond ^ 1, s->condlabel);
9ee6e8bb
PB
8151 s->condjmp = 1;
8152 }
8153 if ((insn & 0x0f900000) == 0x03000000) {
8154 if ((insn & (1 << 21)) == 0) {
8155 ARCH(6T2);
8156 rd = (insn >> 12) & 0xf;
8157 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
8158 if ((insn & (1 << 22)) == 0) {
8159 /* MOVW */
7d1b0095 8160 tmp = tcg_temp_new_i32();
5e3f878a 8161 tcg_gen_movi_i32(tmp, val);
9ee6e8bb
PB
8162 } else {
8163 /* MOVT */
5e3f878a 8164 tmp = load_reg(s, rd);
86831435 8165 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 8166 tcg_gen_ori_i32(tmp, tmp, val << 16);
9ee6e8bb 8167 }
5e3f878a 8168 store_reg(s, rd, tmp);
9ee6e8bb
PB
8169 } else {
8170 if (((insn >> 12) & 0xf) != 0xf)
8171 goto illegal_op;
8172 if (((insn >> 16) & 0xf) == 0) {
8173 gen_nop_hint(s, insn & 0xff);
8174 } else {
8175 /* CPSR = immediate */
8176 val = insn & 0xff;
8177 shift = ((insn >> 8) & 0xf) * 2;
8178 if (shift)
8179 val = (val >> shift) | (val << (32 - shift));
9ee6e8bb 8180 i = ((insn & (1 << 22)) != 0);
7dcc1f89
PM
8181 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
8182 i, val)) {
9ee6e8bb 8183 goto illegal_op;
7dcc1f89 8184 }
9ee6e8bb
PB
8185 }
8186 }
8187 } else if ((insn & 0x0f900000) == 0x01000000
8188 && (insn & 0x00000090) != 0x00000090) {
8189 /* miscellaneous instructions */
8190 op1 = (insn >> 21) & 3;
8191 sh = (insn >> 4) & 0xf;
8192 rm = insn & 0xf;
8193 switch (sh) {
8bfd0550
PM
8194 case 0x0: /* MSR, MRS */
8195 if (insn & (1 << 9)) {
8196 /* MSR (banked) and MRS (banked) */
8197 int sysm = extract32(insn, 16, 4) |
8198 (extract32(insn, 8, 1) << 4);
8199 int r = extract32(insn, 22, 1);
8200
8201 if (op1 & 1) {
8202 /* MSR (banked) */
8203 gen_msr_banked(s, r, sysm, rm);
8204 } else {
8205 /* MRS (banked) */
8206 int rd = extract32(insn, 12, 4);
8207
8208 gen_mrs_banked(s, r, sysm, rd);
8209 }
8210 break;
8211 }
8212
8213 /* MSR, MRS (for PSRs) */
9ee6e8bb
PB
8214 if (op1 & 1) {
8215 /* PSR = reg */
2fbac54b 8216 tmp = load_reg(s, rm);
9ee6e8bb 8217 i = ((op1 & 2) != 0);
7dcc1f89 8218 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
9ee6e8bb
PB
8219 goto illegal_op;
8220 } else {
8221 /* reg = PSR */
8222 rd = (insn >> 12) & 0xf;
8223 if (op1 & 2) {
8224 if (IS_USER(s))
8225 goto illegal_op;
d9ba4830 8226 tmp = load_cpu_field(spsr);
9ee6e8bb 8227 } else {
7d1b0095 8228 tmp = tcg_temp_new_i32();
9ef39277 8229 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 8230 }
d9ba4830 8231 store_reg(s, rd, tmp);
9ee6e8bb
PB
8232 }
8233 break;
8234 case 0x1:
8235 if (op1 == 1) {
8236 /* branch/exchange thumb (bx). */
be5e7a76 8237 ARCH(4T);
d9ba4830
PB
8238 tmp = load_reg(s, rm);
8239 gen_bx(s, tmp);
9ee6e8bb
PB
8240 } else if (op1 == 3) {
8241 /* clz */
be5e7a76 8242 ARCH(5);
9ee6e8bb 8243 rd = (insn >> 12) & 0xf;
1497c961
PB
8244 tmp = load_reg(s, rm);
8245 gen_helper_clz(tmp, tmp);
8246 store_reg(s, rd, tmp);
9ee6e8bb
PB
8247 } else {
8248 goto illegal_op;
8249 }
8250 break;
8251 case 0x2:
8252 if (op1 == 1) {
8253 ARCH(5J); /* bxj */
8254 /* Trivial implementation equivalent to bx. */
d9ba4830
PB
8255 tmp = load_reg(s, rm);
8256 gen_bx(s, tmp);
9ee6e8bb
PB
8257 } else {
8258 goto illegal_op;
8259 }
8260 break;
8261 case 0x3:
8262 if (op1 != 1)
8263 goto illegal_op;
8264
be5e7a76 8265 ARCH(5);
9ee6e8bb 8266 /* branch link/exchange thumb (blx) */
d9ba4830 8267 tmp = load_reg(s, rm);
7d1b0095 8268 tmp2 = tcg_temp_new_i32();
d9ba4830
PB
8269 tcg_gen_movi_i32(tmp2, s->pc);
8270 store_reg(s, 14, tmp2);
8271 gen_bx(s, tmp);
9ee6e8bb 8272 break;
eb0ecd5a
WN
8273 case 0x4:
8274 {
8275 /* crc32/crc32c */
8276 uint32_t c = extract32(insn, 8, 4);
8277
8278 /* Check this CPU supports ARMv8 CRC instructions.
8279 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
8280 * Bits 8, 10 and 11 should be zero.
8281 */
d614a513 8282 if (!arm_dc_feature(s, ARM_FEATURE_CRC) || op1 == 0x3 ||
eb0ecd5a
WN
8283 (c & 0xd) != 0) {
8284 goto illegal_op;
8285 }
8286
8287 rn = extract32(insn, 16, 4);
8288 rd = extract32(insn, 12, 4);
8289
8290 tmp = load_reg(s, rn);
8291 tmp2 = load_reg(s, rm);
aa633469
PM
8292 if (op1 == 0) {
8293 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
8294 } else if (op1 == 1) {
8295 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
8296 }
eb0ecd5a
WN
8297 tmp3 = tcg_const_i32(1 << op1);
8298 if (c & 0x2) {
8299 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
8300 } else {
8301 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
8302 }
8303 tcg_temp_free_i32(tmp2);
8304 tcg_temp_free_i32(tmp3);
8305 store_reg(s, rd, tmp);
8306 break;
8307 }
9ee6e8bb 8308 case 0x5: /* saturating add/subtract */
be5e7a76 8309 ARCH(5TE);
9ee6e8bb
PB
8310 rd = (insn >> 12) & 0xf;
8311 rn = (insn >> 16) & 0xf;
b40d0353 8312 tmp = load_reg(s, rm);
5e3f878a 8313 tmp2 = load_reg(s, rn);
9ee6e8bb 8314 if (op1 & 2)
9ef39277 8315 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
9ee6e8bb 8316 if (op1 & 1)
9ef39277 8317 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 8318 else
9ef39277 8319 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 8320 tcg_temp_free_i32(tmp2);
5e3f878a 8321 store_reg(s, rd, tmp);
9ee6e8bb 8322 break;
49e14940 8323 case 7:
d4a2dc67
PM
8324 {
8325 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
37e6456e 8326 switch (op1) {
19a6e31c
PM
8327 case 0:
8328 /* HLT */
8329 gen_hlt(s, imm16);
8330 break;
37e6456e
PM
8331 case 1:
8332 /* bkpt */
8333 ARCH(5);
8334 gen_exception_insn(s, 4, EXCP_BKPT,
73710361
GB
8335 syn_aa32_bkpt(imm16, false),
8336 default_exception_el(s));
37e6456e
PM
8337 break;
8338 case 2:
8339 /* Hypervisor call (v7) */
8340 ARCH(7);
8341 if (IS_USER(s)) {
8342 goto illegal_op;
8343 }
8344 gen_hvc(s, imm16);
8345 break;
8346 case 3:
8347 /* Secure monitor call (v6+) */
8348 ARCH(6K);
8349 if (IS_USER(s)) {
8350 goto illegal_op;
8351 }
8352 gen_smc(s);
8353 break;
8354 default:
19a6e31c 8355 g_assert_not_reached();
49e14940 8356 }
9ee6e8bb 8357 break;
d4a2dc67 8358 }
9ee6e8bb
PB
8359 case 0x8: /* signed multiply */
8360 case 0xa:
8361 case 0xc:
8362 case 0xe:
be5e7a76 8363 ARCH(5TE);
9ee6e8bb
PB
8364 rs = (insn >> 8) & 0xf;
8365 rn = (insn >> 12) & 0xf;
8366 rd = (insn >> 16) & 0xf;
8367 if (op1 == 1) {
8368 /* (32 * 16) >> 16 */
5e3f878a
PB
8369 tmp = load_reg(s, rm);
8370 tmp2 = load_reg(s, rs);
9ee6e8bb 8371 if (sh & 4)
5e3f878a 8372 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 8373 else
5e3f878a 8374 gen_sxth(tmp2);
a7812ae4
PB
8375 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8376 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 8377 tmp = tcg_temp_new_i32();
ecc7b3aa 8378 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 8379 tcg_temp_free_i64(tmp64);
9ee6e8bb 8380 if ((sh & 2) == 0) {
5e3f878a 8381 tmp2 = load_reg(s, rn);
9ef39277 8382 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8383 tcg_temp_free_i32(tmp2);
9ee6e8bb 8384 }
5e3f878a 8385 store_reg(s, rd, tmp);
9ee6e8bb
PB
8386 } else {
8387 /* 16 * 16 */
5e3f878a
PB
8388 tmp = load_reg(s, rm);
8389 tmp2 = load_reg(s, rs);
8390 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7d1b0095 8391 tcg_temp_free_i32(tmp2);
9ee6e8bb 8392 if (op1 == 2) {
a7812ae4
PB
8393 tmp64 = tcg_temp_new_i64();
8394 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 8395 tcg_temp_free_i32(tmp);
a7812ae4
PB
8396 gen_addq(s, tmp64, rn, rd);
8397 gen_storeq_reg(s, rn, rd, tmp64);
b75263d6 8398 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
8399 } else {
8400 if (op1 == 0) {
5e3f878a 8401 tmp2 = load_reg(s, rn);
9ef39277 8402 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8403 tcg_temp_free_i32(tmp2);
9ee6e8bb 8404 }
5e3f878a 8405 store_reg(s, rd, tmp);
9ee6e8bb
PB
8406 }
8407 }
8408 break;
8409 default:
8410 goto illegal_op;
8411 }
8412 } else if (((insn & 0x0e000000) == 0 &&
8413 (insn & 0x00000090) != 0x90) ||
8414 ((insn & 0x0e000000) == (1 << 25))) {
8415 int set_cc, logic_cc, shiftop;
8416
8417 op1 = (insn >> 21) & 0xf;
8418 set_cc = (insn >> 20) & 1;
8419 logic_cc = table_logic_cc[op1] & set_cc;
8420
8421 /* data processing instruction */
8422 if (insn & (1 << 25)) {
8423 /* immediate operand */
8424 val = insn & 0xff;
8425 shift = ((insn >> 8) & 0xf) * 2;
e9bb4aa9 8426 if (shift) {
9ee6e8bb 8427 val = (val >> shift) | (val << (32 - shift));
e9bb4aa9 8428 }
7d1b0095 8429 tmp2 = tcg_temp_new_i32();
e9bb4aa9
JR
8430 tcg_gen_movi_i32(tmp2, val);
8431 if (logic_cc && shift) {
8432 gen_set_CF_bit31(tmp2);
8433 }
9ee6e8bb
PB
8434 } else {
8435 /* register */
8436 rm = (insn) & 0xf;
e9bb4aa9 8437 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
8438 shiftop = (insn >> 5) & 3;
8439 if (!(insn & (1 << 4))) {
8440 shift = (insn >> 7) & 0x1f;
e9bb4aa9 8441 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9ee6e8bb
PB
8442 } else {
8443 rs = (insn >> 8) & 0xf;
8984bd2e 8444 tmp = load_reg(s, rs);
e9bb4aa9 8445 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9ee6e8bb
PB
8446 }
8447 }
8448 if (op1 != 0x0f && op1 != 0x0d) {
8449 rn = (insn >> 16) & 0xf;
e9bb4aa9
JR
8450 tmp = load_reg(s, rn);
8451 } else {
39d5492a 8452 TCGV_UNUSED_I32(tmp);
9ee6e8bb
PB
8453 }
8454 rd = (insn >> 12) & 0xf;
8455 switch(op1) {
8456 case 0x00:
e9bb4aa9
JR
8457 tcg_gen_and_i32(tmp, tmp, tmp2);
8458 if (logic_cc) {
8459 gen_logic_CC(tmp);
8460 }
7dcc1f89 8461 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8462 break;
8463 case 0x01:
e9bb4aa9
JR
8464 tcg_gen_xor_i32(tmp, tmp, tmp2);
8465 if (logic_cc) {
8466 gen_logic_CC(tmp);
8467 }
7dcc1f89 8468 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8469 break;
8470 case 0x02:
8471 if (set_cc && rd == 15) {
8472 /* SUBS r15, ... is used for exception return. */
e9bb4aa9 8473 if (IS_USER(s)) {
9ee6e8bb 8474 goto illegal_op;
e9bb4aa9 8475 }
72485ec4 8476 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9 8477 gen_exception_return(s, tmp);
9ee6e8bb 8478 } else {
e9bb4aa9 8479 if (set_cc) {
72485ec4 8480 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8481 } else {
8482 tcg_gen_sub_i32(tmp, tmp, tmp2);
8483 }
7dcc1f89 8484 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8485 }
8486 break;
8487 case 0x03:
e9bb4aa9 8488 if (set_cc) {
72485ec4 8489 gen_sub_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
8490 } else {
8491 tcg_gen_sub_i32(tmp, tmp2, tmp);
8492 }
7dcc1f89 8493 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8494 break;
8495 case 0x04:
e9bb4aa9 8496 if (set_cc) {
72485ec4 8497 gen_add_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8498 } else {
8499 tcg_gen_add_i32(tmp, tmp, tmp2);
8500 }
7dcc1f89 8501 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8502 break;
8503 case 0x05:
e9bb4aa9 8504 if (set_cc) {
49b4c31e 8505 gen_adc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8506 } else {
8507 gen_add_carry(tmp, tmp, tmp2);
8508 }
7dcc1f89 8509 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8510 break;
8511 case 0x06:
e9bb4aa9 8512 if (set_cc) {
2de68a49 8513 gen_sbc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8514 } else {
8515 gen_sub_carry(tmp, tmp, tmp2);
8516 }
7dcc1f89 8517 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8518 break;
8519 case 0x07:
e9bb4aa9 8520 if (set_cc) {
2de68a49 8521 gen_sbc_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
8522 } else {
8523 gen_sub_carry(tmp, tmp2, tmp);
8524 }
7dcc1f89 8525 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8526 break;
8527 case 0x08:
8528 if (set_cc) {
e9bb4aa9
JR
8529 tcg_gen_and_i32(tmp, tmp, tmp2);
8530 gen_logic_CC(tmp);
9ee6e8bb 8531 }
7d1b0095 8532 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8533 break;
8534 case 0x09:
8535 if (set_cc) {
e9bb4aa9
JR
8536 tcg_gen_xor_i32(tmp, tmp, tmp2);
8537 gen_logic_CC(tmp);
9ee6e8bb 8538 }
7d1b0095 8539 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8540 break;
8541 case 0x0a:
8542 if (set_cc) {
72485ec4 8543 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb 8544 }
7d1b0095 8545 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8546 break;
8547 case 0x0b:
8548 if (set_cc) {
72485ec4 8549 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 8550 }
7d1b0095 8551 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8552 break;
8553 case 0x0c:
e9bb4aa9
JR
8554 tcg_gen_or_i32(tmp, tmp, tmp2);
8555 if (logic_cc) {
8556 gen_logic_CC(tmp);
8557 }
7dcc1f89 8558 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8559 break;
8560 case 0x0d:
8561 if (logic_cc && rd == 15) {
8562 /* MOVS r15, ... is used for exception return. */
e9bb4aa9 8563 if (IS_USER(s)) {
9ee6e8bb 8564 goto illegal_op;
e9bb4aa9
JR
8565 }
8566 gen_exception_return(s, tmp2);
9ee6e8bb 8567 } else {
e9bb4aa9
JR
8568 if (logic_cc) {
8569 gen_logic_CC(tmp2);
8570 }
7dcc1f89 8571 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
8572 }
8573 break;
8574 case 0x0e:
f669df27 8575 tcg_gen_andc_i32(tmp, tmp, tmp2);
e9bb4aa9
JR
8576 if (logic_cc) {
8577 gen_logic_CC(tmp);
8578 }
7dcc1f89 8579 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8580 break;
8581 default:
8582 case 0x0f:
e9bb4aa9
JR
8583 tcg_gen_not_i32(tmp2, tmp2);
8584 if (logic_cc) {
8585 gen_logic_CC(tmp2);
8586 }
7dcc1f89 8587 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
8588 break;
8589 }
e9bb4aa9 8590 if (op1 != 0x0f && op1 != 0x0d) {
7d1b0095 8591 tcg_temp_free_i32(tmp2);
e9bb4aa9 8592 }
9ee6e8bb
PB
8593 } else {
8594 /* other instructions */
8595 op1 = (insn >> 24) & 0xf;
8596 switch(op1) {
8597 case 0x0:
8598 case 0x1:
8599 /* multiplies, extra load/stores */
8600 sh = (insn >> 5) & 3;
8601 if (sh == 0) {
8602 if (op1 == 0x0) {
8603 rd = (insn >> 16) & 0xf;
8604 rn = (insn >> 12) & 0xf;
8605 rs = (insn >> 8) & 0xf;
8606 rm = (insn) & 0xf;
8607 op1 = (insn >> 20) & 0xf;
8608 switch (op1) {
8609 case 0: case 1: case 2: case 3: case 6:
8610 /* 32 bit mul */
5e3f878a
PB
8611 tmp = load_reg(s, rs);
8612 tmp2 = load_reg(s, rm);
8613 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 8614 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8615 if (insn & (1 << 22)) {
8616 /* Subtract (mls) */
8617 ARCH(6T2);
5e3f878a
PB
8618 tmp2 = load_reg(s, rn);
8619 tcg_gen_sub_i32(tmp, tmp2, tmp);
7d1b0095 8620 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8621 } else if (insn & (1 << 21)) {
8622 /* Add */
5e3f878a
PB
8623 tmp2 = load_reg(s, rn);
8624 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 8625 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8626 }
8627 if (insn & (1 << 20))
5e3f878a
PB
8628 gen_logic_CC(tmp);
8629 store_reg(s, rd, tmp);
9ee6e8bb 8630 break;
8aac08b1
AJ
8631 case 4:
8632 /* 64 bit mul double accumulate (UMAAL) */
8633 ARCH(6);
8634 tmp = load_reg(s, rs);
8635 tmp2 = load_reg(s, rm);
8636 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8637 gen_addq_lo(s, tmp64, rn);
8638 gen_addq_lo(s, tmp64, rd);
8639 gen_storeq_reg(s, rn, rd, tmp64);
8640 tcg_temp_free_i64(tmp64);
8641 break;
8642 case 8: case 9: case 10: case 11:
8643 case 12: case 13: case 14: case 15:
8644 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
5e3f878a
PB
8645 tmp = load_reg(s, rs);
8646 tmp2 = load_reg(s, rm);
8aac08b1 8647 if (insn & (1 << 22)) {
c9f10124 8648 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1 8649 } else {
c9f10124 8650 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1
AJ
8651 }
8652 if (insn & (1 << 21)) { /* mult accumulate */
39d5492a
PM
8653 TCGv_i32 al = load_reg(s, rn);
8654 TCGv_i32 ah = load_reg(s, rd);
c9f10124 8655 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
39d5492a
PM
8656 tcg_temp_free_i32(al);
8657 tcg_temp_free_i32(ah);
9ee6e8bb 8658 }
8aac08b1 8659 if (insn & (1 << 20)) {
c9f10124 8660 gen_logicq_cc(tmp, tmp2);
8aac08b1 8661 }
c9f10124
RH
8662 store_reg(s, rn, tmp);
8663 store_reg(s, rd, tmp2);
9ee6e8bb 8664 break;
8aac08b1
AJ
8665 default:
8666 goto illegal_op;
9ee6e8bb
PB
8667 }
8668 } else {
8669 rn = (insn >> 16) & 0xf;
8670 rd = (insn >> 12) & 0xf;
8671 if (insn & (1 << 23)) {
8672 /* load/store exclusive */
2359bf80 8673 int op2 = (insn >> 8) & 3;
86753403 8674 op1 = (insn >> 21) & 0x3;
2359bf80
MR
8675
8676 switch (op2) {
8677 case 0: /* lda/stl */
8678 if (op1 == 1) {
8679 goto illegal_op;
8680 }
8681 ARCH(8);
8682 break;
8683 case 1: /* reserved */
8684 goto illegal_op;
8685 case 2: /* ldaex/stlex */
8686 ARCH(8);
8687 break;
8688 case 3: /* ldrex/strex */
8689 if (op1) {
8690 ARCH(6K);
8691 } else {
8692 ARCH(6);
8693 }
8694 break;
8695 }
8696
3174f8e9 8697 addr = tcg_temp_local_new_i32();
98a46317 8698 load_reg_var(s, addr, rn);
2359bf80
MR
8699
8700 /* Since the emulation does not have barriers,
8701 the acquire/release semantics need no special
8702 handling */
8703 if (op2 == 0) {
8704 if (insn & (1 << 20)) {
8705 tmp = tcg_temp_new_i32();
8706 switch (op1) {
8707 case 0: /* lda */
12dcc321
PB
8708 gen_aa32_ld32u(s, tmp, addr,
8709 get_mem_index(s));
2359bf80
MR
8710 break;
8711 case 2: /* ldab */
12dcc321
PB
8712 gen_aa32_ld8u(s, tmp, addr,
8713 get_mem_index(s));
2359bf80
MR
8714 break;
8715 case 3: /* ldah */
12dcc321
PB
8716 gen_aa32_ld16u(s, tmp, addr,
8717 get_mem_index(s));
2359bf80
MR
8718 break;
8719 default:
8720 abort();
8721 }
8722 store_reg(s, rd, tmp);
8723 } else {
8724 rm = insn & 0xf;
8725 tmp = load_reg(s, rm);
8726 switch (op1) {
8727 case 0: /* stl */
12dcc321
PB
8728 gen_aa32_st32(s, tmp, addr,
8729 get_mem_index(s));
2359bf80
MR
8730 break;
8731 case 2: /* stlb */
12dcc321
PB
8732 gen_aa32_st8(s, tmp, addr,
8733 get_mem_index(s));
2359bf80
MR
8734 break;
8735 case 3: /* stlh */
12dcc321
PB
8736 gen_aa32_st16(s, tmp, addr,
8737 get_mem_index(s));
2359bf80
MR
8738 break;
8739 default:
8740 abort();
8741 }
8742 tcg_temp_free_i32(tmp);
8743 }
8744 } else if (insn & (1 << 20)) {
86753403
PB
8745 switch (op1) {
8746 case 0: /* ldrex */
426f5abc 8747 gen_load_exclusive(s, rd, 15, addr, 2);
86753403
PB
8748 break;
8749 case 1: /* ldrexd */
426f5abc 8750 gen_load_exclusive(s, rd, rd + 1, addr, 3);
86753403
PB
8751 break;
8752 case 2: /* ldrexb */
426f5abc 8753 gen_load_exclusive(s, rd, 15, addr, 0);
86753403
PB
8754 break;
8755 case 3: /* ldrexh */
426f5abc 8756 gen_load_exclusive(s, rd, 15, addr, 1);
86753403
PB
8757 break;
8758 default:
8759 abort();
8760 }
9ee6e8bb
PB
8761 } else {
8762 rm = insn & 0xf;
86753403
PB
8763 switch (op1) {
8764 case 0: /* strex */
426f5abc 8765 gen_store_exclusive(s, rd, rm, 15, addr, 2);
86753403
PB
8766 break;
8767 case 1: /* strexd */
502e64fe 8768 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
86753403
PB
8769 break;
8770 case 2: /* strexb */
426f5abc 8771 gen_store_exclusive(s, rd, rm, 15, addr, 0);
86753403
PB
8772 break;
8773 case 3: /* strexh */
426f5abc 8774 gen_store_exclusive(s, rd, rm, 15, addr, 1);
86753403
PB
8775 break;
8776 default:
8777 abort();
8778 }
9ee6e8bb 8779 }
39d5492a 8780 tcg_temp_free_i32(addr);
9ee6e8bb 8781 } else {
cf12bce0
EC
8782 TCGv taddr;
8783 TCGMemOp opc = s->be_data;
8784
9ee6e8bb
PB
8785 /* SWP instruction */
8786 rm = (insn) & 0xf;
8787
9ee6e8bb 8788 if (insn & (1 << 22)) {
cf12bce0 8789 opc |= MO_UB;
9ee6e8bb 8790 } else {
cf12bce0 8791 opc |= MO_UL | MO_ALIGN;
9ee6e8bb 8792 }
cf12bce0
EC
8793
8794 addr = load_reg(s, rn);
8795 taddr = gen_aa32_addr(s, addr, opc);
7d1b0095 8796 tcg_temp_free_i32(addr);
cf12bce0
EC
8797
8798 tmp = load_reg(s, rm);
8799 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp,
8800 get_mem_index(s), opc);
8801 tcg_temp_free(taddr);
8802 store_reg(s, rd, tmp);
9ee6e8bb
PB
8803 }
8804 }
8805 } else {
8806 int address_offset;
3960c336
PM
8807 bool load = insn & (1 << 20);
8808 bool doubleword = false;
9ee6e8bb
PB
8809 /* Misc load/store */
8810 rn = (insn >> 16) & 0xf;
8811 rd = (insn >> 12) & 0xf;
3960c336
PM
8812
8813 if (!load && (sh & 2)) {
8814 /* doubleword */
8815 ARCH(5TE);
8816 if (rd & 1) {
8817 /* UNPREDICTABLE; we choose to UNDEF */
8818 goto illegal_op;
8819 }
8820 load = (sh & 1) == 0;
8821 doubleword = true;
8822 }
8823
b0109805 8824 addr = load_reg(s, rn);
9ee6e8bb 8825 if (insn & (1 << 24))
b0109805 8826 gen_add_datah_offset(s, insn, 0, addr);
9ee6e8bb 8827 address_offset = 0;
3960c336
PM
8828
8829 if (doubleword) {
8830 if (!load) {
9ee6e8bb 8831 /* store */
b0109805 8832 tmp = load_reg(s, rd);
12dcc321 8833 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 8834 tcg_temp_free_i32(tmp);
b0109805
PB
8835 tcg_gen_addi_i32(addr, addr, 4);
8836 tmp = load_reg(s, rd + 1);
12dcc321 8837 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 8838 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8839 } else {
8840 /* load */
5a839c0d 8841 tmp = tcg_temp_new_i32();
12dcc321 8842 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805
PB
8843 store_reg(s, rd, tmp);
8844 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 8845 tmp = tcg_temp_new_i32();
12dcc321 8846 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 8847 rd++;
9ee6e8bb
PB
8848 }
8849 address_offset = -4;
3960c336
PM
8850 } else if (load) {
8851 /* load */
8852 tmp = tcg_temp_new_i32();
8853 switch (sh) {
8854 case 1:
12dcc321 8855 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
3960c336
PM
8856 break;
8857 case 2:
12dcc321 8858 gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
3960c336
PM
8859 break;
8860 default:
8861 case 3:
12dcc321 8862 gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
3960c336
PM
8863 break;
8864 }
9ee6e8bb
PB
8865 } else {
8866 /* store */
b0109805 8867 tmp = load_reg(s, rd);
12dcc321 8868 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
5a839c0d 8869 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8870 }
8871 /* Perform base writeback before the loaded value to
8872 ensure correct behavior with overlapping index registers.
b6af0975 8873 ldrd with base writeback is undefined if the
9ee6e8bb
PB
8874 destination and index registers overlap. */
8875 if (!(insn & (1 << 24))) {
b0109805
PB
8876 gen_add_datah_offset(s, insn, address_offset, addr);
8877 store_reg(s, rn, addr);
9ee6e8bb
PB
8878 } else if (insn & (1 << 21)) {
8879 if (address_offset)
b0109805
PB
8880 tcg_gen_addi_i32(addr, addr, address_offset);
8881 store_reg(s, rn, addr);
8882 } else {
7d1b0095 8883 tcg_temp_free_i32(addr);
9ee6e8bb
PB
8884 }
8885 if (load) {
8886 /* Complete the load. */
b0109805 8887 store_reg(s, rd, tmp);
9ee6e8bb
PB
8888 }
8889 }
8890 break;
8891 case 0x4:
8892 case 0x5:
8893 goto do_ldst;
8894 case 0x6:
8895 case 0x7:
8896 if (insn & (1 << 4)) {
8897 ARCH(6);
8898 /* Armv6 Media instructions. */
8899 rm = insn & 0xf;
8900 rn = (insn >> 16) & 0xf;
2c0262af 8901 rd = (insn >> 12) & 0xf;
9ee6e8bb
PB
8902 rs = (insn >> 8) & 0xf;
8903 switch ((insn >> 23) & 3) {
8904 case 0: /* Parallel add/subtract. */
8905 op1 = (insn >> 20) & 7;
6ddbc6e4
PB
8906 tmp = load_reg(s, rn);
8907 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
8908 sh = (insn >> 5) & 7;
8909 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
8910 goto illegal_op;
6ddbc6e4 8911 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7d1b0095 8912 tcg_temp_free_i32(tmp2);
6ddbc6e4 8913 store_reg(s, rd, tmp);
9ee6e8bb
PB
8914 break;
8915 case 1:
8916 if ((insn & 0x00700020) == 0) {
6c95676b 8917 /* Halfword pack. */
3670669c
PB
8918 tmp = load_reg(s, rn);
8919 tmp2 = load_reg(s, rm);
9ee6e8bb 8920 shift = (insn >> 7) & 0x1f;
3670669c
PB
8921 if (insn & (1 << 6)) {
8922 /* pkhtb */
22478e79
AZ
8923 if (shift == 0)
8924 shift = 31;
8925 tcg_gen_sari_i32(tmp2, tmp2, shift);
3670669c 8926 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
86831435 8927 tcg_gen_ext16u_i32(tmp2, tmp2);
3670669c
PB
8928 } else {
8929 /* pkhbt */
22478e79
AZ
8930 if (shift)
8931 tcg_gen_shli_i32(tmp2, tmp2, shift);
86831435 8932 tcg_gen_ext16u_i32(tmp, tmp);
3670669c
PB
8933 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8934 }
8935 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 8936 tcg_temp_free_i32(tmp2);
3670669c 8937 store_reg(s, rd, tmp);
9ee6e8bb
PB
8938 } else if ((insn & 0x00200020) == 0x00200000) {
8939 /* [us]sat */
6ddbc6e4 8940 tmp = load_reg(s, rm);
9ee6e8bb
PB
8941 shift = (insn >> 7) & 0x1f;
8942 if (insn & (1 << 6)) {
8943 if (shift == 0)
8944 shift = 31;
6ddbc6e4 8945 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 8946 } else {
6ddbc6e4 8947 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb
PB
8948 }
8949 sh = (insn >> 16) & 0x1f;
40d3c433
CL
8950 tmp2 = tcg_const_i32(sh);
8951 if (insn & (1 << 22))
9ef39277 8952 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
40d3c433 8953 else
9ef39277 8954 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
40d3c433 8955 tcg_temp_free_i32(tmp2);
6ddbc6e4 8956 store_reg(s, rd, tmp);
9ee6e8bb
PB
8957 } else if ((insn & 0x00300fe0) == 0x00200f20) {
8958 /* [us]sat16 */
6ddbc6e4 8959 tmp = load_reg(s, rm);
9ee6e8bb 8960 sh = (insn >> 16) & 0x1f;
40d3c433
CL
8961 tmp2 = tcg_const_i32(sh);
8962 if (insn & (1 << 22))
9ef39277 8963 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
40d3c433 8964 else
9ef39277 8965 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
40d3c433 8966 tcg_temp_free_i32(tmp2);
6ddbc6e4 8967 store_reg(s, rd, tmp);
9ee6e8bb
PB
8968 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
8969 /* Select bytes. */
6ddbc6e4
PB
8970 tmp = load_reg(s, rn);
8971 tmp2 = load_reg(s, rm);
7d1b0095 8972 tmp3 = tcg_temp_new_i32();
0ecb72a5 8973 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 8974 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
8975 tcg_temp_free_i32(tmp3);
8976 tcg_temp_free_i32(tmp2);
6ddbc6e4 8977 store_reg(s, rd, tmp);
9ee6e8bb 8978 } else if ((insn & 0x000003e0) == 0x00000060) {
5e3f878a 8979 tmp = load_reg(s, rm);
9ee6e8bb 8980 shift = (insn >> 10) & 3;
1301f322 8981 /* ??? In many cases it's not necessary to do a
9ee6e8bb
PB
8982 rotate, a shift is sufficient. */
8983 if (shift != 0)
f669df27 8984 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
8985 op1 = (insn >> 20) & 7;
8986 switch (op1) {
5e3f878a
PB
8987 case 0: gen_sxtb16(tmp); break;
8988 case 2: gen_sxtb(tmp); break;
8989 case 3: gen_sxth(tmp); break;
8990 case 4: gen_uxtb16(tmp); break;
8991 case 6: gen_uxtb(tmp); break;
8992 case 7: gen_uxth(tmp); break;
9ee6e8bb
PB
8993 default: goto illegal_op;
8994 }
8995 if (rn != 15) {
5e3f878a 8996 tmp2 = load_reg(s, rn);
9ee6e8bb 8997 if ((op1 & 3) == 0) {
5e3f878a 8998 gen_add16(tmp, tmp2);
9ee6e8bb 8999 } else {
5e3f878a 9000 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9001 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9002 }
9003 }
6c95676b 9004 store_reg(s, rd, tmp);
9ee6e8bb
PB
9005 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
9006 /* rev */
b0109805 9007 tmp = load_reg(s, rm);
9ee6e8bb
PB
9008 if (insn & (1 << 22)) {
9009 if (insn & (1 << 7)) {
b0109805 9010 gen_revsh(tmp);
9ee6e8bb
PB
9011 } else {
9012 ARCH(6T2);
b0109805 9013 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
9014 }
9015 } else {
9016 if (insn & (1 << 7))
b0109805 9017 gen_rev16(tmp);
9ee6e8bb 9018 else
66896cb8 9019 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb 9020 }
b0109805 9021 store_reg(s, rd, tmp);
9ee6e8bb
PB
9022 } else {
9023 goto illegal_op;
9024 }
9025 break;
9026 case 2: /* Multiplies (Type 3). */
41e9564d
PM
9027 switch ((insn >> 20) & 0x7) {
9028 case 5:
9029 if (((insn >> 6) ^ (insn >> 7)) & 1) {
9030 /* op2 not 00x or 11x : UNDEF */
9031 goto illegal_op;
9032 }
838fa72d
AJ
9033 /* Signed multiply most significant [accumulate].
9034 (SMMUL, SMMLA, SMMLS) */
41e9564d
PM
9035 tmp = load_reg(s, rm);
9036 tmp2 = load_reg(s, rs);
a7812ae4 9037 tmp64 = gen_muls_i64_i32(tmp, tmp2);
838fa72d 9038
955a7dd5 9039 if (rd != 15) {
838fa72d 9040 tmp = load_reg(s, rd);
9ee6e8bb 9041 if (insn & (1 << 6)) {
838fa72d 9042 tmp64 = gen_subq_msw(tmp64, tmp);
9ee6e8bb 9043 } else {
838fa72d 9044 tmp64 = gen_addq_msw(tmp64, tmp);
9ee6e8bb
PB
9045 }
9046 }
838fa72d
AJ
9047 if (insn & (1 << 5)) {
9048 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9049 }
9050 tcg_gen_shri_i64(tmp64, tmp64, 32);
7d1b0095 9051 tmp = tcg_temp_new_i32();
ecc7b3aa 9052 tcg_gen_extrl_i64_i32(tmp, tmp64);
838fa72d 9053 tcg_temp_free_i64(tmp64);
955a7dd5 9054 store_reg(s, rn, tmp);
41e9564d
PM
9055 break;
9056 case 0:
9057 case 4:
9058 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
9059 if (insn & (1 << 7)) {
9060 goto illegal_op;
9061 }
9062 tmp = load_reg(s, rm);
9063 tmp2 = load_reg(s, rs);
9ee6e8bb 9064 if (insn & (1 << 5))
5e3f878a
PB
9065 gen_swap_half(tmp2);
9066 gen_smul_dual(tmp, tmp2);
9ee6e8bb 9067 if (insn & (1 << 22)) {
5e3f878a 9068 /* smlald, smlsld */
33bbd75a
PC
9069 TCGv_i64 tmp64_2;
9070
a7812ae4 9071 tmp64 = tcg_temp_new_i64();
33bbd75a 9072 tmp64_2 = tcg_temp_new_i64();
a7812ae4 9073 tcg_gen_ext_i32_i64(tmp64, tmp);
33bbd75a 9074 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
7d1b0095 9075 tcg_temp_free_i32(tmp);
33bbd75a
PC
9076 tcg_temp_free_i32(tmp2);
9077 if (insn & (1 << 6)) {
9078 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
9079 } else {
9080 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
9081 }
9082 tcg_temp_free_i64(tmp64_2);
a7812ae4
PB
9083 gen_addq(s, tmp64, rd, rn);
9084 gen_storeq_reg(s, rd, rn, tmp64);
b75263d6 9085 tcg_temp_free_i64(tmp64);
9ee6e8bb 9086 } else {
5e3f878a 9087 /* smuad, smusd, smlad, smlsd */
33bbd75a
PC
9088 if (insn & (1 << 6)) {
9089 /* This subtraction cannot overflow. */
9090 tcg_gen_sub_i32(tmp, tmp, tmp2);
9091 } else {
9092 /* This addition cannot overflow 32 bits;
9093 * however it may overflow considered as a
9094 * signed operation, in which case we must set
9095 * the Q flag.
9096 */
9097 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9098 }
9099 tcg_temp_free_i32(tmp2);
22478e79 9100 if (rd != 15)
9ee6e8bb 9101 {
22478e79 9102 tmp2 = load_reg(s, rd);
9ef39277 9103 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 9104 tcg_temp_free_i32(tmp2);
9ee6e8bb 9105 }
22478e79 9106 store_reg(s, rn, tmp);
9ee6e8bb 9107 }
41e9564d 9108 break;
b8b8ea05
PM
9109 case 1:
9110 case 3:
9111 /* SDIV, UDIV */
d614a513 9112 if (!arm_dc_feature(s, ARM_FEATURE_ARM_DIV)) {
b8b8ea05
PM
9113 goto illegal_op;
9114 }
9115 if (((insn >> 5) & 7) || (rd != 15)) {
9116 goto illegal_op;
9117 }
9118 tmp = load_reg(s, rm);
9119 tmp2 = load_reg(s, rs);
9120 if (insn & (1 << 21)) {
9121 gen_helper_udiv(tmp, tmp, tmp2);
9122 } else {
9123 gen_helper_sdiv(tmp, tmp, tmp2);
9124 }
9125 tcg_temp_free_i32(tmp2);
9126 store_reg(s, rn, tmp);
9127 break;
41e9564d
PM
9128 default:
9129 goto illegal_op;
9ee6e8bb
PB
9130 }
9131 break;
9132 case 3:
9133 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
9134 switch (op1) {
9135 case 0: /* Unsigned sum of absolute differences. */
6ddbc6e4
PB
9136 ARCH(6);
9137 tmp = load_reg(s, rm);
9138 tmp2 = load_reg(s, rs);
9139 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 9140 tcg_temp_free_i32(tmp2);
ded9d295
AZ
9141 if (rd != 15) {
9142 tmp2 = load_reg(s, rd);
6ddbc6e4 9143 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9144 tcg_temp_free_i32(tmp2);
9ee6e8bb 9145 }
ded9d295 9146 store_reg(s, rn, tmp);
9ee6e8bb
PB
9147 break;
9148 case 0x20: case 0x24: case 0x28: case 0x2c:
9149 /* Bitfield insert/clear. */
9150 ARCH(6T2);
9151 shift = (insn >> 7) & 0x1f;
9152 i = (insn >> 16) & 0x1f;
45140a57
KB
9153 if (i < shift) {
9154 /* UNPREDICTABLE; we choose to UNDEF */
9155 goto illegal_op;
9156 }
9ee6e8bb
PB
9157 i = i + 1 - shift;
9158 if (rm == 15) {
7d1b0095 9159 tmp = tcg_temp_new_i32();
5e3f878a 9160 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 9161 } else {
5e3f878a 9162 tmp = load_reg(s, rm);
9ee6e8bb
PB
9163 }
9164 if (i != 32) {
5e3f878a 9165 tmp2 = load_reg(s, rd);
d593c48e 9166 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
7d1b0095 9167 tcg_temp_free_i32(tmp2);
9ee6e8bb 9168 }
5e3f878a 9169 store_reg(s, rd, tmp);
9ee6e8bb
PB
9170 break;
9171 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
9172 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
4cc633c3 9173 ARCH(6T2);
5e3f878a 9174 tmp = load_reg(s, rm);
9ee6e8bb
PB
9175 shift = (insn >> 7) & 0x1f;
9176 i = ((insn >> 16) & 0x1f) + 1;
9177 if (shift + i > 32)
9178 goto illegal_op;
9179 if (i < 32) {
9180 if (op1 & 0x20) {
5e3f878a 9181 gen_ubfx(tmp, shift, (1u << i) - 1);
9ee6e8bb 9182 } else {
5e3f878a 9183 gen_sbfx(tmp, shift, i);
9ee6e8bb
PB
9184 }
9185 }
5e3f878a 9186 store_reg(s, rd, tmp);
9ee6e8bb
PB
9187 break;
9188 default:
9189 goto illegal_op;
9190 }
9191 break;
9192 }
9193 break;
9194 }
9195 do_ldst:
9196 /* Check for undefined extension instructions
9197 * per the ARM Bible IE:
9198 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
9199 */
9200 sh = (0xf << 20) | (0xf << 4);
9201 if (op1 == 0x7 && ((insn & sh) == sh))
9202 {
9203 goto illegal_op;
9204 }
9205 /* load/store byte/word */
9206 rn = (insn >> 16) & 0xf;
9207 rd = (insn >> 12) & 0xf;
b0109805 9208 tmp2 = load_reg(s, rn);
a99caa48
PM
9209 if ((insn & 0x01200000) == 0x00200000) {
9210 /* ldrt/strt */
579d21cc 9211 i = get_a32_user_mem_index(s);
a99caa48
PM
9212 } else {
9213 i = get_mem_index(s);
9214 }
9ee6e8bb 9215 if (insn & (1 << 24))
b0109805 9216 gen_add_data_offset(s, insn, tmp2);
9ee6e8bb
PB
9217 if (insn & (1 << 20)) {
9218 /* load */
5a839c0d 9219 tmp = tcg_temp_new_i32();
9ee6e8bb 9220 if (insn & (1 << 22)) {
12dcc321 9221 gen_aa32_ld8u(s, tmp, tmp2, i);
9ee6e8bb 9222 } else {
12dcc321 9223 gen_aa32_ld32u(s, tmp, tmp2, i);
9ee6e8bb 9224 }
9ee6e8bb
PB
9225 } else {
9226 /* store */
b0109805 9227 tmp = load_reg(s, rd);
5a839c0d 9228 if (insn & (1 << 22)) {
12dcc321 9229 gen_aa32_st8(s, tmp, tmp2, i);
5a839c0d 9230 } else {
12dcc321 9231 gen_aa32_st32(s, tmp, tmp2, i);
5a839c0d
PM
9232 }
9233 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9234 }
9235 if (!(insn & (1 << 24))) {
b0109805
PB
9236 gen_add_data_offset(s, insn, tmp2);
9237 store_reg(s, rn, tmp2);
9238 } else if (insn & (1 << 21)) {
9239 store_reg(s, rn, tmp2);
9240 } else {
7d1b0095 9241 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9242 }
9243 if (insn & (1 << 20)) {
9244 /* Complete the load. */
7dcc1f89 9245 store_reg_from_load(s, rd, tmp);
9ee6e8bb
PB
9246 }
9247 break;
9248 case 0x08:
9249 case 0x09:
9250 {
da3e53dd
PM
9251 int j, n, loaded_base;
9252 bool exc_return = false;
9253 bool is_load = extract32(insn, 20, 1);
9254 bool user = false;
39d5492a 9255 TCGv_i32 loaded_var;
9ee6e8bb
PB
9256 /* load/store multiple words */
9257 /* XXX: store correct base if write back */
9ee6e8bb 9258 if (insn & (1 << 22)) {
da3e53dd 9259 /* LDM (user), LDM (exception return) and STM (user) */
9ee6e8bb
PB
9260 if (IS_USER(s))
9261 goto illegal_op; /* only usable in supervisor mode */
9262
da3e53dd
PM
9263 if (is_load && extract32(insn, 15, 1)) {
9264 exc_return = true;
9265 } else {
9266 user = true;
9267 }
9ee6e8bb
PB
9268 }
9269 rn = (insn >> 16) & 0xf;
b0109805 9270 addr = load_reg(s, rn);
9ee6e8bb
PB
9271
9272 /* compute total size */
9273 loaded_base = 0;
39d5492a 9274 TCGV_UNUSED_I32(loaded_var);
9ee6e8bb
PB
9275 n = 0;
9276 for(i=0;i<16;i++) {
9277 if (insn & (1 << i))
9278 n++;
9279 }
9280 /* XXX: test invalid n == 0 case ? */
9281 if (insn & (1 << 23)) {
9282 if (insn & (1 << 24)) {
9283 /* pre increment */
b0109805 9284 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9285 } else {
9286 /* post increment */
9287 }
9288 } else {
9289 if (insn & (1 << 24)) {
9290 /* pre decrement */
b0109805 9291 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
9292 } else {
9293 /* post decrement */
9294 if (n != 1)
b0109805 9295 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
9296 }
9297 }
9298 j = 0;
9299 for(i=0;i<16;i++) {
9300 if (insn & (1 << i)) {
da3e53dd 9301 if (is_load) {
9ee6e8bb 9302 /* load */
5a839c0d 9303 tmp = tcg_temp_new_i32();
12dcc321 9304 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
be5e7a76 9305 if (user) {
b75263d6 9306 tmp2 = tcg_const_i32(i);
1ce94f81 9307 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
b75263d6 9308 tcg_temp_free_i32(tmp2);
7d1b0095 9309 tcg_temp_free_i32(tmp);
9ee6e8bb 9310 } else if (i == rn) {
b0109805 9311 loaded_var = tmp;
9ee6e8bb 9312 loaded_base = 1;
fb0e8e79
PM
9313 } else if (rn == 15 && exc_return) {
9314 store_pc_exc_ret(s, tmp);
9ee6e8bb 9315 } else {
7dcc1f89 9316 store_reg_from_load(s, i, tmp);
9ee6e8bb
PB
9317 }
9318 } else {
9319 /* store */
9320 if (i == 15) {
9321 /* special case: r15 = PC + 8 */
9322 val = (long)s->pc + 4;
7d1b0095 9323 tmp = tcg_temp_new_i32();
b0109805 9324 tcg_gen_movi_i32(tmp, val);
9ee6e8bb 9325 } else if (user) {
7d1b0095 9326 tmp = tcg_temp_new_i32();
b75263d6 9327 tmp2 = tcg_const_i32(i);
9ef39277 9328 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
b75263d6 9329 tcg_temp_free_i32(tmp2);
9ee6e8bb 9330 } else {
b0109805 9331 tmp = load_reg(s, i);
9ee6e8bb 9332 }
12dcc321 9333 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 9334 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9335 }
9336 j++;
9337 /* no need to add after the last transfer */
9338 if (j != n)
b0109805 9339 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9340 }
9341 }
9342 if (insn & (1 << 21)) {
9343 /* write back */
9344 if (insn & (1 << 23)) {
9345 if (insn & (1 << 24)) {
9346 /* pre increment */
9347 } else {
9348 /* post increment */
b0109805 9349 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9350 }
9351 } else {
9352 if (insn & (1 << 24)) {
9353 /* pre decrement */
9354 if (n != 1)
b0109805 9355 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
9356 } else {
9357 /* post decrement */
b0109805 9358 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
9359 }
9360 }
b0109805
PB
9361 store_reg(s, rn, addr);
9362 } else {
7d1b0095 9363 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9364 }
9365 if (loaded_base) {
b0109805 9366 store_reg(s, rn, loaded_var);
9ee6e8bb 9367 }
da3e53dd 9368 if (exc_return) {
9ee6e8bb 9369 /* Restore CPSR from SPSR. */
d9ba4830 9370 tmp = load_cpu_field(spsr);
235ea1f5 9371 gen_helper_cpsr_write_eret(cpu_env, tmp);
7d1b0095 9372 tcg_temp_free_i32(tmp);
577bf808 9373 s->is_jmp = DISAS_JUMP;
9ee6e8bb
PB
9374 }
9375 }
9376 break;
9377 case 0xa:
9378 case 0xb:
9379 {
9380 int32_t offset;
9381
9382 /* branch (and link) */
9383 val = (int32_t)s->pc;
9384 if (insn & (1 << 24)) {
7d1b0095 9385 tmp = tcg_temp_new_i32();
5e3f878a
PB
9386 tcg_gen_movi_i32(tmp, val);
9387 store_reg(s, 14, tmp);
9ee6e8bb 9388 }
534df156
PM
9389 offset = sextract32(insn << 2, 0, 26);
9390 val += offset + 4;
9ee6e8bb
PB
9391 gen_jmp(s, val);
9392 }
9393 break;
9394 case 0xc:
9395 case 0xd:
9396 case 0xe:
6a57f3eb
WN
9397 if (((insn >> 8) & 0xe) == 10) {
9398 /* VFP. */
7dcc1f89 9399 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
9400 goto illegal_op;
9401 }
7dcc1f89 9402 } else if (disas_coproc_insn(s, insn)) {
6a57f3eb 9403 /* Coprocessor. */
9ee6e8bb 9404 goto illegal_op;
6a57f3eb 9405 }
9ee6e8bb
PB
9406 break;
9407 case 0xf:
9408 /* swi */
eaed129d 9409 gen_set_pc_im(s, s->pc);
d4a2dc67 9410 s->svc_imm = extract32(insn, 0, 24);
9ee6e8bb
PB
9411 s->is_jmp = DISAS_SWI;
9412 break;
9413 default:
9414 illegal_op:
73710361
GB
9415 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
9416 default_exception_el(s));
9ee6e8bb
PB
9417 break;
9418 }
9419 }
9420}
9421
9422/* Return true if this is a Thumb-2 logical op. */
9423static int
9424thumb2_logic_op(int op)
9425{
9426 return (op < 8);
9427}
9428
9429/* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
9430 then set condition code flags based on the result of the operation.
9431 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
9432 to the high bit of T1.
9433 Returns zero if the opcode is valid. */
9434
9435static int
39d5492a
PM
9436gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
9437 TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
9438{
9439 int logic_cc;
9440
9441 logic_cc = 0;
9442 switch (op) {
9443 case 0: /* and */
396e467c 9444 tcg_gen_and_i32(t0, t0, t1);
9ee6e8bb
PB
9445 logic_cc = conds;
9446 break;
9447 case 1: /* bic */
f669df27 9448 tcg_gen_andc_i32(t0, t0, t1);
9ee6e8bb
PB
9449 logic_cc = conds;
9450 break;
9451 case 2: /* orr */
396e467c 9452 tcg_gen_or_i32(t0, t0, t1);
9ee6e8bb
PB
9453 logic_cc = conds;
9454 break;
9455 case 3: /* orn */
29501f1b 9456 tcg_gen_orc_i32(t0, t0, t1);
9ee6e8bb
PB
9457 logic_cc = conds;
9458 break;
9459 case 4: /* eor */
396e467c 9460 tcg_gen_xor_i32(t0, t0, t1);
9ee6e8bb
PB
9461 logic_cc = conds;
9462 break;
9463 case 8: /* add */
9464 if (conds)
72485ec4 9465 gen_add_CC(t0, t0, t1);
9ee6e8bb 9466 else
396e467c 9467 tcg_gen_add_i32(t0, t0, t1);
9ee6e8bb
PB
9468 break;
9469 case 10: /* adc */
9470 if (conds)
49b4c31e 9471 gen_adc_CC(t0, t0, t1);
9ee6e8bb 9472 else
396e467c 9473 gen_adc(t0, t1);
9ee6e8bb
PB
9474 break;
9475 case 11: /* sbc */
2de68a49
RH
9476 if (conds) {
9477 gen_sbc_CC(t0, t0, t1);
9478 } else {
396e467c 9479 gen_sub_carry(t0, t0, t1);
2de68a49 9480 }
9ee6e8bb
PB
9481 break;
9482 case 13: /* sub */
9483 if (conds)
72485ec4 9484 gen_sub_CC(t0, t0, t1);
9ee6e8bb 9485 else
396e467c 9486 tcg_gen_sub_i32(t0, t0, t1);
9ee6e8bb
PB
9487 break;
9488 case 14: /* rsb */
9489 if (conds)
72485ec4 9490 gen_sub_CC(t0, t1, t0);
9ee6e8bb 9491 else
396e467c 9492 tcg_gen_sub_i32(t0, t1, t0);
9ee6e8bb
PB
9493 break;
9494 default: /* 5, 6, 7, 9, 12, 15. */
9495 return 1;
9496 }
9497 if (logic_cc) {
396e467c 9498 gen_logic_CC(t0);
9ee6e8bb 9499 if (shifter_out)
396e467c 9500 gen_set_CF_bit31(t1);
9ee6e8bb
PB
9501 }
9502 return 0;
9503}
9504
9505/* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
9506 is not legal. */
0ecb72a5 9507static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
9ee6e8bb 9508{
b0109805 9509 uint32_t insn, imm, shift, offset;
9ee6e8bb 9510 uint32_t rd, rn, rm, rs;
39d5492a
PM
9511 TCGv_i32 tmp;
9512 TCGv_i32 tmp2;
9513 TCGv_i32 tmp3;
9514 TCGv_i32 addr;
a7812ae4 9515 TCGv_i64 tmp64;
9ee6e8bb
PB
9516 int op;
9517 int shiftop;
9518 int conds;
9519 int logic_cc;
9520
d614a513
PM
9521 if (!(arm_dc_feature(s, ARM_FEATURE_THUMB2)
9522 || arm_dc_feature(s, ARM_FEATURE_M))) {
601d70b9 9523 /* Thumb-1 cores may need to treat bl and blx as a pair of
9ee6e8bb
PB
9524 16-bit instructions to get correct prefetch abort behavior. */
9525 insn = insn_hw1;
9526 if ((insn & (1 << 12)) == 0) {
be5e7a76 9527 ARCH(5);
9ee6e8bb
PB
9528 /* Second half of blx. */
9529 offset = ((insn & 0x7ff) << 1);
d9ba4830
PB
9530 tmp = load_reg(s, 14);
9531 tcg_gen_addi_i32(tmp, tmp, offset);
9532 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
9ee6e8bb 9533
7d1b0095 9534 tmp2 = tcg_temp_new_i32();
b0109805 9535 tcg_gen_movi_i32(tmp2, s->pc | 1);
d9ba4830
PB
9536 store_reg(s, 14, tmp2);
9537 gen_bx(s, tmp);
9ee6e8bb
PB
9538 return 0;
9539 }
9540 if (insn & (1 << 11)) {
9541 /* Second half of bl. */
9542 offset = ((insn & 0x7ff) << 1) | 1;
d9ba4830 9543 tmp = load_reg(s, 14);
6a0d8a1d 9544 tcg_gen_addi_i32(tmp, tmp, offset);
9ee6e8bb 9545
7d1b0095 9546 tmp2 = tcg_temp_new_i32();
b0109805 9547 tcg_gen_movi_i32(tmp2, s->pc | 1);
d9ba4830
PB
9548 store_reg(s, 14, tmp2);
9549 gen_bx(s, tmp);
9ee6e8bb
PB
9550 return 0;
9551 }
9552 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
9553 /* Instruction spans a page boundary. Implement it as two
9554 16-bit instructions in case the second half causes an
9555 prefetch abort. */
9556 offset = ((int32_t)insn << 21) >> 9;
396e467c 9557 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
9ee6e8bb
PB
9558 return 0;
9559 }
9560 /* Fall through to 32-bit decode. */
9561 }
9562
f9fd40eb 9563 insn = arm_lduw_code(env, s->pc, s->sctlr_b);
9ee6e8bb
PB
9564 s->pc += 2;
9565 insn |= (uint32_t)insn_hw1 << 16;
9566
9567 if ((insn & 0xf800e800) != 0xf000e800) {
9568 ARCH(6T2);
9569 }
9570
9571 rn = (insn >> 16) & 0xf;
9572 rs = (insn >> 12) & 0xf;
9573 rd = (insn >> 8) & 0xf;
9574 rm = insn & 0xf;
9575 switch ((insn >> 25) & 0xf) {
9576 case 0: case 1: case 2: case 3:
9577 /* 16-bit instructions. Should never happen. */
9578 abort();
9579 case 4:
9580 if (insn & (1 << 22)) {
9581 /* Other load/store, table branch. */
9582 if (insn & 0x01200000) {
9583 /* Load/store doubleword. */
9584 if (rn == 15) {
7d1b0095 9585 addr = tcg_temp_new_i32();
b0109805 9586 tcg_gen_movi_i32(addr, s->pc & ~3);
9ee6e8bb 9587 } else {
b0109805 9588 addr = load_reg(s, rn);
9ee6e8bb
PB
9589 }
9590 offset = (insn & 0xff) * 4;
9591 if ((insn & (1 << 23)) == 0)
9592 offset = -offset;
9593 if (insn & (1 << 24)) {
b0109805 9594 tcg_gen_addi_i32(addr, addr, offset);
9ee6e8bb
PB
9595 offset = 0;
9596 }
9597 if (insn & (1 << 20)) {
9598 /* ldrd */
e2592fad 9599 tmp = tcg_temp_new_i32();
12dcc321 9600 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805
PB
9601 store_reg(s, rs, tmp);
9602 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 9603 tmp = tcg_temp_new_i32();
12dcc321 9604 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 9605 store_reg(s, rd, tmp);
9ee6e8bb
PB
9606 } else {
9607 /* strd */
b0109805 9608 tmp = load_reg(s, rs);
12dcc321 9609 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 9610 tcg_temp_free_i32(tmp);
b0109805
PB
9611 tcg_gen_addi_i32(addr, addr, 4);
9612 tmp = load_reg(s, rd);
12dcc321 9613 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 9614 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9615 }
9616 if (insn & (1 << 21)) {
9617 /* Base writeback. */
9618 if (rn == 15)
9619 goto illegal_op;
b0109805
PB
9620 tcg_gen_addi_i32(addr, addr, offset - 4);
9621 store_reg(s, rn, addr);
9622 } else {
7d1b0095 9623 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9624 }
9625 } else if ((insn & (1 << 23)) == 0) {
9626 /* Load/store exclusive word. */
39d5492a 9627 addr = tcg_temp_local_new_i32();
98a46317 9628 load_reg_var(s, addr, rn);
426f5abc 9629 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
2c0262af 9630 if (insn & (1 << 20)) {
426f5abc 9631 gen_load_exclusive(s, rs, 15, addr, 2);
9ee6e8bb 9632 } else {
426f5abc 9633 gen_store_exclusive(s, rd, rs, 15, addr, 2);
9ee6e8bb 9634 }
39d5492a 9635 tcg_temp_free_i32(addr);
2359bf80 9636 } else if ((insn & (7 << 5)) == 0) {
9ee6e8bb
PB
9637 /* Table Branch. */
9638 if (rn == 15) {
7d1b0095 9639 addr = tcg_temp_new_i32();
b0109805 9640 tcg_gen_movi_i32(addr, s->pc);
9ee6e8bb 9641 } else {
b0109805 9642 addr = load_reg(s, rn);
9ee6e8bb 9643 }
b26eefb6 9644 tmp = load_reg(s, rm);
b0109805 9645 tcg_gen_add_i32(addr, addr, tmp);
9ee6e8bb
PB
9646 if (insn & (1 << 4)) {
9647 /* tbh */
b0109805 9648 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 9649 tcg_temp_free_i32(tmp);
e2592fad 9650 tmp = tcg_temp_new_i32();
12dcc321 9651 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9652 } else { /* tbb */
7d1b0095 9653 tcg_temp_free_i32(tmp);
e2592fad 9654 tmp = tcg_temp_new_i32();
12dcc321 9655 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9656 }
7d1b0095 9657 tcg_temp_free_i32(addr);
b0109805
PB
9658 tcg_gen_shli_i32(tmp, tmp, 1);
9659 tcg_gen_addi_i32(tmp, tmp, s->pc);
9660 store_reg(s, 15, tmp);
9ee6e8bb 9661 } else {
2359bf80 9662 int op2 = (insn >> 6) & 0x3;
9ee6e8bb 9663 op = (insn >> 4) & 0x3;
2359bf80
MR
9664 switch (op2) {
9665 case 0:
426f5abc 9666 goto illegal_op;
2359bf80
MR
9667 case 1:
9668 /* Load/store exclusive byte/halfword/doubleword */
9669 if (op == 2) {
9670 goto illegal_op;
9671 }
9672 ARCH(7);
9673 break;
9674 case 2:
9675 /* Load-acquire/store-release */
9676 if (op == 3) {
9677 goto illegal_op;
9678 }
9679 /* Fall through */
9680 case 3:
9681 /* Load-acquire/store-release exclusive */
9682 ARCH(8);
9683 break;
426f5abc 9684 }
39d5492a 9685 addr = tcg_temp_local_new_i32();
98a46317 9686 load_reg_var(s, addr, rn);
2359bf80
MR
9687 if (!(op2 & 1)) {
9688 if (insn & (1 << 20)) {
9689 tmp = tcg_temp_new_i32();
9690 switch (op) {
9691 case 0: /* ldab */
12dcc321 9692 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
2359bf80
MR
9693 break;
9694 case 1: /* ldah */
12dcc321 9695 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
2359bf80
MR
9696 break;
9697 case 2: /* lda */
12dcc321 9698 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
2359bf80
MR
9699 break;
9700 default:
9701 abort();
9702 }
9703 store_reg(s, rs, tmp);
9704 } else {
9705 tmp = load_reg(s, rs);
9706 switch (op) {
9707 case 0: /* stlb */
12dcc321 9708 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
2359bf80
MR
9709 break;
9710 case 1: /* stlh */
12dcc321 9711 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
2359bf80
MR
9712 break;
9713 case 2: /* stl */
12dcc321 9714 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
2359bf80
MR
9715 break;
9716 default:
9717 abort();
9718 }
9719 tcg_temp_free_i32(tmp);
9720 }
9721 } else if (insn & (1 << 20)) {
426f5abc 9722 gen_load_exclusive(s, rs, rd, addr, op);
9ee6e8bb 9723 } else {
426f5abc 9724 gen_store_exclusive(s, rm, rs, rd, addr, op);
9ee6e8bb 9725 }
39d5492a 9726 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9727 }
9728 } else {
9729 /* Load/store multiple, RFE, SRS. */
9730 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
00115976 9731 /* RFE, SRS: not available in user mode or on M profile */
b53d8923 9732 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 9733 goto illegal_op;
00115976 9734 }
9ee6e8bb
PB
9735 if (insn & (1 << 20)) {
9736 /* rfe */
b0109805
PB
9737 addr = load_reg(s, rn);
9738 if ((insn & (1 << 24)) == 0)
9739 tcg_gen_addi_i32(addr, addr, -8);
9740 /* Load PC into tmp and CPSR into tmp2. */
e2592fad 9741 tmp = tcg_temp_new_i32();
12dcc321 9742 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 9743 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 9744 tmp2 = tcg_temp_new_i32();
12dcc321 9745 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
9746 if (insn & (1 << 21)) {
9747 /* Base writeback. */
b0109805
PB
9748 if (insn & (1 << 24)) {
9749 tcg_gen_addi_i32(addr, addr, 4);
9750 } else {
9751 tcg_gen_addi_i32(addr, addr, -4);
9752 }
9753 store_reg(s, rn, addr);
9754 } else {
7d1b0095 9755 tcg_temp_free_i32(addr);
9ee6e8bb 9756 }
b0109805 9757 gen_rfe(s, tmp, tmp2);
9ee6e8bb
PB
9758 } else {
9759 /* srs */
81465888
PM
9760 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
9761 insn & (1 << 21));
9ee6e8bb
PB
9762 }
9763 } else {
5856d44e 9764 int i, loaded_base = 0;
39d5492a 9765 TCGv_i32 loaded_var;
9ee6e8bb 9766 /* Load/store multiple. */
b0109805 9767 addr = load_reg(s, rn);
9ee6e8bb
PB
9768 offset = 0;
9769 for (i = 0; i < 16; i++) {
9770 if (insn & (1 << i))
9771 offset += 4;
9772 }
9773 if (insn & (1 << 24)) {
b0109805 9774 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
9775 }
9776
39d5492a 9777 TCGV_UNUSED_I32(loaded_var);
9ee6e8bb
PB
9778 for (i = 0; i < 16; i++) {
9779 if ((insn & (1 << i)) == 0)
9780 continue;
9781 if (insn & (1 << 20)) {
9782 /* Load. */
e2592fad 9783 tmp = tcg_temp_new_i32();
12dcc321 9784 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9785 if (i == 15) {
b0109805 9786 gen_bx(s, tmp);
5856d44e
YO
9787 } else if (i == rn) {
9788 loaded_var = tmp;
9789 loaded_base = 1;
9ee6e8bb 9790 } else {
b0109805 9791 store_reg(s, i, tmp);
9ee6e8bb
PB
9792 }
9793 } else {
9794 /* Store. */
b0109805 9795 tmp = load_reg(s, i);
12dcc321 9796 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 9797 tcg_temp_free_i32(tmp);
9ee6e8bb 9798 }
b0109805 9799 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb 9800 }
5856d44e
YO
9801 if (loaded_base) {
9802 store_reg(s, rn, loaded_var);
9803 }
9ee6e8bb
PB
9804 if (insn & (1 << 21)) {
9805 /* Base register writeback. */
9806 if (insn & (1 << 24)) {
b0109805 9807 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
9808 }
9809 /* Fault if writeback register is in register list. */
9810 if (insn & (1 << rn))
9811 goto illegal_op;
b0109805
PB
9812 store_reg(s, rn, addr);
9813 } else {
7d1b0095 9814 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9815 }
9816 }
9817 }
9818 break;
2af9ab77
JB
9819 case 5:
9820
9ee6e8bb 9821 op = (insn >> 21) & 0xf;
2af9ab77 9822 if (op == 6) {
62b44f05
AR
9823 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9824 goto illegal_op;
9825 }
2af9ab77
JB
9826 /* Halfword pack. */
9827 tmp = load_reg(s, rn);
9828 tmp2 = load_reg(s, rm);
9829 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
9830 if (insn & (1 << 5)) {
9831 /* pkhtb */
9832 if (shift == 0)
9833 shift = 31;
9834 tcg_gen_sari_i32(tmp2, tmp2, shift);
9835 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
9836 tcg_gen_ext16u_i32(tmp2, tmp2);
9837 } else {
9838 /* pkhbt */
9839 if (shift)
9840 tcg_gen_shli_i32(tmp2, tmp2, shift);
9841 tcg_gen_ext16u_i32(tmp, tmp);
9842 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9843 }
9844 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 9845 tcg_temp_free_i32(tmp2);
3174f8e9
FN
9846 store_reg(s, rd, tmp);
9847 } else {
2af9ab77
JB
9848 /* Data processing register constant shift. */
9849 if (rn == 15) {
7d1b0095 9850 tmp = tcg_temp_new_i32();
2af9ab77
JB
9851 tcg_gen_movi_i32(tmp, 0);
9852 } else {
9853 tmp = load_reg(s, rn);
9854 }
9855 tmp2 = load_reg(s, rm);
9856
9857 shiftop = (insn >> 4) & 3;
9858 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9859 conds = (insn & (1 << 20)) != 0;
9860 logic_cc = (conds && thumb2_logic_op(op));
9861 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9862 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
9863 goto illegal_op;
7d1b0095 9864 tcg_temp_free_i32(tmp2);
2af9ab77
JB
9865 if (rd != 15) {
9866 store_reg(s, rd, tmp);
9867 } else {
7d1b0095 9868 tcg_temp_free_i32(tmp);
2af9ab77 9869 }
3174f8e9 9870 }
9ee6e8bb
PB
9871 break;
9872 case 13: /* Misc data processing. */
9873 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
9874 if (op < 4 && (insn & 0xf000) != 0xf000)
9875 goto illegal_op;
9876 switch (op) {
9877 case 0: /* Register controlled shift. */
8984bd2e
PB
9878 tmp = load_reg(s, rn);
9879 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
9880 if ((insn & 0x70) != 0)
9881 goto illegal_op;
9882 op = (insn >> 21) & 3;
8984bd2e
PB
9883 logic_cc = (insn & (1 << 20)) != 0;
9884 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
9885 if (logic_cc)
9886 gen_logic_CC(tmp);
7dcc1f89 9887 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9888 break;
9889 case 1: /* Sign/zero extend. */
62b44f05
AR
9890 op = (insn >> 20) & 7;
9891 switch (op) {
9892 case 0: /* SXTAH, SXTH */
9893 case 1: /* UXTAH, UXTH */
9894 case 4: /* SXTAB, SXTB */
9895 case 5: /* UXTAB, UXTB */
9896 break;
9897 case 2: /* SXTAB16, SXTB16 */
9898 case 3: /* UXTAB16, UXTB16 */
9899 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9900 goto illegal_op;
9901 }
9902 break;
9903 default:
9904 goto illegal_op;
9905 }
9906 if (rn != 15) {
9907 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9908 goto illegal_op;
9909 }
9910 }
5e3f878a 9911 tmp = load_reg(s, rm);
9ee6e8bb 9912 shift = (insn >> 4) & 3;
1301f322 9913 /* ??? In many cases it's not necessary to do a
9ee6e8bb
PB
9914 rotate, a shift is sufficient. */
9915 if (shift != 0)
f669df27 9916 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
9917 op = (insn >> 20) & 7;
9918 switch (op) {
5e3f878a
PB
9919 case 0: gen_sxth(tmp); break;
9920 case 1: gen_uxth(tmp); break;
9921 case 2: gen_sxtb16(tmp); break;
9922 case 3: gen_uxtb16(tmp); break;
9923 case 4: gen_sxtb(tmp); break;
9924 case 5: gen_uxtb(tmp); break;
62b44f05
AR
9925 default:
9926 g_assert_not_reached();
9ee6e8bb
PB
9927 }
9928 if (rn != 15) {
5e3f878a 9929 tmp2 = load_reg(s, rn);
9ee6e8bb 9930 if ((op >> 1) == 1) {
5e3f878a 9931 gen_add16(tmp, tmp2);
9ee6e8bb 9932 } else {
5e3f878a 9933 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9934 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9935 }
9936 }
5e3f878a 9937 store_reg(s, rd, tmp);
9ee6e8bb
PB
9938 break;
9939 case 2: /* SIMD add/subtract. */
62b44f05
AR
9940 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9941 goto illegal_op;
9942 }
9ee6e8bb
PB
9943 op = (insn >> 20) & 7;
9944 shift = (insn >> 4) & 7;
9945 if ((op & 3) == 3 || (shift & 3) == 3)
9946 goto illegal_op;
6ddbc6e4
PB
9947 tmp = load_reg(s, rn);
9948 tmp2 = load_reg(s, rm);
9949 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7d1b0095 9950 tcg_temp_free_i32(tmp2);
6ddbc6e4 9951 store_reg(s, rd, tmp);
9ee6e8bb
PB
9952 break;
9953 case 3: /* Other data processing. */
9954 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
9955 if (op < 4) {
9956 /* Saturating add/subtract. */
62b44f05
AR
9957 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9958 goto illegal_op;
9959 }
d9ba4830
PB
9960 tmp = load_reg(s, rn);
9961 tmp2 = load_reg(s, rm);
9ee6e8bb 9962 if (op & 1)
9ef39277 9963 gen_helper_double_saturate(tmp, cpu_env, tmp);
4809c612 9964 if (op & 2)
9ef39277 9965 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9ee6e8bb 9966 else
9ef39277 9967 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 9968 tcg_temp_free_i32(tmp2);
9ee6e8bb 9969 } else {
62b44f05
AR
9970 switch (op) {
9971 case 0x0a: /* rbit */
9972 case 0x08: /* rev */
9973 case 0x09: /* rev16 */
9974 case 0x0b: /* revsh */
9975 case 0x18: /* clz */
9976 break;
9977 case 0x10: /* sel */
9978 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9979 goto illegal_op;
9980 }
9981 break;
9982 case 0x20: /* crc32/crc32c */
9983 case 0x21:
9984 case 0x22:
9985 case 0x28:
9986 case 0x29:
9987 case 0x2a:
9988 if (!arm_dc_feature(s, ARM_FEATURE_CRC)) {
9989 goto illegal_op;
9990 }
9991 break;
9992 default:
9993 goto illegal_op;
9994 }
d9ba4830 9995 tmp = load_reg(s, rn);
9ee6e8bb
PB
9996 switch (op) {
9997 case 0x0a: /* rbit */
d9ba4830 9998 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
9999 break;
10000 case 0x08: /* rev */
66896cb8 10001 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb
PB
10002 break;
10003 case 0x09: /* rev16 */
d9ba4830 10004 gen_rev16(tmp);
9ee6e8bb
PB
10005 break;
10006 case 0x0b: /* revsh */
d9ba4830 10007 gen_revsh(tmp);
9ee6e8bb
PB
10008 break;
10009 case 0x10: /* sel */
d9ba4830 10010 tmp2 = load_reg(s, rm);
7d1b0095 10011 tmp3 = tcg_temp_new_i32();
0ecb72a5 10012 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
d9ba4830 10013 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
10014 tcg_temp_free_i32(tmp3);
10015 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10016 break;
10017 case 0x18: /* clz */
d9ba4830 10018 gen_helper_clz(tmp, tmp);
9ee6e8bb 10019 break;
eb0ecd5a
WN
10020 case 0x20:
10021 case 0x21:
10022 case 0x22:
10023 case 0x28:
10024 case 0x29:
10025 case 0x2a:
10026 {
10027 /* crc32/crc32c */
10028 uint32_t sz = op & 0x3;
10029 uint32_t c = op & 0x8;
10030
eb0ecd5a 10031 tmp2 = load_reg(s, rm);
aa633469
PM
10032 if (sz == 0) {
10033 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
10034 } else if (sz == 1) {
10035 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
10036 }
eb0ecd5a
WN
10037 tmp3 = tcg_const_i32(1 << sz);
10038 if (c) {
10039 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
10040 } else {
10041 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
10042 }
10043 tcg_temp_free_i32(tmp2);
10044 tcg_temp_free_i32(tmp3);
10045 break;
10046 }
9ee6e8bb 10047 default:
62b44f05 10048 g_assert_not_reached();
9ee6e8bb
PB
10049 }
10050 }
d9ba4830 10051 store_reg(s, rd, tmp);
9ee6e8bb
PB
10052 break;
10053 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
62b44f05
AR
10054 switch ((insn >> 20) & 7) {
10055 case 0: /* 32 x 32 -> 32 */
10056 case 7: /* Unsigned sum of absolute differences. */
10057 break;
10058 case 1: /* 16 x 16 -> 32 */
10059 case 2: /* Dual multiply add. */
10060 case 3: /* 32 * 16 -> 32msb */
10061 case 4: /* Dual multiply subtract. */
10062 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10063 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10064 goto illegal_op;
10065 }
10066 break;
10067 }
9ee6e8bb 10068 op = (insn >> 4) & 0xf;
d9ba4830
PB
10069 tmp = load_reg(s, rn);
10070 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
10071 switch ((insn >> 20) & 7) {
10072 case 0: /* 32 x 32 -> 32 */
d9ba4830 10073 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 10074 tcg_temp_free_i32(tmp2);
9ee6e8bb 10075 if (rs != 15) {
d9ba4830 10076 tmp2 = load_reg(s, rs);
9ee6e8bb 10077 if (op)
d9ba4830 10078 tcg_gen_sub_i32(tmp, tmp2, tmp);
9ee6e8bb 10079 else
d9ba4830 10080 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10081 tcg_temp_free_i32(tmp2);
9ee6e8bb 10082 }
9ee6e8bb
PB
10083 break;
10084 case 1: /* 16 x 16 -> 32 */
d9ba4830 10085 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 10086 tcg_temp_free_i32(tmp2);
9ee6e8bb 10087 if (rs != 15) {
d9ba4830 10088 tmp2 = load_reg(s, rs);
9ef39277 10089 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10090 tcg_temp_free_i32(tmp2);
9ee6e8bb 10091 }
9ee6e8bb
PB
10092 break;
10093 case 2: /* Dual multiply add. */
10094 case 4: /* Dual multiply subtract. */
10095 if (op)
d9ba4830
PB
10096 gen_swap_half(tmp2);
10097 gen_smul_dual(tmp, tmp2);
9ee6e8bb 10098 if (insn & (1 << 22)) {
e1d177b9 10099 /* This subtraction cannot overflow. */
d9ba4830 10100 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 10101 } else {
e1d177b9
PM
10102 /* This addition cannot overflow 32 bits;
10103 * however it may overflow considered as a signed
10104 * operation, in which case we must set the Q flag.
10105 */
9ef39277 10106 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 10107 }
7d1b0095 10108 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10109 if (rs != 15)
10110 {
d9ba4830 10111 tmp2 = load_reg(s, rs);
9ef39277 10112 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10113 tcg_temp_free_i32(tmp2);
9ee6e8bb 10114 }
9ee6e8bb
PB
10115 break;
10116 case 3: /* 32 * 16 -> 32msb */
10117 if (op)
d9ba4830 10118 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 10119 else
d9ba4830 10120 gen_sxth(tmp2);
a7812ae4
PB
10121 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10122 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 10123 tmp = tcg_temp_new_i32();
ecc7b3aa 10124 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 10125 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
10126 if (rs != 15)
10127 {
d9ba4830 10128 tmp2 = load_reg(s, rs);
9ef39277 10129 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10130 tcg_temp_free_i32(tmp2);
9ee6e8bb 10131 }
9ee6e8bb 10132 break;
838fa72d
AJ
10133 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10134 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 10135 if (rs != 15) {
838fa72d
AJ
10136 tmp = load_reg(s, rs);
10137 if (insn & (1 << 20)) {
10138 tmp64 = gen_addq_msw(tmp64, tmp);
99c475ab 10139 } else {
838fa72d 10140 tmp64 = gen_subq_msw(tmp64, tmp);
99c475ab 10141 }
2c0262af 10142 }
838fa72d
AJ
10143 if (insn & (1 << 4)) {
10144 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
10145 }
10146 tcg_gen_shri_i64(tmp64, tmp64, 32);
7d1b0095 10147 tmp = tcg_temp_new_i32();
ecc7b3aa 10148 tcg_gen_extrl_i64_i32(tmp, tmp64);
838fa72d 10149 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
10150 break;
10151 case 7: /* Unsigned sum of absolute differences. */
d9ba4830 10152 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 10153 tcg_temp_free_i32(tmp2);
9ee6e8bb 10154 if (rs != 15) {
d9ba4830
PB
10155 tmp2 = load_reg(s, rs);
10156 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10157 tcg_temp_free_i32(tmp2);
5fd46862 10158 }
9ee6e8bb 10159 break;
2c0262af 10160 }
d9ba4830 10161 store_reg(s, rd, tmp);
2c0262af 10162 break;
9ee6e8bb
PB
10163 case 6: case 7: /* 64-bit multiply, Divide. */
10164 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
5e3f878a
PB
10165 tmp = load_reg(s, rn);
10166 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
10167 if ((op & 0x50) == 0x10) {
10168 /* sdiv, udiv */
d614a513 10169 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DIV)) {
9ee6e8bb 10170 goto illegal_op;
47789990 10171 }
9ee6e8bb 10172 if (op & 0x20)
5e3f878a 10173 gen_helper_udiv(tmp, tmp, tmp2);
2c0262af 10174 else
5e3f878a 10175 gen_helper_sdiv(tmp, tmp, tmp2);
7d1b0095 10176 tcg_temp_free_i32(tmp2);
5e3f878a 10177 store_reg(s, rd, tmp);
9ee6e8bb
PB
10178 } else if ((op & 0xe) == 0xc) {
10179 /* Dual multiply accumulate long. */
62b44f05
AR
10180 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10181 tcg_temp_free_i32(tmp);
10182 tcg_temp_free_i32(tmp2);
10183 goto illegal_op;
10184 }
9ee6e8bb 10185 if (op & 1)
5e3f878a
PB
10186 gen_swap_half(tmp2);
10187 gen_smul_dual(tmp, tmp2);
9ee6e8bb 10188 if (op & 0x10) {
5e3f878a 10189 tcg_gen_sub_i32(tmp, tmp, tmp2);
b5ff1b31 10190 } else {
5e3f878a 10191 tcg_gen_add_i32(tmp, tmp, tmp2);
b5ff1b31 10192 }
7d1b0095 10193 tcg_temp_free_i32(tmp2);
a7812ae4
PB
10194 /* BUGFIX */
10195 tmp64 = tcg_temp_new_i64();
10196 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 10197 tcg_temp_free_i32(tmp);
a7812ae4
PB
10198 gen_addq(s, tmp64, rs, rd);
10199 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 10200 tcg_temp_free_i64(tmp64);
2c0262af 10201 } else {
9ee6e8bb
PB
10202 if (op & 0x20) {
10203 /* Unsigned 64-bit multiply */
a7812ae4 10204 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
b5ff1b31 10205 } else {
9ee6e8bb
PB
10206 if (op & 8) {
10207 /* smlalxy */
62b44f05
AR
10208 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10209 tcg_temp_free_i32(tmp2);
10210 tcg_temp_free_i32(tmp);
10211 goto illegal_op;
10212 }
5e3f878a 10213 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 10214 tcg_temp_free_i32(tmp2);
a7812ae4
PB
10215 tmp64 = tcg_temp_new_i64();
10216 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 10217 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10218 } else {
10219 /* Signed 64-bit multiply */
a7812ae4 10220 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 10221 }
b5ff1b31 10222 }
9ee6e8bb
PB
10223 if (op & 4) {
10224 /* umaal */
62b44f05
AR
10225 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10226 tcg_temp_free_i64(tmp64);
10227 goto illegal_op;
10228 }
a7812ae4
PB
10229 gen_addq_lo(s, tmp64, rs);
10230 gen_addq_lo(s, tmp64, rd);
9ee6e8bb
PB
10231 } else if (op & 0x40) {
10232 /* 64-bit accumulate. */
a7812ae4 10233 gen_addq(s, tmp64, rs, rd);
9ee6e8bb 10234 }
a7812ae4 10235 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 10236 tcg_temp_free_i64(tmp64);
5fd46862 10237 }
2c0262af 10238 break;
9ee6e8bb
PB
10239 }
10240 break;
10241 case 6: case 7: case 14: case 15:
10242 /* Coprocessor. */
10243 if (((insn >> 24) & 3) == 3) {
10244 /* Translate into the equivalent ARM encoding. */
f06053e3 10245 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
7dcc1f89 10246 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 10247 goto illegal_op;
7dcc1f89 10248 }
6a57f3eb 10249 } else if (((insn >> 8) & 0xe) == 10) {
7dcc1f89 10250 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
10251 goto illegal_op;
10252 }
9ee6e8bb
PB
10253 } else {
10254 if (insn & (1 << 28))
10255 goto illegal_op;
7dcc1f89 10256 if (disas_coproc_insn(s, insn)) {
9ee6e8bb 10257 goto illegal_op;
7dcc1f89 10258 }
9ee6e8bb
PB
10259 }
10260 break;
10261 case 8: case 9: case 10: case 11:
10262 if (insn & (1 << 15)) {
10263 /* Branches, misc control. */
10264 if (insn & 0x5000) {
10265 /* Unconditional branch. */
10266 /* signextend(hw1[10:0]) -> offset[:12]. */
10267 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
10268 /* hw1[10:0] -> offset[11:1]. */
10269 offset |= (insn & 0x7ff) << 1;
10270 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
10271 offset[24:22] already have the same value because of the
10272 sign extension above. */
10273 offset ^= ((~insn) & (1 << 13)) << 10;
10274 offset ^= ((~insn) & (1 << 11)) << 11;
10275
9ee6e8bb
PB
10276 if (insn & (1 << 14)) {
10277 /* Branch and link. */
3174f8e9 10278 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
b5ff1b31 10279 }
3b46e624 10280
b0109805 10281 offset += s->pc;
9ee6e8bb
PB
10282 if (insn & (1 << 12)) {
10283 /* b/bl */
b0109805 10284 gen_jmp(s, offset);
9ee6e8bb
PB
10285 } else {
10286 /* blx */
b0109805 10287 offset &= ~(uint32_t)2;
be5e7a76 10288 /* thumb2 bx, no need to check */
b0109805 10289 gen_bx_im(s, offset);
2c0262af 10290 }
9ee6e8bb
PB
10291 } else if (((insn >> 23) & 7) == 7) {
10292 /* Misc control */
10293 if (insn & (1 << 13))
10294 goto illegal_op;
10295
10296 if (insn & (1 << 26)) {
37e6456e
PM
10297 if (!(insn & (1 << 20))) {
10298 /* Hypervisor call (v7) */
10299 int imm16 = extract32(insn, 16, 4) << 12
10300 | extract32(insn, 0, 12);
10301 ARCH(7);
10302 if (IS_USER(s)) {
10303 goto illegal_op;
10304 }
10305 gen_hvc(s, imm16);
10306 } else {
10307 /* Secure monitor call (v6+) */
10308 ARCH(6K);
10309 if (IS_USER(s)) {
10310 goto illegal_op;
10311 }
10312 gen_smc(s);
10313 }
2c0262af 10314 } else {
9ee6e8bb
PB
10315 op = (insn >> 20) & 7;
10316 switch (op) {
10317 case 0: /* msr cpsr. */
b53d8923 10318 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e
PB
10319 tmp = load_reg(s, rn);
10320 addr = tcg_const_i32(insn & 0xff);
10321 gen_helper_v7m_msr(cpu_env, addr, tmp);
b75263d6 10322 tcg_temp_free_i32(addr);
7d1b0095 10323 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10324 gen_lookup_tb(s);
10325 break;
10326 }
10327 /* fall through */
10328 case 1: /* msr spsr. */
b53d8923 10329 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10330 goto illegal_op;
b53d8923 10331 }
8bfd0550
PM
10332
10333 if (extract32(insn, 5, 1)) {
10334 /* MSR (banked) */
10335 int sysm = extract32(insn, 8, 4) |
10336 (extract32(insn, 4, 1) << 4);
10337 int r = op & 1;
10338
10339 gen_msr_banked(s, r, sysm, rm);
10340 break;
10341 }
10342
10343 /* MSR (for PSRs) */
2fbac54b
FN
10344 tmp = load_reg(s, rn);
10345 if (gen_set_psr(s,
7dcc1f89 10346 msr_mask(s, (insn >> 8) & 0xf, op == 1),
2fbac54b 10347 op == 1, tmp))
9ee6e8bb
PB
10348 goto illegal_op;
10349 break;
10350 case 2: /* cps, nop-hint. */
10351 if (((insn >> 8) & 7) == 0) {
10352 gen_nop_hint(s, insn & 0xff);
10353 }
10354 /* Implemented as NOP in user mode. */
10355 if (IS_USER(s))
10356 break;
10357 offset = 0;
10358 imm = 0;
10359 if (insn & (1 << 10)) {
10360 if (insn & (1 << 7))
10361 offset |= CPSR_A;
10362 if (insn & (1 << 6))
10363 offset |= CPSR_I;
10364 if (insn & (1 << 5))
10365 offset |= CPSR_F;
10366 if (insn & (1 << 9))
10367 imm = CPSR_A | CPSR_I | CPSR_F;
10368 }
10369 if (insn & (1 << 8)) {
10370 offset |= 0x1f;
10371 imm |= (insn & 0x1f);
10372 }
10373 if (offset) {
2fbac54b 10374 gen_set_psr_im(s, offset, 0, imm);
9ee6e8bb
PB
10375 }
10376 break;
10377 case 3: /* Special control operations. */
426f5abc 10378 ARCH(7);
9ee6e8bb
PB
10379 op = (insn >> 4) & 0xf;
10380 switch (op) {
10381 case 2: /* clrex */
426f5abc 10382 gen_clrex(s);
9ee6e8bb
PB
10383 break;
10384 case 4: /* dsb */
10385 case 5: /* dmb */
61e4c432 10386 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9ee6e8bb 10387 break;
6df99dec
SS
10388 case 6: /* isb */
10389 /* We need to break the TB after this insn
10390 * to execute self-modifying code correctly
10391 * and also to take any pending interrupts
10392 * immediately.
10393 */
10394 gen_lookup_tb(s);
10395 break;
9ee6e8bb
PB
10396 default:
10397 goto illegal_op;
10398 }
10399 break;
10400 case 4: /* bxj */
10401 /* Trivial implementation equivalent to bx. */
d9ba4830
PB
10402 tmp = load_reg(s, rn);
10403 gen_bx(s, tmp);
9ee6e8bb
PB
10404 break;
10405 case 5: /* Exception return. */
b8b45b68
RV
10406 if (IS_USER(s)) {
10407 goto illegal_op;
10408 }
10409 if (rn != 14 || rd != 15) {
10410 goto illegal_op;
10411 }
10412 tmp = load_reg(s, rn);
10413 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
10414 gen_exception_return(s, tmp);
10415 break;
8bfd0550
PM
10416 case 6: /* MRS */
10417 if (extract32(insn, 5, 1)) {
10418 /* MRS (banked) */
10419 int sysm = extract32(insn, 16, 4) |
10420 (extract32(insn, 4, 1) << 4);
10421
10422 gen_mrs_banked(s, 0, sysm, rd);
10423 break;
10424 }
10425
10426 /* mrs cpsr */
7d1b0095 10427 tmp = tcg_temp_new_i32();
b53d8923 10428 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e
PB
10429 addr = tcg_const_i32(insn & 0xff);
10430 gen_helper_v7m_mrs(tmp, cpu_env, addr);
b75263d6 10431 tcg_temp_free_i32(addr);
9ee6e8bb 10432 } else {
9ef39277 10433 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 10434 }
8984bd2e 10435 store_reg(s, rd, tmp);
9ee6e8bb 10436 break;
8bfd0550
PM
10437 case 7: /* MRS */
10438 if (extract32(insn, 5, 1)) {
10439 /* MRS (banked) */
10440 int sysm = extract32(insn, 16, 4) |
10441 (extract32(insn, 4, 1) << 4);
10442
10443 gen_mrs_banked(s, 1, sysm, rd);
10444 break;
10445 }
10446
10447 /* mrs spsr. */
9ee6e8bb 10448 /* Not accessible in user mode. */
b53d8923 10449 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10450 goto illegal_op;
b53d8923 10451 }
d9ba4830
PB
10452 tmp = load_cpu_field(spsr);
10453 store_reg(s, rd, tmp);
9ee6e8bb 10454 break;
2c0262af
FB
10455 }
10456 }
9ee6e8bb
PB
10457 } else {
10458 /* Conditional branch. */
10459 op = (insn >> 22) & 0xf;
10460 /* Generate a conditional jump to next instruction. */
10461 s->condlabel = gen_new_label();
39fb730a 10462 arm_gen_test_cc(op ^ 1, s->condlabel);
9ee6e8bb
PB
10463 s->condjmp = 1;
10464
10465 /* offset[11:1] = insn[10:0] */
10466 offset = (insn & 0x7ff) << 1;
10467 /* offset[17:12] = insn[21:16]. */
10468 offset |= (insn & 0x003f0000) >> 4;
10469 /* offset[31:20] = insn[26]. */
10470 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
10471 /* offset[18] = insn[13]. */
10472 offset |= (insn & (1 << 13)) << 5;
10473 /* offset[19] = insn[11]. */
10474 offset |= (insn & (1 << 11)) << 8;
10475
10476 /* jump to the offset */
b0109805 10477 gen_jmp(s, s->pc + offset);
9ee6e8bb
PB
10478 }
10479 } else {
10480 /* Data processing immediate. */
10481 if (insn & (1 << 25)) {
10482 if (insn & (1 << 24)) {
10483 if (insn & (1 << 20))
10484 goto illegal_op;
10485 /* Bitfield/Saturate. */
10486 op = (insn >> 21) & 7;
10487 imm = insn & 0x1f;
10488 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6ddbc6e4 10489 if (rn == 15) {
7d1b0095 10490 tmp = tcg_temp_new_i32();
6ddbc6e4
PB
10491 tcg_gen_movi_i32(tmp, 0);
10492 } else {
10493 tmp = load_reg(s, rn);
10494 }
9ee6e8bb
PB
10495 switch (op) {
10496 case 2: /* Signed bitfield extract. */
10497 imm++;
10498 if (shift + imm > 32)
10499 goto illegal_op;
10500 if (imm < 32)
6ddbc6e4 10501 gen_sbfx(tmp, shift, imm);
9ee6e8bb
PB
10502 break;
10503 case 6: /* Unsigned bitfield extract. */
10504 imm++;
10505 if (shift + imm > 32)
10506 goto illegal_op;
10507 if (imm < 32)
6ddbc6e4 10508 gen_ubfx(tmp, shift, (1u << imm) - 1);
9ee6e8bb
PB
10509 break;
10510 case 3: /* Bitfield insert/clear. */
10511 if (imm < shift)
10512 goto illegal_op;
10513 imm = imm + 1 - shift;
10514 if (imm != 32) {
6ddbc6e4 10515 tmp2 = load_reg(s, rd);
d593c48e 10516 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
7d1b0095 10517 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10518 }
10519 break;
10520 case 7:
10521 goto illegal_op;
10522 default: /* Saturate. */
9ee6e8bb
PB
10523 if (shift) {
10524 if (op & 1)
6ddbc6e4 10525 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 10526 else
6ddbc6e4 10527 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb 10528 }
6ddbc6e4 10529 tmp2 = tcg_const_i32(imm);
9ee6e8bb
PB
10530 if (op & 4) {
10531 /* Unsigned. */
62b44f05
AR
10532 if ((op & 1) && shift == 0) {
10533 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10534 tcg_temp_free_i32(tmp);
10535 tcg_temp_free_i32(tmp2);
10536 goto illegal_op;
10537 }
9ef39277 10538 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
62b44f05 10539 } else {
9ef39277 10540 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
62b44f05 10541 }
2c0262af 10542 } else {
9ee6e8bb 10543 /* Signed. */
62b44f05
AR
10544 if ((op & 1) && shift == 0) {
10545 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10546 tcg_temp_free_i32(tmp);
10547 tcg_temp_free_i32(tmp2);
10548 goto illegal_op;
10549 }
9ef39277 10550 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
62b44f05 10551 } else {
9ef39277 10552 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
62b44f05 10553 }
2c0262af 10554 }
b75263d6 10555 tcg_temp_free_i32(tmp2);
9ee6e8bb 10556 break;
2c0262af 10557 }
6ddbc6e4 10558 store_reg(s, rd, tmp);
9ee6e8bb
PB
10559 } else {
10560 imm = ((insn & 0x04000000) >> 15)
10561 | ((insn & 0x7000) >> 4) | (insn & 0xff);
10562 if (insn & (1 << 22)) {
10563 /* 16-bit immediate. */
10564 imm |= (insn >> 4) & 0xf000;
10565 if (insn & (1 << 23)) {
10566 /* movt */
5e3f878a 10567 tmp = load_reg(s, rd);
86831435 10568 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 10569 tcg_gen_ori_i32(tmp, tmp, imm << 16);
2c0262af 10570 } else {
9ee6e8bb 10571 /* movw */
7d1b0095 10572 tmp = tcg_temp_new_i32();
5e3f878a 10573 tcg_gen_movi_i32(tmp, imm);
2c0262af
FB
10574 }
10575 } else {
9ee6e8bb
PB
10576 /* Add/sub 12-bit immediate. */
10577 if (rn == 15) {
b0109805 10578 offset = s->pc & ~(uint32_t)3;
9ee6e8bb 10579 if (insn & (1 << 23))
b0109805 10580 offset -= imm;
9ee6e8bb 10581 else
b0109805 10582 offset += imm;
7d1b0095 10583 tmp = tcg_temp_new_i32();
5e3f878a 10584 tcg_gen_movi_i32(tmp, offset);
2c0262af 10585 } else {
5e3f878a 10586 tmp = load_reg(s, rn);
9ee6e8bb 10587 if (insn & (1 << 23))
5e3f878a 10588 tcg_gen_subi_i32(tmp, tmp, imm);
9ee6e8bb 10589 else
5e3f878a 10590 tcg_gen_addi_i32(tmp, tmp, imm);
2c0262af 10591 }
9ee6e8bb 10592 }
5e3f878a 10593 store_reg(s, rd, tmp);
191abaa2 10594 }
9ee6e8bb
PB
10595 } else {
10596 int shifter_out = 0;
10597 /* modified 12-bit immediate. */
10598 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
10599 imm = (insn & 0xff);
10600 switch (shift) {
10601 case 0: /* XY */
10602 /* Nothing to do. */
10603 break;
10604 case 1: /* 00XY00XY */
10605 imm |= imm << 16;
10606 break;
10607 case 2: /* XY00XY00 */
10608 imm |= imm << 16;
10609 imm <<= 8;
10610 break;
10611 case 3: /* XYXYXYXY */
10612 imm |= imm << 16;
10613 imm |= imm << 8;
10614 break;
10615 default: /* Rotated constant. */
10616 shift = (shift << 1) | (imm >> 7);
10617 imm |= 0x80;
10618 imm = imm << (32 - shift);
10619 shifter_out = 1;
10620 break;
b5ff1b31 10621 }
7d1b0095 10622 tmp2 = tcg_temp_new_i32();
3174f8e9 10623 tcg_gen_movi_i32(tmp2, imm);
9ee6e8bb 10624 rn = (insn >> 16) & 0xf;
3174f8e9 10625 if (rn == 15) {
7d1b0095 10626 tmp = tcg_temp_new_i32();
3174f8e9
FN
10627 tcg_gen_movi_i32(tmp, 0);
10628 } else {
10629 tmp = load_reg(s, rn);
10630 }
9ee6e8bb
PB
10631 op = (insn >> 21) & 0xf;
10632 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
3174f8e9 10633 shifter_out, tmp, tmp2))
9ee6e8bb 10634 goto illegal_op;
7d1b0095 10635 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10636 rd = (insn >> 8) & 0xf;
10637 if (rd != 15) {
3174f8e9
FN
10638 store_reg(s, rd, tmp);
10639 } else {
7d1b0095 10640 tcg_temp_free_i32(tmp);
2c0262af 10641 }
2c0262af 10642 }
9ee6e8bb
PB
10643 }
10644 break;
10645 case 12: /* Load/store single data item. */
10646 {
10647 int postinc = 0;
10648 int writeback = 0;
a99caa48 10649 int memidx;
9ee6e8bb 10650 if ((insn & 0x01100000) == 0x01000000) {
7dcc1f89 10651 if (disas_neon_ls_insn(s, insn)) {
c1713132 10652 goto illegal_op;
7dcc1f89 10653 }
9ee6e8bb
PB
10654 break;
10655 }
a2fdc890
PM
10656 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
10657 if (rs == 15) {
10658 if (!(insn & (1 << 20))) {
10659 goto illegal_op;
10660 }
10661 if (op != 2) {
10662 /* Byte or halfword load space with dest == r15 : memory hints.
10663 * Catch them early so we don't emit pointless addressing code.
10664 * This space is a mix of:
10665 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
10666 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
10667 * cores)
10668 * unallocated hints, which must be treated as NOPs
10669 * UNPREDICTABLE space, which we NOP or UNDEF depending on
10670 * which is easiest for the decoding logic
10671 * Some space which must UNDEF
10672 */
10673 int op1 = (insn >> 23) & 3;
10674 int op2 = (insn >> 6) & 0x3f;
10675 if (op & 2) {
10676 goto illegal_op;
10677 }
10678 if (rn == 15) {
02afbf64
PM
10679 /* UNPREDICTABLE, unallocated hint or
10680 * PLD/PLDW/PLI (literal)
10681 */
a2fdc890
PM
10682 return 0;
10683 }
10684 if (op1 & 1) {
02afbf64 10685 return 0; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
10686 }
10687 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
02afbf64 10688 return 0; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
10689 }
10690 /* UNDEF space, or an UNPREDICTABLE */
10691 return 1;
10692 }
10693 }
a99caa48 10694 memidx = get_mem_index(s);
9ee6e8bb 10695 if (rn == 15) {
7d1b0095 10696 addr = tcg_temp_new_i32();
9ee6e8bb
PB
10697 /* PC relative. */
10698 /* s->pc has already been incremented by 4. */
10699 imm = s->pc & 0xfffffffc;
10700 if (insn & (1 << 23))
10701 imm += insn & 0xfff;
10702 else
10703 imm -= insn & 0xfff;
b0109805 10704 tcg_gen_movi_i32(addr, imm);
9ee6e8bb 10705 } else {
b0109805 10706 addr = load_reg(s, rn);
9ee6e8bb
PB
10707 if (insn & (1 << 23)) {
10708 /* Positive offset. */
10709 imm = insn & 0xfff;
b0109805 10710 tcg_gen_addi_i32(addr, addr, imm);
9ee6e8bb 10711 } else {
9ee6e8bb 10712 imm = insn & 0xff;
2a0308c5
PM
10713 switch ((insn >> 8) & 0xf) {
10714 case 0x0: /* Shifted Register. */
9ee6e8bb 10715 shift = (insn >> 4) & 0xf;
2a0308c5
PM
10716 if (shift > 3) {
10717 tcg_temp_free_i32(addr);
18c9b560 10718 goto illegal_op;
2a0308c5 10719 }
b26eefb6 10720 tmp = load_reg(s, rm);
9ee6e8bb 10721 if (shift)
b26eefb6 10722 tcg_gen_shli_i32(tmp, tmp, shift);
b0109805 10723 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 10724 tcg_temp_free_i32(tmp);
9ee6e8bb 10725 break;
2a0308c5 10726 case 0xc: /* Negative offset. */
b0109805 10727 tcg_gen_addi_i32(addr, addr, -imm);
9ee6e8bb 10728 break;
2a0308c5 10729 case 0xe: /* User privilege. */
b0109805 10730 tcg_gen_addi_i32(addr, addr, imm);
579d21cc 10731 memidx = get_a32_user_mem_index(s);
9ee6e8bb 10732 break;
2a0308c5 10733 case 0x9: /* Post-decrement. */
9ee6e8bb
PB
10734 imm = -imm;
10735 /* Fall through. */
2a0308c5 10736 case 0xb: /* Post-increment. */
9ee6e8bb
PB
10737 postinc = 1;
10738 writeback = 1;
10739 break;
2a0308c5 10740 case 0xd: /* Pre-decrement. */
9ee6e8bb
PB
10741 imm = -imm;
10742 /* Fall through. */
2a0308c5 10743 case 0xf: /* Pre-increment. */
b0109805 10744 tcg_gen_addi_i32(addr, addr, imm);
9ee6e8bb
PB
10745 writeback = 1;
10746 break;
10747 default:
2a0308c5 10748 tcg_temp_free_i32(addr);
b7bcbe95 10749 goto illegal_op;
9ee6e8bb
PB
10750 }
10751 }
10752 }
9ee6e8bb
PB
10753 if (insn & (1 << 20)) {
10754 /* Load. */
5a839c0d 10755 tmp = tcg_temp_new_i32();
a2fdc890 10756 switch (op) {
5a839c0d 10757 case 0:
12dcc321 10758 gen_aa32_ld8u(s, tmp, addr, memidx);
5a839c0d
PM
10759 break;
10760 case 4:
12dcc321 10761 gen_aa32_ld8s(s, tmp, addr, memidx);
5a839c0d
PM
10762 break;
10763 case 1:
12dcc321 10764 gen_aa32_ld16u(s, tmp, addr, memidx);
5a839c0d
PM
10765 break;
10766 case 5:
12dcc321 10767 gen_aa32_ld16s(s, tmp, addr, memidx);
5a839c0d
PM
10768 break;
10769 case 2:
12dcc321 10770 gen_aa32_ld32u(s, tmp, addr, memidx);
5a839c0d 10771 break;
2a0308c5 10772 default:
5a839c0d 10773 tcg_temp_free_i32(tmp);
2a0308c5
PM
10774 tcg_temp_free_i32(addr);
10775 goto illegal_op;
a2fdc890
PM
10776 }
10777 if (rs == 15) {
10778 gen_bx(s, tmp);
9ee6e8bb 10779 } else {
a2fdc890 10780 store_reg(s, rs, tmp);
9ee6e8bb
PB
10781 }
10782 } else {
10783 /* Store. */
b0109805 10784 tmp = load_reg(s, rs);
9ee6e8bb 10785 switch (op) {
5a839c0d 10786 case 0:
12dcc321 10787 gen_aa32_st8(s, tmp, addr, memidx);
5a839c0d
PM
10788 break;
10789 case 1:
12dcc321 10790 gen_aa32_st16(s, tmp, addr, memidx);
5a839c0d
PM
10791 break;
10792 case 2:
12dcc321 10793 gen_aa32_st32(s, tmp, addr, memidx);
5a839c0d 10794 break;
2a0308c5 10795 default:
5a839c0d 10796 tcg_temp_free_i32(tmp);
2a0308c5
PM
10797 tcg_temp_free_i32(addr);
10798 goto illegal_op;
b7bcbe95 10799 }
5a839c0d 10800 tcg_temp_free_i32(tmp);
2c0262af 10801 }
9ee6e8bb 10802 if (postinc)
b0109805
PB
10803 tcg_gen_addi_i32(addr, addr, imm);
10804 if (writeback) {
10805 store_reg(s, rn, addr);
10806 } else {
7d1b0095 10807 tcg_temp_free_i32(addr);
b0109805 10808 }
9ee6e8bb
PB
10809 }
10810 break;
10811 default:
10812 goto illegal_op;
2c0262af 10813 }
9ee6e8bb
PB
10814 return 0;
10815illegal_op:
10816 return 1;
2c0262af
FB
10817}
10818
0ecb72a5 10819static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
99c475ab
FB
10820{
10821 uint32_t val, insn, op, rm, rn, rd, shift, cond;
10822 int32_t offset;
10823 int i;
39d5492a
PM
10824 TCGv_i32 tmp;
10825 TCGv_i32 tmp2;
10826 TCGv_i32 addr;
99c475ab 10827
9ee6e8bb
PB
10828 if (s->condexec_mask) {
10829 cond = s->condexec_cond;
bedd2912
JB
10830 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
10831 s->condlabel = gen_new_label();
39fb730a 10832 arm_gen_test_cc(cond ^ 1, s->condlabel);
bedd2912
JB
10833 s->condjmp = 1;
10834 }
9ee6e8bb
PB
10835 }
10836
f9fd40eb 10837 insn = arm_lduw_code(env, s->pc, s->sctlr_b);
99c475ab 10838 s->pc += 2;
b5ff1b31 10839
99c475ab
FB
10840 switch (insn >> 12) {
10841 case 0: case 1:
396e467c 10842
99c475ab
FB
10843 rd = insn & 7;
10844 op = (insn >> 11) & 3;
10845 if (op == 3) {
10846 /* add/subtract */
10847 rn = (insn >> 3) & 7;
396e467c 10848 tmp = load_reg(s, rn);
99c475ab
FB
10849 if (insn & (1 << 10)) {
10850 /* immediate */
7d1b0095 10851 tmp2 = tcg_temp_new_i32();
396e467c 10852 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
99c475ab
FB
10853 } else {
10854 /* reg */
10855 rm = (insn >> 6) & 7;
396e467c 10856 tmp2 = load_reg(s, rm);
99c475ab 10857 }
9ee6e8bb
PB
10858 if (insn & (1 << 9)) {
10859 if (s->condexec_mask)
396e467c 10860 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 10861 else
72485ec4 10862 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb
PB
10863 } else {
10864 if (s->condexec_mask)
396e467c 10865 tcg_gen_add_i32(tmp, tmp, tmp2);
9ee6e8bb 10866 else
72485ec4 10867 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 10868 }
7d1b0095 10869 tcg_temp_free_i32(tmp2);
396e467c 10870 store_reg(s, rd, tmp);
99c475ab
FB
10871 } else {
10872 /* shift immediate */
10873 rm = (insn >> 3) & 7;
10874 shift = (insn >> 6) & 0x1f;
9a119ff6
PB
10875 tmp = load_reg(s, rm);
10876 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
10877 if (!s->condexec_mask)
10878 gen_logic_CC(tmp);
10879 store_reg(s, rd, tmp);
99c475ab
FB
10880 }
10881 break;
10882 case 2: case 3:
10883 /* arithmetic large immediate */
10884 op = (insn >> 11) & 3;
10885 rd = (insn >> 8) & 0x7;
396e467c 10886 if (op == 0) { /* mov */
7d1b0095 10887 tmp = tcg_temp_new_i32();
396e467c 10888 tcg_gen_movi_i32(tmp, insn & 0xff);
9ee6e8bb 10889 if (!s->condexec_mask)
396e467c
FN
10890 gen_logic_CC(tmp);
10891 store_reg(s, rd, tmp);
10892 } else {
10893 tmp = load_reg(s, rd);
7d1b0095 10894 tmp2 = tcg_temp_new_i32();
396e467c
FN
10895 tcg_gen_movi_i32(tmp2, insn & 0xff);
10896 switch (op) {
10897 case 1: /* cmp */
72485ec4 10898 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
10899 tcg_temp_free_i32(tmp);
10900 tcg_temp_free_i32(tmp2);
396e467c
FN
10901 break;
10902 case 2: /* add */
10903 if (s->condexec_mask)
10904 tcg_gen_add_i32(tmp, tmp, tmp2);
10905 else
72485ec4 10906 gen_add_CC(tmp, tmp, tmp2);
7d1b0095 10907 tcg_temp_free_i32(tmp2);
396e467c
FN
10908 store_reg(s, rd, tmp);
10909 break;
10910 case 3: /* sub */
10911 if (s->condexec_mask)
10912 tcg_gen_sub_i32(tmp, tmp, tmp2);
10913 else
72485ec4 10914 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095 10915 tcg_temp_free_i32(tmp2);
396e467c
FN
10916 store_reg(s, rd, tmp);
10917 break;
10918 }
99c475ab 10919 }
99c475ab
FB
10920 break;
10921 case 4:
10922 if (insn & (1 << 11)) {
10923 rd = (insn >> 8) & 7;
5899f386
FB
10924 /* load pc-relative. Bit 1 of PC is ignored. */
10925 val = s->pc + 2 + ((insn & 0xff) * 4);
10926 val &= ~(uint32_t)2;
7d1b0095 10927 addr = tcg_temp_new_i32();
b0109805 10928 tcg_gen_movi_i32(addr, val);
c40c8556 10929 tmp = tcg_temp_new_i32();
12dcc321 10930 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
7d1b0095 10931 tcg_temp_free_i32(addr);
b0109805 10932 store_reg(s, rd, tmp);
99c475ab
FB
10933 break;
10934 }
10935 if (insn & (1 << 10)) {
10936 /* data processing extended or blx */
10937 rd = (insn & 7) | ((insn >> 4) & 8);
10938 rm = (insn >> 3) & 0xf;
10939 op = (insn >> 8) & 3;
10940 switch (op) {
10941 case 0: /* add */
396e467c
FN
10942 tmp = load_reg(s, rd);
10943 tmp2 = load_reg(s, rm);
10944 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10945 tcg_temp_free_i32(tmp2);
396e467c 10946 store_reg(s, rd, tmp);
99c475ab
FB
10947 break;
10948 case 1: /* cmp */
396e467c
FN
10949 tmp = load_reg(s, rd);
10950 tmp2 = load_reg(s, rm);
72485ec4 10951 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
10952 tcg_temp_free_i32(tmp2);
10953 tcg_temp_free_i32(tmp);
99c475ab
FB
10954 break;
10955 case 2: /* mov/cpy */
396e467c
FN
10956 tmp = load_reg(s, rm);
10957 store_reg(s, rd, tmp);
99c475ab
FB
10958 break;
10959 case 3:/* branch [and link] exchange thumb register */
b0109805 10960 tmp = load_reg(s, rm);
99c475ab 10961 if (insn & (1 << 7)) {
be5e7a76 10962 ARCH(5);
99c475ab 10963 val = (uint32_t)s->pc | 1;
7d1b0095 10964 tmp2 = tcg_temp_new_i32();
b0109805
PB
10965 tcg_gen_movi_i32(tmp2, val);
10966 store_reg(s, 14, tmp2);
99c475ab 10967 }
be5e7a76 10968 /* already thumb, no need to check */
d9ba4830 10969 gen_bx(s, tmp);
99c475ab
FB
10970 break;
10971 }
10972 break;
10973 }
10974
10975 /* data processing register */
10976 rd = insn & 7;
10977 rm = (insn >> 3) & 7;
10978 op = (insn >> 6) & 0xf;
10979 if (op == 2 || op == 3 || op == 4 || op == 7) {
10980 /* the shift/rotate ops want the operands backwards */
10981 val = rm;
10982 rm = rd;
10983 rd = val;
10984 val = 1;
10985 } else {
10986 val = 0;
10987 }
10988
396e467c 10989 if (op == 9) { /* neg */
7d1b0095 10990 tmp = tcg_temp_new_i32();
396e467c
FN
10991 tcg_gen_movi_i32(tmp, 0);
10992 } else if (op != 0xf) { /* mvn doesn't read its first operand */
10993 tmp = load_reg(s, rd);
10994 } else {
39d5492a 10995 TCGV_UNUSED_I32(tmp);
396e467c 10996 }
99c475ab 10997
396e467c 10998 tmp2 = load_reg(s, rm);
5899f386 10999 switch (op) {
99c475ab 11000 case 0x0: /* and */
396e467c 11001 tcg_gen_and_i32(tmp, tmp, tmp2);
9ee6e8bb 11002 if (!s->condexec_mask)
396e467c 11003 gen_logic_CC(tmp);
99c475ab
FB
11004 break;
11005 case 0x1: /* eor */
396e467c 11006 tcg_gen_xor_i32(tmp, tmp, tmp2);
9ee6e8bb 11007 if (!s->condexec_mask)
396e467c 11008 gen_logic_CC(tmp);
99c475ab
FB
11009 break;
11010 case 0x2: /* lsl */
9ee6e8bb 11011 if (s->condexec_mask) {
365af80e 11012 gen_shl(tmp2, tmp2, tmp);
9ee6e8bb 11013 } else {
9ef39277 11014 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11015 gen_logic_CC(tmp2);
9ee6e8bb 11016 }
99c475ab
FB
11017 break;
11018 case 0x3: /* lsr */
9ee6e8bb 11019 if (s->condexec_mask) {
365af80e 11020 gen_shr(tmp2, tmp2, tmp);
9ee6e8bb 11021 } else {
9ef39277 11022 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11023 gen_logic_CC(tmp2);
9ee6e8bb 11024 }
99c475ab
FB
11025 break;
11026 case 0x4: /* asr */
9ee6e8bb 11027 if (s->condexec_mask) {
365af80e 11028 gen_sar(tmp2, tmp2, tmp);
9ee6e8bb 11029 } else {
9ef39277 11030 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11031 gen_logic_CC(tmp2);
9ee6e8bb 11032 }
99c475ab
FB
11033 break;
11034 case 0x5: /* adc */
49b4c31e 11035 if (s->condexec_mask) {
396e467c 11036 gen_adc(tmp, tmp2);
49b4c31e
RH
11037 } else {
11038 gen_adc_CC(tmp, tmp, tmp2);
11039 }
99c475ab
FB
11040 break;
11041 case 0x6: /* sbc */
2de68a49 11042 if (s->condexec_mask) {
396e467c 11043 gen_sub_carry(tmp, tmp, tmp2);
2de68a49
RH
11044 } else {
11045 gen_sbc_CC(tmp, tmp, tmp2);
11046 }
99c475ab
FB
11047 break;
11048 case 0x7: /* ror */
9ee6e8bb 11049 if (s->condexec_mask) {
f669df27
AJ
11050 tcg_gen_andi_i32(tmp, tmp, 0x1f);
11051 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9ee6e8bb 11052 } else {
9ef39277 11053 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11054 gen_logic_CC(tmp2);
9ee6e8bb 11055 }
99c475ab
FB
11056 break;
11057 case 0x8: /* tst */
396e467c
FN
11058 tcg_gen_and_i32(tmp, tmp, tmp2);
11059 gen_logic_CC(tmp);
99c475ab 11060 rd = 16;
5899f386 11061 break;
99c475ab 11062 case 0x9: /* neg */
9ee6e8bb 11063 if (s->condexec_mask)
396e467c 11064 tcg_gen_neg_i32(tmp, tmp2);
9ee6e8bb 11065 else
72485ec4 11066 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
11067 break;
11068 case 0xa: /* cmp */
72485ec4 11069 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
11070 rd = 16;
11071 break;
11072 case 0xb: /* cmn */
72485ec4 11073 gen_add_CC(tmp, tmp, tmp2);
99c475ab
FB
11074 rd = 16;
11075 break;
11076 case 0xc: /* orr */
396e467c 11077 tcg_gen_or_i32(tmp, tmp, tmp2);
9ee6e8bb 11078 if (!s->condexec_mask)
396e467c 11079 gen_logic_CC(tmp);
99c475ab
FB
11080 break;
11081 case 0xd: /* mul */
7b2919a0 11082 tcg_gen_mul_i32(tmp, tmp, tmp2);
9ee6e8bb 11083 if (!s->condexec_mask)
396e467c 11084 gen_logic_CC(tmp);
99c475ab
FB
11085 break;
11086 case 0xe: /* bic */
f669df27 11087 tcg_gen_andc_i32(tmp, tmp, tmp2);
9ee6e8bb 11088 if (!s->condexec_mask)
396e467c 11089 gen_logic_CC(tmp);
99c475ab
FB
11090 break;
11091 case 0xf: /* mvn */
396e467c 11092 tcg_gen_not_i32(tmp2, tmp2);
9ee6e8bb 11093 if (!s->condexec_mask)
396e467c 11094 gen_logic_CC(tmp2);
99c475ab 11095 val = 1;
5899f386 11096 rm = rd;
99c475ab
FB
11097 break;
11098 }
11099 if (rd != 16) {
396e467c
FN
11100 if (val) {
11101 store_reg(s, rm, tmp2);
11102 if (op != 0xf)
7d1b0095 11103 tcg_temp_free_i32(tmp);
396e467c
FN
11104 } else {
11105 store_reg(s, rd, tmp);
7d1b0095 11106 tcg_temp_free_i32(tmp2);
396e467c
FN
11107 }
11108 } else {
7d1b0095
PM
11109 tcg_temp_free_i32(tmp);
11110 tcg_temp_free_i32(tmp2);
99c475ab
FB
11111 }
11112 break;
11113
11114 case 5:
11115 /* load/store register offset. */
11116 rd = insn & 7;
11117 rn = (insn >> 3) & 7;
11118 rm = (insn >> 6) & 7;
11119 op = (insn >> 9) & 7;
b0109805 11120 addr = load_reg(s, rn);
b26eefb6 11121 tmp = load_reg(s, rm);
b0109805 11122 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 11123 tcg_temp_free_i32(tmp);
99c475ab 11124
c40c8556 11125 if (op < 3) { /* store */
b0109805 11126 tmp = load_reg(s, rd);
c40c8556
PM
11127 } else {
11128 tmp = tcg_temp_new_i32();
11129 }
99c475ab
FB
11130
11131 switch (op) {
11132 case 0: /* str */
12dcc321 11133 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11134 break;
11135 case 1: /* strh */
12dcc321 11136 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11137 break;
11138 case 2: /* strb */
12dcc321 11139 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11140 break;
11141 case 3: /* ldrsb */
12dcc321 11142 gen_aa32_ld8s(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11143 break;
11144 case 4: /* ldr */
12dcc321 11145 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11146 break;
11147 case 5: /* ldrh */
12dcc321 11148 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11149 break;
11150 case 6: /* ldrb */
12dcc321 11151 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11152 break;
11153 case 7: /* ldrsh */
12dcc321 11154 gen_aa32_ld16s(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11155 break;
11156 }
c40c8556 11157 if (op >= 3) { /* load */
b0109805 11158 store_reg(s, rd, tmp);
c40c8556
PM
11159 } else {
11160 tcg_temp_free_i32(tmp);
11161 }
7d1b0095 11162 tcg_temp_free_i32(addr);
99c475ab
FB
11163 break;
11164
11165 case 6:
11166 /* load/store word immediate offset */
11167 rd = insn & 7;
11168 rn = (insn >> 3) & 7;
b0109805 11169 addr = load_reg(s, rn);
99c475ab 11170 val = (insn >> 4) & 0x7c;
b0109805 11171 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11172
11173 if (insn & (1 << 11)) {
11174 /* load */
c40c8556 11175 tmp = tcg_temp_new_i32();
12dcc321 11176 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 11177 store_reg(s, rd, tmp);
99c475ab
FB
11178 } else {
11179 /* store */
b0109805 11180 tmp = load_reg(s, rd);
12dcc321 11181 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11182 tcg_temp_free_i32(tmp);
99c475ab 11183 }
7d1b0095 11184 tcg_temp_free_i32(addr);
99c475ab
FB
11185 break;
11186
11187 case 7:
11188 /* load/store byte immediate offset */
11189 rd = insn & 7;
11190 rn = (insn >> 3) & 7;
b0109805 11191 addr = load_reg(s, rn);
99c475ab 11192 val = (insn >> 6) & 0x1f;
b0109805 11193 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11194
11195 if (insn & (1 << 11)) {
11196 /* load */
c40c8556 11197 tmp = tcg_temp_new_i32();
12dcc321 11198 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
b0109805 11199 store_reg(s, rd, tmp);
99c475ab
FB
11200 } else {
11201 /* store */
b0109805 11202 tmp = load_reg(s, rd);
12dcc321 11203 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
c40c8556 11204 tcg_temp_free_i32(tmp);
99c475ab 11205 }
7d1b0095 11206 tcg_temp_free_i32(addr);
99c475ab
FB
11207 break;
11208
11209 case 8:
11210 /* load/store halfword immediate offset */
11211 rd = insn & 7;
11212 rn = (insn >> 3) & 7;
b0109805 11213 addr = load_reg(s, rn);
99c475ab 11214 val = (insn >> 5) & 0x3e;
b0109805 11215 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11216
11217 if (insn & (1 << 11)) {
11218 /* load */
c40c8556 11219 tmp = tcg_temp_new_i32();
12dcc321 11220 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
b0109805 11221 store_reg(s, rd, tmp);
99c475ab
FB
11222 } else {
11223 /* store */
b0109805 11224 tmp = load_reg(s, rd);
12dcc321 11225 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
c40c8556 11226 tcg_temp_free_i32(tmp);
99c475ab 11227 }
7d1b0095 11228 tcg_temp_free_i32(addr);
99c475ab
FB
11229 break;
11230
11231 case 9:
11232 /* load/store from stack */
11233 rd = (insn >> 8) & 7;
b0109805 11234 addr = load_reg(s, 13);
99c475ab 11235 val = (insn & 0xff) * 4;
b0109805 11236 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11237
11238 if (insn & (1 << 11)) {
11239 /* load */
c40c8556 11240 tmp = tcg_temp_new_i32();
12dcc321 11241 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 11242 store_reg(s, rd, tmp);
99c475ab
FB
11243 } else {
11244 /* store */
b0109805 11245 tmp = load_reg(s, rd);
12dcc321 11246 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11247 tcg_temp_free_i32(tmp);
99c475ab 11248 }
7d1b0095 11249 tcg_temp_free_i32(addr);
99c475ab
FB
11250 break;
11251
11252 case 10:
11253 /* add to high reg */
11254 rd = (insn >> 8) & 7;
5899f386
FB
11255 if (insn & (1 << 11)) {
11256 /* SP */
5e3f878a 11257 tmp = load_reg(s, 13);
5899f386
FB
11258 } else {
11259 /* PC. bit 1 is ignored. */
7d1b0095 11260 tmp = tcg_temp_new_i32();
5e3f878a 11261 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
5899f386 11262 }
99c475ab 11263 val = (insn & 0xff) * 4;
5e3f878a
PB
11264 tcg_gen_addi_i32(tmp, tmp, val);
11265 store_reg(s, rd, tmp);
99c475ab
FB
11266 break;
11267
11268 case 11:
11269 /* misc */
11270 op = (insn >> 8) & 0xf;
11271 switch (op) {
11272 case 0:
11273 /* adjust stack pointer */
b26eefb6 11274 tmp = load_reg(s, 13);
99c475ab
FB
11275 val = (insn & 0x7f) * 4;
11276 if (insn & (1 << 7))
6a0d8a1d 11277 val = -(int32_t)val;
b26eefb6
PB
11278 tcg_gen_addi_i32(tmp, tmp, val);
11279 store_reg(s, 13, tmp);
99c475ab
FB
11280 break;
11281
9ee6e8bb
PB
11282 case 2: /* sign/zero extend. */
11283 ARCH(6);
11284 rd = insn & 7;
11285 rm = (insn >> 3) & 7;
b0109805 11286 tmp = load_reg(s, rm);
9ee6e8bb 11287 switch ((insn >> 6) & 3) {
b0109805
PB
11288 case 0: gen_sxth(tmp); break;
11289 case 1: gen_sxtb(tmp); break;
11290 case 2: gen_uxth(tmp); break;
11291 case 3: gen_uxtb(tmp); break;
9ee6e8bb 11292 }
b0109805 11293 store_reg(s, rd, tmp);
9ee6e8bb 11294 break;
99c475ab
FB
11295 case 4: case 5: case 0xc: case 0xd:
11296 /* push/pop */
b0109805 11297 addr = load_reg(s, 13);
5899f386
FB
11298 if (insn & (1 << 8))
11299 offset = 4;
99c475ab 11300 else
5899f386
FB
11301 offset = 0;
11302 for (i = 0; i < 8; i++) {
11303 if (insn & (1 << i))
11304 offset += 4;
11305 }
11306 if ((insn & (1 << 11)) == 0) {
b0109805 11307 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 11308 }
99c475ab
FB
11309 for (i = 0; i < 8; i++) {
11310 if (insn & (1 << i)) {
11311 if (insn & (1 << 11)) {
11312 /* pop */
c40c8556 11313 tmp = tcg_temp_new_i32();
12dcc321 11314 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 11315 store_reg(s, i, tmp);
99c475ab
FB
11316 } else {
11317 /* push */
b0109805 11318 tmp = load_reg(s, i);
12dcc321 11319 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11320 tcg_temp_free_i32(tmp);
99c475ab 11321 }
5899f386 11322 /* advance to the next address. */
b0109805 11323 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
11324 }
11325 }
39d5492a 11326 TCGV_UNUSED_I32(tmp);
99c475ab
FB
11327 if (insn & (1 << 8)) {
11328 if (insn & (1 << 11)) {
11329 /* pop pc */
c40c8556 11330 tmp = tcg_temp_new_i32();
12dcc321 11331 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11332 /* don't set the pc until the rest of the instruction
11333 has completed */
11334 } else {
11335 /* push lr */
b0109805 11336 tmp = load_reg(s, 14);
12dcc321 11337 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11338 tcg_temp_free_i32(tmp);
99c475ab 11339 }
b0109805 11340 tcg_gen_addi_i32(addr, addr, 4);
99c475ab 11341 }
5899f386 11342 if ((insn & (1 << 11)) == 0) {
b0109805 11343 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 11344 }
99c475ab 11345 /* write back the new stack pointer */
b0109805 11346 store_reg(s, 13, addr);
99c475ab 11347 /* set the new PC value */
be5e7a76 11348 if ((insn & 0x0900) == 0x0900) {
7dcc1f89 11349 store_reg_from_load(s, 15, tmp);
be5e7a76 11350 }
99c475ab
FB
11351 break;
11352
9ee6e8bb
PB
11353 case 1: case 3: case 9: case 11: /* czb */
11354 rm = insn & 7;
d9ba4830 11355 tmp = load_reg(s, rm);
9ee6e8bb
PB
11356 s->condlabel = gen_new_label();
11357 s->condjmp = 1;
11358 if (insn & (1 << 11))
cb63669a 11359 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9ee6e8bb 11360 else
cb63669a 11361 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
7d1b0095 11362 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
11363 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
11364 val = (uint32_t)s->pc + 2;
11365 val += offset;
11366 gen_jmp(s, val);
11367 break;
11368
11369 case 15: /* IT, nop-hint. */
11370 if ((insn & 0xf) == 0) {
11371 gen_nop_hint(s, (insn >> 4) & 0xf);
11372 break;
11373 }
11374 /* If Then. */
11375 s->condexec_cond = (insn >> 4) & 0xe;
11376 s->condexec_mask = insn & 0x1f;
11377 /* No actual code generated for this insn, just setup state. */
11378 break;
11379
06c949e6 11380 case 0xe: /* bkpt */
d4a2dc67
PM
11381 {
11382 int imm8 = extract32(insn, 0, 8);
be5e7a76 11383 ARCH(5);
73710361
GB
11384 gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true),
11385 default_exception_el(s));
06c949e6 11386 break;
d4a2dc67 11387 }
06c949e6 11388
19a6e31c
PM
11389 case 0xa: /* rev, and hlt */
11390 {
11391 int op1 = extract32(insn, 6, 2);
11392
11393 if (op1 == 2) {
11394 /* HLT */
11395 int imm6 = extract32(insn, 0, 6);
11396
11397 gen_hlt(s, imm6);
11398 break;
11399 }
11400
11401 /* Otherwise this is rev */
9ee6e8bb
PB
11402 ARCH(6);
11403 rn = (insn >> 3) & 0x7;
11404 rd = insn & 0x7;
b0109805 11405 tmp = load_reg(s, rn);
19a6e31c 11406 switch (op1) {
66896cb8 11407 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
b0109805
PB
11408 case 1: gen_rev16(tmp); break;
11409 case 3: gen_revsh(tmp); break;
19a6e31c
PM
11410 default:
11411 g_assert_not_reached();
9ee6e8bb 11412 }
b0109805 11413 store_reg(s, rd, tmp);
9ee6e8bb 11414 break;
19a6e31c 11415 }
9ee6e8bb 11416
d9e028c1
PM
11417 case 6:
11418 switch ((insn >> 5) & 7) {
11419 case 2:
11420 /* setend */
11421 ARCH(6);
9886ecdf
PB
11422 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
11423 gen_helper_setend(cpu_env);
11424 s->is_jmp = DISAS_UPDATE;
d9e028c1 11425 }
9ee6e8bb 11426 break;
d9e028c1
PM
11427 case 3:
11428 /* cps */
11429 ARCH(6);
11430 if (IS_USER(s)) {
11431 break;
8984bd2e 11432 }
b53d8923 11433 if (arm_dc_feature(s, ARM_FEATURE_M)) {
d9e028c1
PM
11434 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
11435 /* FAULTMASK */
11436 if (insn & 1) {
11437 addr = tcg_const_i32(19);
11438 gen_helper_v7m_msr(cpu_env, addr, tmp);
11439 tcg_temp_free_i32(addr);
11440 }
11441 /* PRIMASK */
11442 if (insn & 2) {
11443 addr = tcg_const_i32(16);
11444 gen_helper_v7m_msr(cpu_env, addr, tmp);
11445 tcg_temp_free_i32(addr);
11446 }
11447 tcg_temp_free_i32(tmp);
11448 gen_lookup_tb(s);
11449 } else {
11450 if (insn & (1 << 4)) {
11451 shift = CPSR_A | CPSR_I | CPSR_F;
11452 } else {
11453 shift = 0;
11454 }
11455 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8984bd2e 11456 }
d9e028c1
PM
11457 break;
11458 default:
11459 goto undef;
9ee6e8bb
PB
11460 }
11461 break;
11462
99c475ab
FB
11463 default:
11464 goto undef;
11465 }
11466 break;
11467
11468 case 12:
a7d3970d 11469 {
99c475ab 11470 /* load/store multiple */
39d5492a
PM
11471 TCGv_i32 loaded_var;
11472 TCGV_UNUSED_I32(loaded_var);
99c475ab 11473 rn = (insn >> 8) & 0x7;
b0109805 11474 addr = load_reg(s, rn);
99c475ab
FB
11475 for (i = 0; i < 8; i++) {
11476 if (insn & (1 << i)) {
99c475ab
FB
11477 if (insn & (1 << 11)) {
11478 /* load */
c40c8556 11479 tmp = tcg_temp_new_i32();
12dcc321 11480 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
a7d3970d
PM
11481 if (i == rn) {
11482 loaded_var = tmp;
11483 } else {
11484 store_reg(s, i, tmp);
11485 }
99c475ab
FB
11486 } else {
11487 /* store */
b0109805 11488 tmp = load_reg(s, i);
12dcc321 11489 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11490 tcg_temp_free_i32(tmp);
99c475ab 11491 }
5899f386 11492 /* advance to the next address */
b0109805 11493 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
11494 }
11495 }
b0109805 11496 if ((insn & (1 << rn)) == 0) {
a7d3970d 11497 /* base reg not in list: base register writeback */
b0109805
PB
11498 store_reg(s, rn, addr);
11499 } else {
a7d3970d
PM
11500 /* base reg in list: if load, complete it now */
11501 if (insn & (1 << 11)) {
11502 store_reg(s, rn, loaded_var);
11503 }
7d1b0095 11504 tcg_temp_free_i32(addr);
b0109805 11505 }
99c475ab 11506 break;
a7d3970d 11507 }
99c475ab
FB
11508 case 13:
11509 /* conditional branch or swi */
11510 cond = (insn >> 8) & 0xf;
11511 if (cond == 0xe)
11512 goto undef;
11513
11514 if (cond == 0xf) {
11515 /* swi */
eaed129d 11516 gen_set_pc_im(s, s->pc);
d4a2dc67 11517 s->svc_imm = extract32(insn, 0, 8);
9ee6e8bb 11518 s->is_jmp = DISAS_SWI;
99c475ab
FB
11519 break;
11520 }
11521 /* generate a conditional jump to next instruction */
e50e6a20 11522 s->condlabel = gen_new_label();
39fb730a 11523 arm_gen_test_cc(cond ^ 1, s->condlabel);
e50e6a20 11524 s->condjmp = 1;
99c475ab
FB
11525
11526 /* jump to the offset */
5899f386 11527 val = (uint32_t)s->pc + 2;
99c475ab 11528 offset = ((int32_t)insn << 24) >> 24;
5899f386 11529 val += offset << 1;
8aaca4c0 11530 gen_jmp(s, val);
99c475ab
FB
11531 break;
11532
11533 case 14:
358bf29e 11534 if (insn & (1 << 11)) {
9ee6e8bb
PB
11535 if (disas_thumb2_insn(env, s, insn))
11536 goto undef32;
358bf29e
PB
11537 break;
11538 }
9ee6e8bb 11539 /* unconditional branch */
99c475ab
FB
11540 val = (uint32_t)s->pc;
11541 offset = ((int32_t)insn << 21) >> 21;
11542 val += (offset << 1) + 2;
8aaca4c0 11543 gen_jmp(s, val);
99c475ab
FB
11544 break;
11545
11546 case 15:
9ee6e8bb 11547 if (disas_thumb2_insn(env, s, insn))
6a0d8a1d 11548 goto undef32;
9ee6e8bb 11549 break;
99c475ab
FB
11550 }
11551 return;
9ee6e8bb 11552undef32:
73710361
GB
11553 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
11554 default_exception_el(s));
9ee6e8bb
PB
11555 return;
11556illegal_op:
99c475ab 11557undef:
73710361
GB
11558 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
11559 default_exception_el(s));
99c475ab
FB
11560}
11561
541ebcd4
PM
11562static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
11563{
11564 /* Return true if the insn at dc->pc might cross a page boundary.
11565 * (False positives are OK, false negatives are not.)
11566 */
11567 uint16_t insn;
11568
11569 if ((s->pc & 3) == 0) {
11570 /* At a 4-aligned address we can't be crossing a page */
11571 return false;
11572 }
11573
11574 /* This must be a Thumb insn */
f9fd40eb 11575 insn = arm_lduw_code(env, s->pc, s->sctlr_b);
541ebcd4
PM
11576
11577 if ((insn >> 11) >= 0x1d) {
11578 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
11579 * First half of a 32-bit Thumb insn. Thumb-1 cores might
11580 * end up actually treating this as two 16-bit insns (see the
11581 * code at the start of disas_thumb2_insn()) but we don't bother
11582 * to check for that as it is unlikely, and false positives here
11583 * are harmless.
11584 */
11585 return true;
11586 }
11587 /* Definitely a 16-bit insn, can't be crossing a page. */
11588 return false;
11589}
11590
20157705 11591/* generate intermediate code for basic block 'tb'. */
4e5e1215 11592void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
2c0262af 11593{
4e5e1215 11594 ARMCPU *cpu = arm_env_get_cpu(env);
ed2803da 11595 CPUState *cs = CPU(cpu);
2c0262af 11596 DisasContext dc1, *dc = &dc1;
0fa85d43 11597 target_ulong pc_start;
0a2461fa 11598 target_ulong next_page_start;
2e70f6ef
PB
11599 int num_insns;
11600 int max_insns;
541ebcd4 11601 bool end_of_page;
3b46e624 11602
2c0262af 11603 /* generate intermediate code */
40f860cd
PM
11604
11605 /* The A64 decoder has its own top level loop, because it doesn't need
11606 * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
11607 */
11608 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
4e5e1215 11609 gen_intermediate_code_a64(cpu, tb);
40f860cd
PM
11610 return;
11611 }
11612
0fa85d43 11613 pc_start = tb->pc;
3b46e624 11614
2c0262af
FB
11615 dc->tb = tb;
11616
2c0262af
FB
11617 dc->is_jmp = DISAS_NEXT;
11618 dc->pc = pc_start;
ed2803da 11619 dc->singlestep_enabled = cs->singlestep_enabled;
e50e6a20 11620 dc->condjmp = 0;
3926cc84 11621
40f860cd 11622 dc->aarch64 = 0;
cef9ee70
SS
11623 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
11624 * there is no secure EL1, so we route exceptions to EL3.
11625 */
11626 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
11627 !arm_el_is_aa64(env, 3);
40f860cd 11628 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
f9fd40eb 11629 dc->sctlr_b = ARM_TBFLAG_SCTLR_B(tb->flags);
91cca2cd 11630 dc->be_data = ARM_TBFLAG_BE_DATA(tb->flags) ? MO_BE : MO_LE;
40f860cd
PM
11631 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
11632 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
c1e37810
PM
11633 dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
11634 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
3926cc84 11635#if !defined(CONFIG_USER_ONLY)
c1e37810 11636 dc->user = (dc->current_el == 0);
3926cc84 11637#endif
3f342b9e 11638 dc->ns = ARM_TBFLAG_NS(tb->flags);
9dbbc748 11639 dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(tb->flags);
40f860cd
PM
11640 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
11641 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
11642 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
c0f4af17 11643 dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
60322b39 11644 dc->cp_regs = cpu->cp_regs;
a984e42c 11645 dc->features = env->features;
40f860cd 11646
50225ad0
PM
11647 /* Single step state. The code-generation logic here is:
11648 * SS_ACTIVE == 0:
11649 * generate code with no special handling for single-stepping (except
11650 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
11651 * this happens anyway because those changes are all system register or
11652 * PSTATE writes).
11653 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
11654 * emit code for one insn
11655 * emit code to clear PSTATE.SS
11656 * emit code to generate software step exception for completed step
11657 * end TB (as usual for having generated an exception)
11658 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
11659 * emit code to generate a software step exception
11660 * end the TB
11661 */
11662 dc->ss_active = ARM_TBFLAG_SS_ACTIVE(tb->flags);
11663 dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(tb->flags);
11664 dc->is_ldex = false;
11665 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
11666
a7812ae4
PB
11667 cpu_F0s = tcg_temp_new_i32();
11668 cpu_F1s = tcg_temp_new_i32();
11669 cpu_F0d = tcg_temp_new_i64();
11670 cpu_F1d = tcg_temp_new_i64();
ad69471c
PB
11671 cpu_V0 = cpu_F0d;
11672 cpu_V1 = cpu_F1d;
e677137d 11673 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
a7812ae4 11674 cpu_M0 = tcg_temp_new_i64();
b5ff1b31 11675 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2e70f6ef
PB
11676 num_insns = 0;
11677 max_insns = tb->cflags & CF_COUNT_MASK;
190ce7fb 11678 if (max_insns == 0) {
2e70f6ef 11679 max_insns = CF_COUNT_MASK;
190ce7fb
RH
11680 }
11681 if (max_insns > TCG_MAX_INSNS) {
11682 max_insns = TCG_MAX_INSNS;
11683 }
2e70f6ef 11684
cd42d5b2 11685 gen_tb_start(tb);
e12ce78d 11686
3849902c
PM
11687 tcg_clear_temp_count();
11688
e12ce78d
PM
11689 /* A note on handling of the condexec (IT) bits:
11690 *
11691 * We want to avoid the overhead of having to write the updated condexec
0ecb72a5 11692 * bits back to the CPUARMState for every instruction in an IT block. So:
e12ce78d 11693 * (1) if the condexec bits are not already zero then we write
0ecb72a5 11694 * zero back into the CPUARMState now. This avoids complications trying
e12ce78d
PM
11695 * to do it at the end of the block. (For example if we don't do this
11696 * it's hard to identify whether we can safely skip writing condexec
11697 * at the end of the TB, which we definitely want to do for the case
11698 * where a TB doesn't do anything with the IT state at all.)
11699 * (2) if we are going to leave the TB then we call gen_set_condexec()
0ecb72a5 11700 * which will write the correct value into CPUARMState if zero is wrong.
e12ce78d
PM
11701 * This is done both for leaving the TB at the end, and for leaving
11702 * it because of an exception we know will happen, which is done in
11703 * gen_exception_insn(). The latter is necessary because we need to
11704 * leave the TB with the PC/IT state just prior to execution of the
11705 * instruction which caused the exception.
11706 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
0ecb72a5 11707 * then the CPUARMState will be wrong and we need to reset it.
e12ce78d 11708 * This is handled in the same way as restoration of the
4e5e1215
RH
11709 * PC in these situations; we save the value of the condexec bits
11710 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
11711 * then uses this to restore them after an exception.
e12ce78d
PM
11712 *
11713 * Note that there are no instructions which can read the condexec
11714 * bits, and none which can write non-static values to them, so
0ecb72a5 11715 * we don't need to care about whether CPUARMState is correct in the
e12ce78d
PM
11716 * middle of a TB.
11717 */
11718
9ee6e8bb
PB
11719 /* Reset the conditional execution bits immediately. This avoids
11720 complications trying to do it at the end of the block. */
98eac7ca 11721 if (dc->condexec_mask || dc->condexec_cond)
8f01245e 11722 {
39d5492a 11723 TCGv_i32 tmp = tcg_temp_new_i32();
8f01245e 11724 tcg_gen_movi_i32(tmp, 0);
d9ba4830 11725 store_cpu_field(tmp, condexec_bits);
8f01245e 11726 }
2c0262af 11727 do {
52e971d9 11728 tcg_gen_insn_start(dc->pc,
aaa1f954
EI
11729 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
11730 0);
b933066a
RH
11731 num_insns++;
11732
fbb4a2e3
PB
11733#ifdef CONFIG_USER_ONLY
11734 /* Intercept jump to the magic kernel page. */
40f860cd 11735 if (dc->pc >= 0xffff0000) {
fbb4a2e3
PB
11736 /* We always get here via a jump, so know we are not in a
11737 conditional execution block. */
d4a2dc67 11738 gen_exception_internal(EXCP_KERNEL_TRAP);
577bf808 11739 dc->is_jmp = DISAS_EXC;
fbb4a2e3
PB
11740 break;
11741 }
11742#else
b53d8923 11743 if (dc->pc >= 0xfffffff0 && arm_dc_feature(dc, ARM_FEATURE_M)) {
9ee6e8bb
PB
11744 /* We always get here via a jump, so know we are not in a
11745 conditional execution block. */
d4a2dc67 11746 gen_exception_internal(EXCP_EXCEPTION_EXIT);
577bf808 11747 dc->is_jmp = DISAS_EXC;
d60bb01c 11748 break;
9ee6e8bb
PB
11749 }
11750#endif
11751
f0c3c505 11752 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
b933066a 11753 CPUBreakpoint *bp;
f0c3c505 11754 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
a1d1bb31 11755 if (bp->pc == dc->pc) {
5d98bf8f 11756 if (bp->flags & BP_CPU) {
ce8a1b54 11757 gen_set_condexec(dc);
ed6c6448 11758 gen_set_pc_im(dc, dc->pc);
5d98bf8f
SF
11759 gen_helper_check_breakpoints(cpu_env);
11760 /* End the TB early; it's likely not going to be executed */
11761 dc->is_jmp = DISAS_UPDATE;
11762 } else {
11763 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
522a0d4e
RH
11764 /* The address covered by the breakpoint must be
11765 included in [tb->pc, tb->pc + tb->size) in order
11766 to for it to be properly cleared -- thus we
11767 increment the PC here so that the logic setting
11768 tb->size below does the right thing. */
5d98bf8f
SF
11769 /* TODO: Advance PC by correct instruction length to
11770 * avoid disassembler error messages */
11771 dc->pc += 2;
11772 goto done_generating;
11773 }
11774 break;
1fddef4b
FB
11775 }
11776 }
11777 }
e50e6a20 11778
959082fc 11779 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
2e70f6ef 11780 gen_io_start();
959082fc 11781 }
2e70f6ef 11782
50225ad0
PM
11783 if (dc->ss_active && !dc->pstate_ss) {
11784 /* Singlestep state is Active-pending.
11785 * If we're in this state at the start of a TB then either
11786 * a) we just took an exception to an EL which is being debugged
11787 * and this is the first insn in the exception handler
11788 * b) debug exceptions were masked and we just unmasked them
11789 * without changing EL (eg by clearing PSTATE.D)
11790 * In either case we're going to take a swstep exception in the
11791 * "did not step an insn" case, and so the syndrome ISV and EX
11792 * bits should be zero.
11793 */
959082fc 11794 assert(num_insns == 1);
73710361
GB
11795 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
11796 default_exception_el(dc));
50225ad0
PM
11797 goto done_generating;
11798 }
11799
40f860cd 11800 if (dc->thumb) {
9ee6e8bb
PB
11801 disas_thumb_insn(env, dc);
11802 if (dc->condexec_mask) {
11803 dc->condexec_cond = (dc->condexec_cond & 0xe)
11804 | ((dc->condexec_mask >> 4) & 1);
11805 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
11806 if (dc->condexec_mask == 0) {
11807 dc->condexec_cond = 0;
11808 }
11809 }
11810 } else {
f9fd40eb 11811 unsigned int insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
f4df2210
PM
11812 dc->pc += 4;
11813 disas_arm_insn(dc, insn);
9ee6e8bb 11814 }
e50e6a20
FB
11815
11816 if (dc->condjmp && !dc->is_jmp) {
11817 gen_set_label(dc->condlabel);
11818 dc->condjmp = 0;
11819 }
3849902c
PM
11820
11821 if (tcg_check_temp_count()) {
0a2461fa
AG
11822 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
11823 dc->pc);
3849902c
PM
11824 }
11825
aaf2d97d 11826 /* Translation stops when a conditional branch is encountered.
e50e6a20 11827 * Otherwise the subsequent code could get translated several times.
b5ff1b31 11828 * Also stop translation when a page boundary is reached. This
bf20dc07 11829 * ensures prefetch aborts occur at the right place. */
541ebcd4
PM
11830
11831 /* We want to stop the TB if the next insn starts in a new page,
11832 * or if it spans between this page and the next. This means that
11833 * if we're looking at the last halfword in the page we need to
11834 * see if it's a 16-bit Thumb insn (which will fit in this TB)
11835 * or a 32-bit Thumb insn (which won't).
11836 * This is to avoid generating a silly TB with a single 16-bit insn
11837 * in it at the end of this page (which would execute correctly
11838 * but isn't very efficient).
11839 */
11840 end_of_page = (dc->pc >= next_page_start) ||
11841 ((dc->pc >= next_page_start - 3) && insn_crosses_page(env, dc));
11842
fe700adb 11843 } while (!dc->is_jmp && !tcg_op_buf_full() &&
ed2803da 11844 !cs->singlestep_enabled &&
1b530a6d 11845 !singlestep &&
50225ad0 11846 !dc->ss_active &&
541ebcd4 11847 !end_of_page &&
2e70f6ef
PB
11848 num_insns < max_insns);
11849
11850 if (tb->cflags & CF_LAST_IO) {
11851 if (dc->condjmp) {
11852 /* FIXME: This can theoretically happen with self-modifying
11853 code. */
a47dddd7 11854 cpu_abort(cs, "IO on conditional branch instruction");
2e70f6ef
PB
11855 }
11856 gen_io_end();
11857 }
9ee6e8bb 11858
b5ff1b31 11859 /* At this stage dc->condjmp will only be set when the skipped
9ee6e8bb
PB
11860 instruction was a conditional branch or trap, and the PC has
11861 already been written. */
50225ad0 11862 if (unlikely(cs->singlestep_enabled || dc->ss_active)) {
7999a5c8 11863 /* Unconditional and "condition passed" instruction codepath. */
9ee6e8bb 11864 gen_set_condexec(dc);
7999a5c8
SF
11865 switch (dc->is_jmp) {
11866 case DISAS_SWI:
50225ad0 11867 gen_ss_advance(dc);
73710361
GB
11868 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
11869 default_exception_el(dc));
7999a5c8
SF
11870 break;
11871 case DISAS_HVC:
37e6456e 11872 gen_ss_advance(dc);
73710361 11873 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
7999a5c8
SF
11874 break;
11875 case DISAS_SMC:
37e6456e 11876 gen_ss_advance(dc);
73710361 11877 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
7999a5c8
SF
11878 break;
11879 case DISAS_NEXT:
11880 case DISAS_UPDATE:
11881 gen_set_pc_im(dc, dc->pc);
11882 /* fall through */
11883 default:
11884 if (dc->ss_active) {
11885 gen_step_complete_exception(dc);
11886 } else {
11887 /* FIXME: Single stepping a WFI insn will not halt
11888 the CPU. */
11889 gen_exception_internal(EXCP_DEBUG);
11890 }
11891 }
11892 if (dc->condjmp) {
11893 /* "Condition failed" instruction codepath. */
11894 gen_set_label(dc->condlabel);
11895 gen_set_condexec(dc);
11896 gen_set_pc_im(dc, dc->pc);
11897 if (dc->ss_active) {
11898 gen_step_complete_exception(dc);
11899 } else {
11900 gen_exception_internal(EXCP_DEBUG);
11901 }
9ee6e8bb 11902 }
8aaca4c0 11903 } else {
9ee6e8bb
PB
11904 /* While branches must always occur at the end of an IT block,
11905 there are a few other things that can cause us to terminate
65626741 11906 the TB in the middle of an IT block:
9ee6e8bb
PB
11907 - Exception generating instructions (bkpt, swi, undefined).
11908 - Page boundaries.
11909 - Hardware watchpoints.
11910 Hardware breakpoints have already been handled and skip this code.
11911 */
11912 gen_set_condexec(dc);
8aaca4c0 11913 switch(dc->is_jmp) {
8aaca4c0 11914 case DISAS_NEXT:
6e256c93 11915 gen_goto_tb(dc, 1, dc->pc);
8aaca4c0 11916 break;
8aaca4c0 11917 case DISAS_UPDATE:
577bf808
SF
11918 gen_set_pc_im(dc, dc->pc);
11919 /* fall through */
11920 case DISAS_JUMP:
11921 default:
8aaca4c0 11922 /* indicate that the hash table must be used to find the next TB */
57fec1fe 11923 tcg_gen_exit_tb(0);
8aaca4c0
FB
11924 break;
11925 case DISAS_TB_JUMP:
11926 /* nothing more to generate */
11927 break;
9ee6e8bb 11928 case DISAS_WFI:
1ce94f81 11929 gen_helper_wfi(cpu_env);
84549b6d
PM
11930 /* The helper doesn't necessarily throw an exception, but we
11931 * must go back to the main loop to check for interrupts anyway.
11932 */
11933 tcg_gen_exit_tb(0);
9ee6e8bb 11934 break;
72c1d3af
PM
11935 case DISAS_WFE:
11936 gen_helper_wfe(cpu_env);
11937 break;
c87e5a61
PM
11938 case DISAS_YIELD:
11939 gen_helper_yield(cpu_env);
11940 break;
9ee6e8bb 11941 case DISAS_SWI:
73710361
GB
11942 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
11943 default_exception_el(dc));
9ee6e8bb 11944 break;
37e6456e 11945 case DISAS_HVC:
73710361 11946 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
37e6456e
PM
11947 break;
11948 case DISAS_SMC:
73710361 11949 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
37e6456e 11950 break;
8aaca4c0 11951 }
e50e6a20
FB
11952 if (dc->condjmp) {
11953 gen_set_label(dc->condlabel);
9ee6e8bb 11954 gen_set_condexec(dc);
6e256c93 11955 gen_goto_tb(dc, 1, dc->pc);
e50e6a20
FB
11956 dc->condjmp = 0;
11957 }
2c0262af 11958 }
2e70f6ef 11959
9ee6e8bb 11960done_generating:
806f352d 11961 gen_tb_end(tb, num_insns);
2c0262af
FB
11962
11963#ifdef DEBUG_DISAS
06486077
AB
11964 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
11965 qemu_log_in_addr_range(pc_start)) {
1ee73216 11966 qemu_log_lock();
93fcfe39
AL
11967 qemu_log("----------------\n");
11968 qemu_log("IN: %s\n", lookup_symbol(pc_start));
d49190c4 11969 log_target_disas(cs, pc_start, dc->pc - pc_start,
f9fd40eb 11970 dc->thumb | (dc->sctlr_b << 1));
93fcfe39 11971 qemu_log("\n");
1ee73216 11972 qemu_log_unlock();
2c0262af
FB
11973 }
11974#endif
4e5e1215
RH
11975 tb->size = dc->pc - pc_start;
11976 tb->icount = num_insns;
2c0262af
FB
11977}
11978
b5ff1b31 11979static const char *cpu_mode_names[16] = {
28c9457d
EI
11980 "usr", "fiq", "irq", "svc", "???", "???", "mon", "abt",
11981 "???", "???", "hyp", "und", "???", "???", "???", "sys"
b5ff1b31 11982};
9ee6e8bb 11983
878096ee
AF
11984void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
11985 int flags)
2c0262af 11986{
878096ee
AF
11987 ARMCPU *cpu = ARM_CPU(cs);
11988 CPUARMState *env = &cpu->env;
2c0262af 11989 int i;
b5ff1b31 11990 uint32_t psr;
06e5cf7a 11991 const char *ns_status;
2c0262af 11992
17731115
PM
11993 if (is_a64(env)) {
11994 aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
11995 return;
11996 }
11997
2c0262af 11998 for(i=0;i<16;i++) {
7fe48483 11999 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2c0262af 12000 if ((i % 4) == 3)
7fe48483 12001 cpu_fprintf(f, "\n");
2c0262af 12002 else
7fe48483 12003 cpu_fprintf(f, " ");
2c0262af 12004 }
b5ff1b31 12005 psr = cpsr_read(env);
06e5cf7a
PM
12006
12007 if (arm_feature(env, ARM_FEATURE_EL3) &&
12008 (psr & CPSR_M) != ARM_CPU_MODE_MON) {
12009 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
12010 } else {
12011 ns_status = "";
12012 }
12013
12014 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
687fa640 12015 psr,
b5ff1b31
FB
12016 psr & (1 << 31) ? 'N' : '-',
12017 psr & (1 << 30) ? 'Z' : '-',
12018 psr & (1 << 29) ? 'C' : '-',
12019 psr & (1 << 28) ? 'V' : '-',
5fafdf24 12020 psr & CPSR_T ? 'T' : 'A',
06e5cf7a 12021 ns_status,
b5ff1b31 12022 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
b7bcbe95 12023
f2617cfc
PM
12024 if (flags & CPU_DUMP_FPU) {
12025 int numvfpregs = 0;
12026 if (arm_feature(env, ARM_FEATURE_VFP)) {
12027 numvfpregs += 16;
12028 }
12029 if (arm_feature(env, ARM_FEATURE_VFP3)) {
12030 numvfpregs += 16;
12031 }
12032 for (i = 0; i < numvfpregs; i++) {
12033 uint64_t v = float64_val(env->vfp.regs[i]);
12034 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
12035 i * 2, (uint32_t)v,
12036 i * 2 + 1, (uint32_t)(v >> 32),
12037 i, v);
12038 }
12039 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
b7bcbe95 12040 }
2c0262af 12041}
a6b025d3 12042
bad729e2
RH
12043void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
12044 target_ulong *data)
d2856f1a 12045{
3926cc84 12046 if (is_a64(env)) {
bad729e2 12047 env->pc = data[0];
40f860cd 12048 env->condexec_bits = 0;
aaa1f954 12049 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 12050 } else {
bad729e2
RH
12051 env->regs[15] = data[0];
12052 env->condexec_bits = data[1];
aaa1f954 12053 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 12054 }
d2856f1a 12055}